Java Code Examples for org.alfresco.service.cmr.repository.ContentReader#getSize()

The following examples show how to use org.alfresco.service.cmr.repository.ContentReader#getSize() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: AbstractContentTransformer2.java    From alfresco-repository with GNU Lesser General Public License v3.0 6 votes vote down vote up
/**
 * Convenience method to check the transformability of a transformation
 * 
 * @param reader    content reader
 * @param writer    content writer
 * @param options   transformation options
 * @throws AlfrescoRuntimeException if the the transformation isn't supported
 */
protected void checkTransformable(ContentReader reader, ContentWriter writer, TransformationOptions options)
{
    String sourceMimetype = getMimetype(reader);
    String targetMimetype = getMimetype(writer);
    long sourceSize = reader.getSize();
    boolean transformable = isTransformable(sourceMimetype, sourceSize, targetMimetype, options);
    if (transformable == false)
    {
        // This method is only called once a transformer has been selected, so it should be able to
        // handle the mimetypes but might not be able to handle all the limits as it might be part of
        // of a complex (compound) transformer. So report the max size if set.
        long maxSourceSizeKBytes = getMaxSourceSizeKBytes(sourceMimetype, targetMimetype, options);
        boolean sizeOkay = maxSourceSizeKBytes < 0 || (maxSourceSizeKBytes > 0 && sourceSize <= maxSourceSizeKBytes*1024);
        AlfrescoRuntimeException e = new UnsupportedTransformationException("Unsupported transformation: " +
                getBeanName()+' '+sourceMimetype+" to "+targetMimetype+' '+
                (sizeOkay
                ? ""
                : transformerDebug.fileSize(sourceSize)+" > "+ transformerDebug.fileSize(maxSourceSizeKBytes*1024)));
        throw transformerDebug.setCause(e);
    }
    // it all checks out OK
}
 
Example 2
Source File: ContentCacheImpl.java    From alfresco-repository with GNU Lesser General Public License v3.0 6 votes vote down vote up
@Override
public boolean put(String contentUrl, ContentReader source)
{
    File tempFile = createCacheFile();
    
    // Copy the content from the source into a cache file
    if (source.getSize() > 0L)
    {
        source.getContent(tempFile);
        File cacheFile = renameTempToActive(tempFile);
        // Add a record of the cached file to the in-memory cache.
        recordCacheEntries(contentUrl, cacheFile);
        return true;
    }

    return false;
}
 
Example 3
Source File: AbstractContentReader.java    From alfresco-repository with GNU Lesser General Public License v3.0 5 votes vote down vote up
/**
 * Does a comparison of the binaries associated with two readers.  Several shortcuts are assumed to be valid:<br/>
 *  - if the readers are the same instance, then the binaries are the same<br/>
 *  - if the size field is different, then the binaries are different<br/>
 * Otherwise the binaries are {@link EqualsHelper#binaryStreamEquals(InputStream, InputStream) compared}.
 * 
 * @return          Returns <tt>true</tt> if the underlying binaries are the same
 * @throws ContentIOException
 */
public static boolean compareContentReaders(ContentReader left, ContentReader right) throws ContentIOException
{
    if (left == right)
    {
        return true;
    }
    else if (left == null || right == null)
    {
        return false;
    }
    else if (left.getSize() != right.getSize())
    {
        return false;
    }
    InputStream leftIs = left.getContentInputStream();
    InputStream rightIs = right.getContentInputStream();
    try
    {
        return EqualsHelper.binaryStreamEquals(leftIs, rightIs);
    }
    catch (IOException e)
    {
        throw new ContentIOException(
                "Failed to compare content reader streams: \n" +
                "   Left:  " + left + "\n" +
                "   right: " + right);
    }
}
 
Example 4
Source File: ContentTransformServiceAdaptor.java    From alfresco-repository with GNU Lesser General Public License v3.0 5 votes vote down vote up
@Deprecated
@Override
public boolean isTransformable(ContentReader reader, ContentWriter writer, TransformationOptions transformationOptions)
{
    String sourceMimetype = reader.getMimetype();
    long sourceSizeInBytes = reader.getSize();
    String contentUrl = reader.getContentUrl();
    String targetMimetype = writer.getMimetype();
    NodeRef sourceNodeRef = transformationOptions.getSourceNodeRef();
    Map<String, String> options = converter.getOptions(transformationOptions, null, null);
    return synchronousTransformClient.isSupported(sourceMimetype, sourceSizeInBytes, contentUrl, targetMimetype,
            options, null, sourceNodeRef);
}
 
Example 5
Source File: ThumbnailServiceImplTest.java    From alfresco-repository with GNU Lesser General Public License v3.0 5 votes vote down vote up
@Test
public void testCreateRenditionThumbnailFromPdfPage2() throws Exception
{
    ImageTransformationOptions options = new ImageTransformationOptions();
    PagedSourceOptions pagedSourceOptions = new PagedSourceOptions();
    pagedSourceOptions.setStartPageNumber(new Integer(2));
    pagedSourceOptions.setEndPageNumber(new Integer(2));
    options.addSourceOptions(pagedSourceOptions);
    
    ThumbnailDefinition thumbnailDefinition = new ThumbnailDefinition(MimetypeMap.MIMETYPE_PDF, options, "doclib_2");
    thumbnailService.getThumbnailRegistry().addThumbnailDefinition(thumbnailDefinition);

    checkTransformer();

    NodeRef pdfOrig = createOriginalContent(this.folder, MimetypeMap.MIMETYPE_PDF);

    NodeRef thumbnail0 = this.thumbnailService.createThumbnail(pdfOrig, ContentModel.PROP_CONTENT,
                MimetypeMap.MIMETYPE_IMAGE_JPEG, thumbnailDefinition.getTransformationOptions(), "doclib_2");
    assertNotNull(thumbnail0);
    checkRenditioned(pdfOrig, Collections.singletonList(new ExpectedAssoc(RegexQNamePattern.MATCH_ALL, "doclib_2", 1)));
    checkRendition("doclib_2", thumbnail0);
    
    // Check the length
    File tempFile = TempFileProvider.createTempFile("thumbnailServiceImplTest", ".jpg");
    ContentReader reader = this.contentService.getReader(thumbnail0, ContentModel.PROP_CONTENT);
    
    long size = reader.getSize();
    reader.getContent(tempFile);
    assertTrue("Page 2 should be blank and less than 4500 bytes. It was "+size+" bytes. tempFile="+tempFile.getPath(), size < 4500);
}
 
Example 6
Source File: ImageMagickContentTransformerTest.java    From alfresco-repository with GNU Lesser General Public License v3.0 5 votes vote down vote up
protected long transform(String sourceMimetype, String targetMimetype, TransformationOptions options) throws IOException
{
    long size = -1;
    String[] quickFiles = getQuickFilenames(sourceMimetype);
    for (String quickFile : quickFiles)
    {
        String sourceExtension = quickFile.substring(quickFile.lastIndexOf('.')+1);
        String targetExtension = mimetypeService.getExtension(targetMimetype);
        
        // is there a test file for this conversion?
        File sourceFile = AbstractContentTransformerTest.loadNamedQuickTestFile(quickFile);
        if (sourceFile == null)
        {
            continue;  // no test file available for that extension
        }
        ContentReader sourceReader = new FileContentReader(sourceFile);
        
        // make a writer for the target file
        File targetFile = TempFileProvider.createTempFile(
                getClass().getSimpleName() + "_" + getName() + "_" + sourceExtension + "_",
                "." + targetExtension);
        ContentWriter targetWriter = new FileContentWriter(targetFile);
        
        // do the transformation
        sourceReader.setMimetype(sourceMimetype);
        targetWriter.setMimetype(targetMimetype);
        transformer.transform(sourceReader.getReader(), targetWriter, options);
        ContentReader targetReader = targetWriter.getReader();
        size = targetReader.getSize();
        assertTrue(size > 0);
    }
    return size;
}
 
Example 7
Source File: RoutingContentServiceTest.java    From alfresco-repository with GNU Lesser General Public License v3.0 5 votes vote down vote up
/**
 * Checks that the URL, mimetype and encoding are automatically set on the readers
 * and writers
 */
public void testAutoSettingOfProperties() throws Exception
{
    // get a writer onto the node
    ContentWriter writer = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true);
    assertNotNull("Writer should not be null", writer);
    assertNotNull("Content URL should not be null", writer.getContentUrl());
    assertNotNull("Content mimetype should not be null", writer.getMimetype());
    assertNotNull("Content encoding should not be null", writer.getEncoding());
    assertNotNull("Content locale should not be null", writer.getLocale());
    
    // write some content
    writer.putContent(SOME_CONTENT);
    
    // get the reader
    ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT);
    assertNotNull("Reader should not be null", reader);
    assertNotNull("Content URL should not be null", reader.getContentUrl());
    assertNotNull("Content mimetype should not be null", reader.getMimetype());
    assertNotNull("Content encoding should not be null", reader.getEncoding());
    assertNotNull("Content locale should not be null", reader.getLocale());
    
    // check that the content length is correct
    // - note encoding is important as we get the byte length
    long length = SOME_CONTENT.getBytes(reader.getEncoding()).length;  // ensures correct decoding
    long checkLength = reader.getSize();
    assertEquals("Content length incorrect", length, checkLength);

    // check the content - the encoding will come into effect here
    String contentCheck = reader.getContentString();
    assertEquals("Content incorrect", SOME_CONTENT, contentCheck);
}
 
Example 8
Source File: ContentMetadataEmbedderTest.java    From alfresco-repository with GNU Lesser General Public License v3.0 5 votes vote down vote up
/**
 * Test that a failing embedder does not destroy the original content
 */
@Test
public void testFailingEmbedder()
{
    MetadataExtracterRegistry registry = (MetadataExtracterRegistry) applicationContext.getBean("metadataExtracterRegistry");
    FailingEmbedder embedder = new FailingEmbedder(Arrays.asList(MimetypeMap.MIMETYPE_PDF));
    embedder.setRegistry(registry);
    embedder.setDictionaryService(this.dictionaryService);
    embedder.setMimetypeService(this.mimetypeService);
    embedder.register();
    
    String myCreator = "Embedded creator";

    // Get the old props
    Map<QName, Serializable> props = this.nodeService.getProperties(this.nodeRef);
    props.put(ContentModel.PROP_AUTHOR, myCreator);
    this.nodeService.setProperties(this.nodeRef, props);

    // Execute the action
    ActionImpl action = new ActionImpl(null, ID, SetPropertyValueActionExecuter.NAME, null);
    
    ContentReader origReader = this.contentService.getReader(this.nodeRef, ContentModel.PROP_CONTENT);
    long origSize = origReader.getSize();
    assertTrue(origSize > 0);

    this.executer.execute(action, this.nodeRef);
    
    ContentReader embeddedReader = this.contentService.getReader(this.nodeRef, ContentModel.PROP_CONTENT);
    
    assertEquals("The original content should remain unchanged on embed failures", origSize, embeddedReader.getSize());
}
 
Example 9
Source File: BinaryProperty.java    From alfresco-remote-api with GNU Lesser General Public License v3.0 5 votes vote down vote up
/**
 * This is the preferred constructor to use. Takes the properties from content reader that it needs.
 * @param reader ContentReader
 */
public BinaryProperty(ContentReader reader)
{
    super();
    this.mimeType = reader.getMimetype();
    this.encoding = reader.getEncoding();
    this.length = reader.getSize();
    this.locale = reader.getLocale();
}
 
Example 10
Source File: AbstractLocalTransform.java    From alfresco-repository with GNU Lesser General Public License v3.0 4 votes vote down vote up
private void retryWithDifferentMimetype(ContentReader reader, ContentWriter writer, String targetMimetype,
                                        Map<String, String> transformOptions, String renditionName,
                                        NodeRef sourceNodeRef, Throwable e)
{
    if (mimetypeService != null && localTransformServiceRegistry != null)
    {
        String differentType = mimetypeService.getMimetypeIfNotMatches(reader.getReader());
        if (differentType == null)
        {
            transformerDebug.debug("          Failed", e);
            throw new ContentIOException("Content conversion failed: \n" +
                    "   reader: " + reader + "\n" +
                    "   writer: " + writer + "\n" +
                    "   options: " + transformOptions,
                    e);
        }
        else
        {
            transformerDebug.debug("          Failed: Mimetype was '" + differentType + "'", e);
            String claimedMimetype = reader.getMimetype();

            if (retryTransformOnDifferentMimeType)
            {
                reader = reader.getReader();
                reader.setMimetype(differentType);
                long sourceSizeInBytes = reader.getSize();

                LocalTransform localTransform = localTransformServiceRegistry.getLocalTransform(
                        differentType, sourceSizeInBytes, targetMimetype, transformOptions, renditionName);
                if (localTransform == null)
                {
                    transformerDebug.debug("          Failed", e);
                    throw new ContentIOException("Content conversion failed: \n" +
                            "   reader: " + reader + "\n" +
                            "   writer: " + writer + "\n" +
                            "   options: " + transformOptions + "\n" +
                            "   claimed mime type: " + claimedMimetype + "\n" +
                            "   detected mime type: " + differentType + "\n" +
                            "   transformer not found" + "\n",
                            e
                    );
                }
                localTransform.transform(reader, writer, transformOptions, renditionName, sourceNodeRef);
            }
            else
            {
                throw new ContentIOException("Content conversion failed: \n" +
                        "   reader: " + reader + "\n" +
                        "   writer: " + writer + "\n" +
                        "   options: " + transformOptions + "\n" +
                        "   claimed mime type: " + claimedMimetype + "\n" +
                        "   detected mime type: " + differentType,
                        e
                );
            }
        }
    }
}
 
Example 11
Source File: OOoContentTransformerHelper.java    From alfresco-repository with GNU Lesser General Public License v3.0 4 votes vote down vote up
public void transform(
        ContentReader reader,
        ContentWriter writer,
        TransformationOptions options) throws Exception
{
    if (isAvailable() == false)
    {
        throw new ContentIOException("Content conversion failed (unavailable): \n" +
                "   reader: " + reader + "\n" +
                "   writer: " + writer);
    }
    
    if (getLogger().isDebugEnabled())
    {
            StringBuilder msg = new StringBuilder();
            msg.append("transforming content from ")
                .append(reader.getMimetype())
                .append(" to ")
                .append(writer.getMimetype());
            getLogger().debug(msg.toString());
    }
    
    String sourceMimetype = getMimetype(reader);
    String targetMimetype = getMimetype(writer);

    MimetypeService mimetypeService = getMimetypeService();
    String sourceExtension = mimetypeService.getExtension(sourceMimetype);
    String targetExtension = mimetypeService.getExtension(targetMimetype);
    // query the registry for the source format
    DocumentFormat sourceFormat = formatRegistry.getFormatByExtension(sourceExtension);
    if (sourceFormat == null)
    {
        // source format is not recognised
        throw new ContentIOException("No OpenOffice document format for source extension: " + sourceExtension);
    }
    // query the registry for the target format
    DocumentFormat targetFormat = formatRegistry.getFormatByExtension(targetExtension);
    if (targetFormat == null)
    {
        // target format is not recognised
        throw new ContentIOException("No OpenOffice document format for target extension: " + targetExtension);
    }
    // get the family of the target document
    DocumentFamily sourceFamily = sourceFormat.getInputFamily();
    // does the format support the conversion
    if (!formatRegistry.getOutputFormats(sourceFamily).contains(targetFormat)) // same as: targetFormat.getStoreProperties(sourceFamily) == null
    {
        throw new ContentIOException(
                "OpenOffice conversion not supported: \n" +
                "   reader: " + reader + "\n" +
                "   writer: " + writer);
    }

    // There is a bug (reported in ALF-219) whereby JooConverter (the Alfresco Community Edition's 3rd party
    // OpenOffice connector library) struggles to handle zero-size files being transformed to pdf.
    // For zero-length .html files, it throws NullPointerExceptions.
    // For zero-length .txt files, it produces a pdf transformation, but it is not a conformant
    // pdf file and cannot be viewed (contains no pages).
    //
    // For these reasons, if the file is of zero length, we will not use JooConverter & OpenOffice
    // and will instead ask Apache PDFBox to produce an empty pdf file for us.
    final long documentSize = reader.getSize();
    if (documentSize == 0L || temporaryMsFile(options))
    {
        File tempToFile = TempFileProvider.createTempFile(
                getTempFilePrefix()+"-target-",
                "." + targetExtension);
        produceEmptyPdfFile(tempToFile);
        writer.putContent(tempToFile);
    }
    else
    {
        if (remoteTransformerClientConfigured())
        {
            transformRemote(reader, writer, options, sourceMimetype, sourceExtension, targetMimetype, targetExtension);
        }
        else
        {
            transformLocal(reader, writer, options, sourceMimetype,
                    sourceExtension, targetExtension, sourceFormat, targetFormat);
        }
    }

    if (getLogger().isDebugEnabled())
    {
        getLogger().debug("transformation successful");
    }
}
 
Example 12
Source File: CachingContentStore.java    From alfresco-repository with GNU Lesser General Public License v3.0 4 votes vote down vote up
private ContentReader cacheAndRead(String url)
{
    WriteLock writeLock = readWriteLock(url).writeLock();
    writeLock.lock();
    try
    {
        for (int i = 0; i < maxCacheTries; i++)
        {
            ContentReader backingStoreReader = backingStore.getReader(url);
            long contentSize = backingStoreReader.getSize();
            
            if (!quota.beforeWritingCacheFile(contentSize))
            {
                return backingStoreReader;
            }
            
            ContentReader reader = attemptCacheAndRead(url, backingStoreReader);
            
            if (reader != null)
            {
                boolean keepCacheFile = quota.afterWritingCacheFile(contentSize);
                if (keepCacheFile)
                {
                    return reader;
                }
                else
                {
                    // Quota strategy has requested cache file not to be kept.
                    cache.deleteFile(url);
                    cache.remove(url);
                    return backingStore.getReader(url);
                }
            }
        }
        // Have tried multiple times to cache the item and read it back from the cache
        // but there is a recurring problem - give up and return the item from the backing store.
        if (log.isWarnEnabled())
        {
            log.warn("Attempted " + maxCacheTries + " times to cache content item and failed - "
                        + "returning reader from backing store instead [" + 
                        "backingStore=" + backingStore + 
                        ", url=" + url +
                        "]");
        }
        return backingStore.getReader(url);
    }
    finally
    {
        writeLock.unlock();
    }
}
 
Example 13
Source File: HttpAlfrescoStore.java    From alfresco-repository with GNU Lesser General Public License v3.0 4 votes vote down vote up
private static void doTest(ApplicationContext ctx, String baseUrl, String contentUrl) throws Exception
{
    ServiceRegistry serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
    TransactionService transactionService = serviceRegistry.getTransactionService();
    AuthenticationService authenticationService = serviceRegistry.getAuthenticationService();
    // Construct the store
    HttpAlfrescoStore store = new HttpAlfrescoStore();
    store.setTransactionService(transactionService);
    store.setAuthenticationService(authenticationService);
    store.setBaseHttpUrl(baseUrl);
    
    // Now test
    System.out.println(
            "   Retrieving reader for URL " + contentUrl);
    ContentReader reader = store.getReader(contentUrl);
    System.out.println(
            "   Retrieved reader for URL " + contentUrl);
    // Check if the content exists
    boolean exists = reader.exists();
    if (!exists)
    {
        System.out.println(
                "   Content doesn't exist: " + contentUrl);
        return;
    }
    else
    {
        System.out.println(
                "   Content exists: " + contentUrl);
    }
    // Get the content data
    ContentData contentData = reader.getContentData();
    System.out.println(
            "   Retrieved content data: " + contentData);
    
    // Now get the content
    ByteBuffer buffer = ByteBuffer.allocate((int)reader.getSize());
    FileChannel channel = reader.getFileChannel();
    try
    {
        int count = channel.read(buffer);
        if (count != reader.getSize())
        {
            System.err.println("The number of bytes read was " + count + " but expected " + reader.getSize());
            return;
        }
    }
    finally
    {
        channel.close();
    }
}
 
Example 14
Source File: XmlMetadataExtracter.java    From alfresco-repository with GNU Lesser General Public License v3.0 4 votes vote down vote up
/**
 * Selects and extracter to perform the work and redirects to it.
 */
@Override
public Map<QName, Serializable> extract(ContentReader reader, OverwritePolicy overwritePolicy,
            Map<QName, Serializable> destination, Map<String, Set<QName>> mapping)
{
    // Check the content length
    if (reader.getSize() == 0)
    {
        // There is no content. We don't spoof any properties so there can
        // be nothing extracted.
        if (logger.isDebugEnabled())
        {
            logger.debug("\n" + "XML document has zero length, so bypassing extraction: \n" + "   Document: "
                        + reader);
        }
        return destination;
    }

    MetadataExtracter extracter = null;
    // Select a worker
    for (ContentWorkerSelector<MetadataExtracter> selector : selectors)
    {
        ContentReader spawnedReader = reader.getReader();
        try
        {
            extracter = selector.getWorker(spawnedReader);
        }
        catch (Throwable e)
        {
            // The selector failed, so try another
        }
        finally
        {
            if (reader.isChannelOpen())
            {
                logger.error("Content reader not closed by MetadataExtractor selector: \n" + "   reader:   "
                            + reader + "\n" + "   selector: " + selector);
            }
        }
        // Just take the first successful one
        if (extracter != null)
        {
            if (logger.isDebugEnabled())
            {
                logger.debug("\n" + "Found metadata extracter to process XML document: \n" + "   Selector: "
                            + selector + "\n" + "   Document: " + reader);
            }
            break;
        }
    }
    Map<QName, Serializable> modifiedProperties = null;
    // Did we find anything?
    if (extracter == null)
    {
        if (logger.isDebugEnabled())
        {
            logger.debug("\n" + "No working metadata extractor could be found: \n" + "   Document: " + reader);
        }
        // There will be no properties extracted
        modifiedProperties = destination;
    }
    else
    {
        // An extractor was selected
        try
        {
            modifiedProperties = extracter.extract(reader, overwritePolicy, destination, mapping);
        }
        finally
        {
            if (reader.isChannelOpen())
            {
                logger.error("Content reader not closed by MetadataExtractor: \n" + "   Reader:   " + reader + "\n"
                            + "   extracter: " + extracter);
            }
        }
    }
    // Done
    if (logger.isDebugEnabled())
    {
        logger.debug("\n" + "XML metadata extractor redirected: \n" + "   Reader:    " + reader + "\n"
                    + "   Extracter: " + extracter + "\n" + "   Metadata: " + modifiedProperties);
    }
    return modifiedProperties;
}
 
Example 15
Source File: ContentTransformServiceImpl.java    From alfresco-repository with GNU Lesser General Public License v3.0 4 votes vote down vote up
@Deprecated
public void transform(ContentReader reader, ContentWriter writer, TransformationOptions options)
        throws NoTransformerException, ContentIOException
{
    // check that source and target mimetypes are available
    if (reader == null)
    {
        throw new AlfrescoRuntimeException("The content reader must be set");
    }
    String sourceMimetype = reader.getMimetype();
    if (sourceMimetype == null)
    {
        throw new AlfrescoRuntimeException("The content reader mimetype must be set: " + reader);
    }
    String targetMimetype = writer.getMimetype();
    if (targetMimetype == null)
    {
        throw new AlfrescoRuntimeException("The content writer mimetype must be set: " + writer);
    }

    long sourceSize = reader.getSize();
    try
    {
        // look for a transformer
        transformerDebug.pushAvailable(reader.getContentUrl(), sourceMimetype, targetMimetype, options);
        List<ContentTransformer> transformers = getActiveTransformers(sourceMimetype, sourceSize, targetMimetype, options);
        transformerDebug.availableTransformers(transformers, sourceSize, options, "ContentService.transform(...)");

        int count = transformers.size();
        if (count == 0)
        {
            throw new NoTransformerException(sourceMimetype, targetMimetype);
        }

        if (count == 1 || !transformerFailover)
        {
            ContentTransformer transformer = transformers.size() == 0 ? null : transformers.get(0);
            transformer.transform(reader, writer, options);
        }
        else
        {
            failoverTransformers(reader, writer, options, targetMimetype, transformers);
        }
    }
    finally
    {
        if (transformerDebug.isEnabled())
        {
            transformerDebug.popAvailable();
            debugTransformations(sourceMimetype, targetMimetype, sourceSize, options);
        }
    }
}
 
Example 16
Source File: CMISConnector.java    From alfresco-repository with GNU Lesser General Public License v3.0 4 votes vote down vote up
/**
 * Gets the content from the repository.
 */
public ContentStream getContentStream(CMISNodeInfo info, String streamId, BigInteger offset, BigInteger length)
{
    // get the type and check if the object can have content
    TypeDefinitionWrapper type = info.getType();
    checkDocumentTypeForContent(type);

    // looks like a document, now get the content
    ContentStreamImpl result = new ContentStreamImpl();
    result.setFileName(info.getName());

    // if streamId is set, fetch other content
    NodeRef streamNodeRef = info.getNodeRef();
    if ((streamId != null) && (streamId.length() > 0))
    {
        CMISNodeInfo streamInfo = createNodeInfo(streamId);
        if (!streamInfo.isVariant(CMISObjectVariant.CURRENT_VERSION))
        {
            throw new CmisInvalidArgumentException("Stream id is invalid: " + streamId + ", expected variant " + CMISObjectVariant.CURRENT_VERSION + ", got variant " + streamInfo.getObjectVariant());
        }

        streamNodeRef = streamInfo.getNodeRef();
        type = streamInfo.getType();
        checkDocumentTypeForContent(type);
    }

    // get the stream now
    try
    {
        ContentReader contentReader = contentService.getReader(streamNodeRef, ContentModel.PROP_CONTENT);
        if (contentReader == null)
        {
            throw new CmisConstraintException("Document has no content!");
        }

        result.setMimeType(contentReader.getMimetype());
        long contentSize = contentReader.getSize();

        if ((offset == null) && (length == null))
        {
            result.setStream(contentReader.getContentInputStream());
            result.setLength(BigInteger.valueOf(contentSize));
            publishReadEvent(streamNodeRef, info.getName(), result.getMimeType(), contentSize, contentReader.getEncoding(), null);
        }
        else
        {
            long off = (offset == null ? 0 : offset.longValue());
            long len = (length == null ? contentSize : length.longValue());
            if (off + len > contentSize)
            {
                len = contentReader.getSize() - off;
            }

            result.setStream(new RangeInputStream(contentReader.getContentInputStream(), off, len));
            result.setLength(BigInteger.valueOf(len));
            publishReadEvent(streamNodeRef, info.getName(), result.getMimeType(), contentSize, contentReader.getEncoding(), off+" - "+len);
        }
    }
    catch (Exception e)
    {
        if (e instanceof CmisBaseException)
        {
            throw (CmisBaseException) e;
        }
        else
        {
            StringBuilder msg = new StringBuilder("Failed to retrieve content: " + e.getMessage());
            Throwable cause = e.getCause();
            if(cause != null)
            {
                // add the cause to the CMIS exception
                msg.append(", ");
                msg.append(cause.getMessage());
            }
            throw new CmisRuntimeException(msg.toString(), e);
        }
    }

    return result;
}