]> git.aero2k.de Git - tmp/jakarta-migration.git/commitdiff
DRYD-1250: UCB Blob contributions (#372)
authorMichael Ritter <mikejritter@users.noreply.github.com>
Fri, 5 Jan 2024 01:13:16 +0000 (18:13 -0700)
committerGitHub <noreply@github.com>
Fri, 5 Jan 2024 01:13:16 +0000 (20:13 -0500)
Co-authored-by: Richard Millet <richard.millet@berkeley.edu>
3rdparty/nuxeo/nuxeo-server/9.10-HF30/bundles/nuxeo-binary-metadata-9.10.jar [new file with mode: 0644]
services/blob/service/src/main/java/org/collectionspace/services/blob/BlobResource.java
services/blob/service/src/main/java/org/collectionspace/services/blob/nuxeo/BlobDocumentModelHandler.java
services/common/pom.xml
services/common/src/main/java/org/collectionspace/services/common/blob/BlobOutput.java
services/common/src/main/java/org/collectionspace/services/common/imaging/nuxeo/NuxeoBlobUtils.java

diff --git a/3rdparty/nuxeo/nuxeo-server/9.10-HF30/bundles/nuxeo-binary-metadata-9.10.jar b/3rdparty/nuxeo/nuxeo-server/9.10-HF30/bundles/nuxeo-binary-metadata-9.10.jar
new file mode 100644 (file)
index 0000000..dfa8177
Binary files /dev/null and b/3rdparty/nuxeo/nuxeo-server/9.10-HF30/bundles/nuxeo-binary-metadata-9.10.jar differ
index 578373c0ee8de313fee3e31ef1ded9db960560ec..d51f80327b851370e907416a145504add2f57acc 100644 (file)
@@ -70,10 +70,10 @@ import java.util.regex.Pattern;
 @Consumes("application/xml")
 @Produces("application/xml")
 public class BlobResource extends NuxeoBasedResource {
-       
+
        private static final int DEFAULT_MAX_CACHE_AGE = 86400; // 1 day of seconds.
        private static final String DERIVATIVES_REGEX = "(\\w+)(/blobs/\\*/derivatives/)(\\w+)(/content)"; // matches things like 'GET/blobs/*/derivatives/Medium/content'
-       
+
        @Override
     public String getServiceName(){
         return BlobClient.SERVICE_NAME;
@@ -99,11 +99,11 @@ public class BlobResource extends NuxeoBasedResource {
 //    protected CommonList search(MultivaluedMap<String,String> queryParams,String keywords) {
 //         return (CommonList) super.search(queryParams, keywords);
 //    }
-    
+
     private CommonList getDerivativeList(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
                String csid) throws Exception {
        CommonList result = null;
-       
+
        BlobInput blobInput = new BlobInput();
        blobInput.setDerivativeListRequested(true);
        BlobUtil.setBlobInput(ctx, blobInput);
@@ -117,21 +117,21 @@ public class BlobResource extends NuxeoBasedResource {
        // blobInput instance
        //
        result = BlobUtil.getBlobInput(ctx).getDerivativeList();
-       
+
        return result;
     }
-    
+
     public InputStream getBlobContent(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
-               String csid, 
-               String derivativeTerm, 
+               String csid,
+               String derivativeTerm,
                StringBuffer outMimeType) throws CSWebApplicationException {
        InputStream result = null;
-       
+
        try {
                BlobInput blobInput = BlobUtil.getBlobInput(ctx);
                blobInput.setDerivativeTerm(derivativeTerm);
                blobInput.setContentRequested(true);
-               
+
                PoxPayloadOut response = this.get(csid, ctx);
                if (logger.isDebugEnabled() == true) {
                        logger.debug(response.toString());
@@ -140,7 +140,7 @@ public class BlobResource extends NuxeoBasedResource {
                // The result of a successful get should have put the results in the
                // blobInput instance
                //
-               
+
                String mimeType = blobInput.getMimeType();
                if (mimeType != null) {
                        outMimeType.append(mimeType); // blobInput's mime type was set on call to "get" above by the doc handler
@@ -149,7 +149,7 @@ public class BlobResource extends NuxeoBasedResource {
        } catch (Exception e) {
                throw bigReThrow(e, ServiceMessages.CREATE_FAILED);
        }
-       
+
        if (result == null) {
                String errMsg = String.format("Index failed. Could not get the contents for the Blob with CSID = '%s'.",
                                csid);
@@ -157,10 +157,52 @@ public class BlobResource extends NuxeoBasedResource {
                        Response.Status.INTERNAL_SERVER_ERROR).entity(errMsg).type("text/plain").build();
                throw new CSWebApplicationException(response);
        }
-       
+
        return result;
     }
-    
+
+       /**
+        * Create a response for the Blob content. Depending on how the Blob is stored by Nuxeo, this may or may not support
+        * the Range HTTP header. If a Blob is backed by a File it will support Range, otherwise we can only use the input
+        * stream which RESTEasy won't apply the header to.
+        *
+        * @param ctx the service context
+        * @param csid the csid of the blob to get
+        * @return the http response builder for the Blob
+        * @throws CSWebApplicationException if the Blob or its content can't be retrieved
+        */
+       private ResponseBuilder getBlobContentResponse(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx, String csid) {
+               ResponseBuilder response = null;
+
+               try {
+                       BlobInput blobInput = BlobUtil.getBlobInput(ctx);
+                       blobInput.setDerivativeTerm(null);
+                       blobInput.setContentRequested(true);
+
+                       // refresh the BlobInput
+                       PoxPayloadOut poxPayloadOut = this.get(csid, ctx);
+
+                       if (blobInput.getBlobFile() != null) {
+                               response = Response.ok(blobInput.getBlobFile(), blobInput.getMimeType());
+                       } else if (blobInput.getContentStream() != null) {
+                               response = Response.ok(blobInput.getContentStream(), blobInput.getMimeType());
+                       }
+               } catch (Exception e) {
+                       throw bigReThrow(e, ServiceMessages.GET_FAILED);
+               }
+
+               if (response == null) {
+                       String errMsg = String.format("Index failed. Could not get the contents for the Blob with CSID = '%s'.",
+                                                                                 csid);
+                       Response errorResponse = Response.status(Response.Status.INTERNAL_SERVER_ERROR)
+                                                                               .entity(errMsg)
+                                                                               .type(MediaType.TEXT_PLAIN).build();
+                       throw new CSWebApplicationException(errorResponse);
+               }
+
+               return response;
+       }
+
     /*
      * This method can replace the 'createBlob' -specifically, this JAX-RS technique can replace the call to
      * the BlobInput.createBlobFile() method.  In theory, this should reduce by 1 the number of times we need to copy
@@ -175,15 +217,15 @@ public class BlobResource extends NuxeoBasedResource {
                @Context HttpServletRequest req,
                @QueryParam(BlobClient.BLOB_URI_PARAM) String blobUri,
                MultipartFormDataInput partFormData) {
-       Response response = null;       
+       Response response = null;
        try {
                InputStream fileStream = null;
                String preamble = partFormData.getPreamble();
                System.out.println("Preamble type is:" + preamble);
-               
+
                Map<String, List<InputPart>> partsMap = partFormData.getFormDataMap();
                List<InputPart> fileParts = partsMap.get("file");
-               
+
                for (InputPart part : fileParts)
                {
                        String mediaType = part.getMediaType().toString();
@@ -191,23 +233,23 @@ public class BlobResource extends NuxeoBasedResource {
                        fileStream = part.getBody(InputStream.class, null);
                        FileUtilities.createTmpFile(fileStream, getServiceName() + "_");
                }
-               
+
                ResponseBuilder rb = Response.ok();
                rb.entity("Goodbye, world!");
                response = rb.build();
        } catch (Exception e) {
                throw bigReThrow(e, ServiceMessages.CREATE_FAILED);
        }
-                       
+
                return response;
-    }    
-    
+    }
+
     @POST
     @Consumes("multipart/form-data")
     @Produces("application/xml")
     public Response createBlob(@Context HttpServletRequest req,
                @QueryParam(BlobClient.BLOB_URI_PARAM) String blobUri) {
-       Response response = null;       
+       Response response = null;
        try {
                ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext();
                BlobInput blobInput = BlobUtil.getBlobInput(ctx);
@@ -216,20 +258,20 @@ public class BlobResource extends NuxeoBasedResource {
        } catch (Exception e) {
                throw bigReThrow(e, ServiceMessages.CREATE_FAILED);
        }
-                       
+
                return response;
     }
-    
+
     @POST
     @Override
     public Response create(
-               @Context ResourceMap resourceMap, 
+               @Context ResourceMap resourceMap,
                @Context UriInfo ui,
                String xmlPayload) {
        Response response = null;
        MultivaluedMap<String, String> queryParams = ui.getQueryParameters();
        String blobUri = queryParams.getFirst(BlobClient.BLOB_URI_PARAM);
-       
+
        try {
                if (blobUri != null) { // If we were passed a URI than try to create a blob from it
                        ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext();
@@ -243,10 +285,10 @@ public class BlobResource extends NuxeoBasedResource {
        } catch (Exception e) {
                throw bigReThrow(e, ServiceMessages.CREATE_FAILED);
        }
-                       
+
                return response;
-    }    
-    
+    }
+
     /**
      * If there is no explicit setting in the Blobs service binding, we'll ask the HTTP client to cache blobs for 1 full day.
      * @param ctx
@@ -256,7 +298,7 @@ public class BlobResource extends NuxeoBasedResource {
     @Override
     protected CacheControl getCacheControl(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx, String cacheKey) {
        CacheControl result = null;
-       
+
        if (cacheKey.matches(DERIVATIVES_REGEX)) {
                Pattern p = Pattern.compile(DERIVATIVES_REGEX);
                Matcher m = p.matcher(cacheKey);
@@ -264,16 +306,16 @@ public class BlobResource extends NuxeoBasedResource {
                        cacheKey = String.format("%s%s*%s", m.group(1), m.group(2), m.group(4));  // Converts something like this "GET/blobs/*/derivatives/Medium/content" into this "GET/blobs/*/derivatives/*/content"
                }
        }
-       
+
        result = super.getCacheControl(ctx, cacheKey);
        if (result == null) {
                result = new CacheControl();
                result.setMaxAge(DEFAULT_MAX_CACHE_AGE);
        }
-       
+
        return result;
     }
-    
+
     @GET
     @Path("{csid}/content")
     public Response getBlobContent(
@@ -281,18 +323,15 @@ public class BlobResource extends NuxeoBasedResource {
                @Context Request jaxRsRequest,
                @Context UriInfo uriInfo) {
        Response result = null;
-       ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = null; 
-       
+       ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = null;
+
        try {
                ctx = createServiceContext(jaxRsRequest, uriInfo);
                        BlobsCommon blobsCommon = getBlobsCommon(csid);
-               StringBuffer mimeType = new StringBuffer();
-               InputStream contentStream = getBlobContent(ctx, csid, null /*derivative term*/, mimeType /*will get set*/);
-                   
-               Response.ResponseBuilder responseBuilder = Response.ok(contentStream, mimeType.toString());
+
+                       Response.ResponseBuilder responseBuilder = getBlobContentResponse(ctx, csid);
                setCacheControl(ctx, responseBuilder);
-               responseBuilder = responseBuilder.header("Content-Disposition","inline;filename=\""
-                               + blobsCommon.getName() +"\"");
+               responseBuilder.header("Content-Disposition","inline;filename=\"" + blobsCommon.getName() + "\"");
                result = responseBuilder.build();
        } catch (Exception e) {
                throw bigReThrow(e, ServiceMessages.CREATE_FAILED);
@@ -300,18 +339,18 @@ public class BlobResource extends NuxeoBasedResource {
 
        return result;
     }
-    
+
        private BlobsCommon getBlobsCommon(String csid) throws Exception {
        BlobsCommon result = null;
-       
+
        ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext();
                PoxPayloadOut ppo = this.get(csid, ctx);
                PayloadPart blobsCommonPart = ppo.getPart(BlobClient.SERVICE_COMMON_PART_NAME);
                result = (BlobsCommon)blobsCommonPart.getBody();
-               
+
        return result;
     }
-    
+
     /*
      * Publish the blob content.
      */
@@ -323,45 +362,45 @@ public class BlobResource extends NuxeoBasedResource {
                @PathParam("csid") String csid) {
        Response result = null;
        ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = null;
-       
+
        try {
-                       ctx = createServiceContext();                   
+                       ctx = createServiceContext();
                        BlobsCommon blobsCommon = getBlobsCommon(csid);
                StringBuffer mimeType = new StringBuffer();
-               InputStream contentStream = getBlobContent(ctx, csid, null /*derivative term*/, mimeType /*will get set*/);             
-               result = PublicItemUtil.publishToRepository((PublicitemsCommon)null, resourceMap, uriInfo, 
+               InputStream contentStream = getBlobContent(ctx, csid, null /*derivative term*/, mimeType /*will get set*/);
+               result = PublicItemUtil.publishToRepository((PublicitemsCommon)null, resourceMap, uriInfo,
                                getRepositoryClient(ctx), ctx, contentStream, blobsCommon.getName());
        } catch (Exception e) {
                throw bigReThrow(e, ServiceMessages.PUT_FAILED);
        }
-       
+
        return result;
     }
-    
+
     @POST
     @Path("{csid}/derivatives/{derivativeTerm}/content/publish")
     public Response publishDerivativeContent(
                @Context ResourceMap resourceMap,
-               @Context UriInfo uriInfo,               
+               @Context UriInfo uriInfo,
                @PathParam("csid") String csid,
                @PathParam("derivativeTerm") String derivativeTerm) {
        Response result = null;
        ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = null;
-       
+
                try {
                        ctx = createServiceContext();
                                BlobsCommon blobsCommon = getBlobsCommon(csid);
                        StringBuffer mimeType = new StringBuffer();
                        InputStream contentStream = getBlobContent(ctx, csid, derivativeTerm, mimeType);
-                       result = PublicItemUtil.publishToRepository((PublicitemsCommon)null, resourceMap, uriInfo, 
+                       result = PublicItemUtil.publishToRepository((PublicitemsCommon)null, resourceMap, uriInfo,
                                        getRepositoryClient(ctx), ctx, contentStream, blobsCommon.getName());
                } catch (Exception e) {
                        throw bigReThrow(e, ServiceMessages.CREATE_FAILED);
                }
-               
+
            return result;
     }
-    
+
     @GET
     @Path("{csid}/derivatives/{derivativeTerm}/content")
     public Response getDerivativeContent(
@@ -371,7 +410,7 @@ public class BlobResource extends NuxeoBasedResource {
                @Context UriInfo uriInfo) {
        Response result = null;
        ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = null;
-       
+
                try {
                        // Setup the call to get the blob derivative
                        ctx = createServiceContext(jaxRsRequest, uriInfo);
@@ -391,13 +430,13 @@ public class BlobResource extends NuxeoBasedResource {
 
            return result;
     }
-    
+
     @GET
     @Path("{csid}/derivatives/{derivativeTerm}")
     public String getDerivative(@PathParam("csid") String csid,
                @PathParam("derivativeTerm") String derivativeTerm) {
        PoxPayloadOut result = null;
-       
+
        ensureCSID(csid, READ);
         try {
                ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = createServiceContext();
@@ -412,10 +451,10 @@ public class BlobResource extends NuxeoBasedResource {
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.READ_FAILED, csid);
         }
-        
+
         return result.toXML();
     }
-        
+
     @GET
     @Path("{csid}/derivatives")
     public CommonList getDerivatives(@PathParam("csid") String csid) {
@@ -433,8 +472,8 @@ public class BlobResource extends NuxeoBasedResource {
         } catch (Exception e) {
             throw bigReThrow(e, ServiceMessages.READ_FAILED, csid);
         }
-           
+
        return result;
     }
-    
+
 }
index a9475b49af41952eea418469f77f6a77857b2409..dc0f4d9817f141a5cf9e741e49cb789dc2e2eba8 100644 (file)
@@ -166,6 +166,7 @@ extends NuxeoDocumentModelHandler<BlobsCommon> {
                        if (getContentFlag == true) {
                                if (blobOutput != null) {
                                        blobInput.setContentStream(blobOutput.getBlobInputStream());
+                                       blobInput.setBlobFile(blobOutput.getBlobFile());
                                } else {
                                        blobInput.setContentStream(null);
                                }
index 73ff2f71d161257cd778cc252617cf90cc958413..b728271209e003457a78cc51e0ed56d4f78a05d3 100644 (file)
                        <scope>provided</scope>
                </dependency>
                <!-- nuxeo -->
+               <dependency>
+                       <groupId>org.nuxeo.binary.metadata</groupId>
+                       <artifactId>nuxeo-binary-metadata</artifactId>
+                       <version>${nuxeo.platform.version}</version>
+               </dependency>
                <dependency>
                        <groupId>org.nuxeo.lib.runtime</groupId>
                        <artifactId>nuxeo-runtime-launcher</artifactId>
index 6acb2a3275578b936e16100f32a9055cd4cf24ea..a2c9043f7079560f0acb6e96bf287f1a9365a46b 100644 (file)
@@ -1,5 +1,6 @@
 package org.collectionspace.services.common.blob;
 
+import java.io.File;
 import java.io.InputStream;
 import org.collectionspace.services.blob.BlobsCommon;
 
@@ -7,6 +8,7 @@ public class BlobOutput {
        private String mimeType;
        private BlobsCommon blobsCommon;
        private InputStream blobInputStream;
+       private File blobFile;
 
        public BlobsCommon getBlobsCommon() {
                return blobsCommon;
@@ -26,4 +28,12 @@ public class BlobOutput {
        public void setMimeType(String mimeType) {
                this.mimeType = mimeType;
        }
+
+       public void setBlobFile(File file) {
+               this.blobFile = file;
+       }
+
+       public File getBlobFile() {
+               return this.blobFile;
+       }
 }
index 905c379b88c7da82f3758ccbe6c25d9badda4654..2b638550da8f722370eb52092cdd80e469ba5235 100644 (file)
@@ -1,4 +1,4 @@
-/**    
+/**
  * NuxeoImageUtils.java
  *
  * {Purpose of This Class}
@@ -59,6 +59,7 @@ import org.nuxeo.ecm.core.api.blobholder.BlobHolder;
 import org.nuxeo.ecm.core.api.blobholder.DocumentBlobHolder;
 import org.nuxeo.ecm.core.api.impl.blob.FileBlob;
 import org.nuxeo.ecm.core.api.model.Property;
+import org.nuxeo.binary.metadata.api.BinaryMetadataService;
 import org.nuxeo.ecm.core.api.Blob;
 import org.nuxeo.ecm.core.api.ClientException;
 import org.nuxeo.ecm.core.api.DocumentModel;
@@ -104,7 +105,7 @@ import org.collectionspace.services.config.service.ListResultField;
  */
 class CSpaceFileBlob extends FileBlob {
        /**
-        * 
+        *
         */
        private static final long serialVersionUID = 1L;
 
@@ -118,23 +119,22 @@ class CSpaceFileBlob extends FileBlob {
  * The Class NuxeoBlobUtils.
  */
 public class NuxeoBlobUtils {
-                       
+
        /** The Constant logger. */
-       private static final Logger logger = LoggerFactory
-                       .getLogger(NuxeoBlobUtils.class);
-       
+       private static final Logger logger = LoggerFactory.getLogger(NuxeoBlobUtils.class);
+
     private static final String VIEWS_PROPERTY = "picture:views";
     private static final String TITLE_PROPERTY = "title";
     private static final String FILENAME_PROPERTY = "filename";
 
-       //
-       // A maximum byte size for the byte array used to hold an image.  Images larger than this will
-       // be returned as FileInputStreams rather than ByteArrayInputStreams
-       //
-       private static final int MAX_IMAGE_BUFFER = 256 * 1024; // REM: 11/26/2013 - This should be set in a config/property file.
-       
+       /**
+        * A maximum byte size for the byte array used to hold an image.  Images larger than this will
+        * be returned as FileInputStreams rather than ByteArrayInputStreams
+        * <p>
+        * REM: 11/26/2013 - This should be set in a config/property file.
+        */
+       private static final int MAX_IMAGE_BUFFER = 256 * 1024;
 
-       
        //
        // File name constants
        //
@@ -143,7 +143,7 @@ public class NuxeoBlobUtils {
 
        public static final String DOCUMENT_PLACEHOLDER_IMAGE = "documentImage.jpg";
        public static final String DOCUMENT_MISSING_PLACEHOLDER_IMAGE = "documentImageMissing.jpg";
-       
+
        public static final String DOCUMENT_PLACEHOLDER_CSV  = "documentCSV.jpg";
        public static final String DOCUMENT_PLACEHOLDER_DOC  = "documentDOC.jpg";
        public static final String DOCUMENT_PLACEHOLDER_DOCX = "documentDOC.jpg";
@@ -174,8 +174,7 @@ public class NuxeoBlobUtils {
         * hard coded.
         */
        public static final String DERIVATIVE_ORIGINAL = "Original";
-       public static final String DERIVATIVE_ORIGINAL_TAG = DERIVATIVE_ORIGINAL
-                       + "_";
+       public static final String DERIVATIVE_ORIGINAL_TAG = DERIVATIVE_ORIGINAL + "_";
 
        public static final String DERIVATIVE_ORIGINAL_JPEG = "OriginalJpeg";
        public static final String DERIVATIVE_ORIGINAL_JPEG_TAG = DERIVATIVE_ORIGINAL_JPEG + "_";
@@ -263,17 +262,17 @@ public class NuxeoBlobUtils {
 
                return item;
        }
-       
+
        static public String getSanizitedFilename(File srcFile) throws Exception {
                return getSanizitedFilename(srcFile.getName());
        }
-       
+
        /*
         * Valid Nuxeo file names are a subset of *nix and Windows filenames, so we need to check.
         */
        static public String getSanizitedFilename(String fileName) throws Exception {
                String result = fileName;
-               
+
                if (fileName != null && fileName.matches(NUXEO_FILENAME_VALID_STRING) == false) {
                        String fixedString = fileName.replaceAll(NUXEO_FILENAME_BAD_CHARS, "_");  // Replace "bad" chars with underscore character
                        if (fixedString.matches(NUXEO_FILENAME_VALID_STRING) == true) {
@@ -283,7 +282,7 @@ public class NuxeoBlobUtils {
                                throw new Exception(errMsg);
                        }
                }
-               
+
                if (result != null && logger.isDebugEnabled() == true) {
                        if (result.equals(fileName) == false) {
                                logger.debug(String.format("The file name '%s' was sanizitized to '%s'.", fileName, result));
@@ -293,9 +292,9 @@ public class NuxeoBlobUtils {
                return result;
        }
 
-       static private void handleGenericBlobs(DocumentBlobHolder docBlobHolder, CommonList commonList, String uri) {
+       private static void handleGenericBlobs(DocumentBlobHolder docBlobHolder, CommonList commonList, String uri) {
                int total = 0;
-               List<Blob> docBlobs = docBlobHolder.getBlobs();                 
+               List<Blob> docBlobs = docBlobHolder.getBlobs();
                // List<BlobListItem> blobListItems = result.getBlobListItem();
                HashMap<String, Object> item = null;
                for (Blob blob : docBlobs) {
@@ -311,8 +310,8 @@ public class NuxeoBlobUtils {
                commonList.setTotalItems(total);
                commonList.setItemsInPage(total);
        }
-       
-       static private void handlePictureViewBlobs(PictureBlobHolder pictureBlobHolder,
+
+       private static void handlePictureViewBlobs(PictureBlobHolder pictureBlobHolder,
                        CoreSessionInterface repoSession,
                        String repositoryId,
                        CommonList commonList,
@@ -359,111 +358,97 @@ public class NuxeoBlobUtils {
                } else {
                        handleGenericBlobs(docBlobHolder, commonList, uri);
                }
-               
+
                return commonList;
        }
 
-       /*
-        * [dublincore, uid, picture, iptc, common, image_metadata]
-        */
-       static private Map<String, Object> getMetadata(Blob nuxeoBlob)
-                       throws Exception {
-               ImagingService service = Framework.getService(ImagingService.class);
-               Map<String, Object> metadataMap = service.getImageMetadata(nuxeoBlob);
-               return metadataMap;
-       }
+    public static boolean isBlobAnImage(Blob input) {
+        boolean result = false;
+
+        FileImporter importer = getFileManagerService().getPluginByName("Imageplugin");
+
+        String normalizedMimeType = getMimeService().getMimetypeEntryByMimeType(input.getMimeType()).getNormalized();
+        if (importer.isEnabled() && (importer.matches(normalizedMimeType) || importer.matches(input.getMimeType()))) {
+            result = true;
+        }
+
+        return result;
+    }
+
+    /*
+     * [dublincore, uid, picture, iptc, common, image_metadata]
+     */
+    private static Map<String, Object> getMetadata(Blob nuxeoBlob) throws Exception {
+        BinaryMetadataService binaryMetadataService = Framework.getService(BinaryMetadataService.class);
+        return binaryMetadataService.readMetadata(nuxeoBlob, false);
+    }
 
-       private static String[] imageTypes = {"jpeg", "bmp", "gif", "png", "tiff", "octet-stream"};
-       static private boolean isImageMedia(Blob nuxeoBlob) {
-               boolean result = false;
-               
-               String mimeType = nuxeoBlob.getMimeType();
-               if (mimeType != null) {
-                       mimeType = mimeType.toLowerCase().trim();
-                       String[] parts = mimeType.split("/"); // split strings like "application/xml" into an array of two strings
-                       if (parts.length == 2) {
-                               for (String type : imageTypes) {
-                                       if (parts[1].equalsIgnoreCase(type)) {
-                                               result = true;
-                                               break;
-                                       }
-                               }
-                       }
-               }
-               
-               return result;
-       }
-       
        static private MeasuredPartGroupList getDimensions(
                        DocumentModel documentModel, Blob nuxeoBlob) {
                MeasuredPartGroupList result = null;
-               
-               if (isImageMedia(nuxeoBlob) == true) try {
-                       ImagingService service = Framework.getService(ImagingService.class);
-                       ImageInfo imageInfo = service.getImageInfo(nuxeoBlob);
-                       Map<String, Object> metadataMap = getMetadata(nuxeoBlob);
 
-                       if (imageInfo != null) {
-                               //
-                               // Create a timestamp to add to all the image's dimensions
-                               //
-                               String valueDate = GregorianCalendarDateTimeUtils
-                                               .timestampUTC();
-                               
-                               result = new MeasuredPartGroupList();
-                               List<MeasuredPartGroup> measuredPartGroupList = 
-                                               (result).getMeasuredPartGroup();
-                               //
-                               // Create a new measured part for the "image"
-                               //
-                               MeasuredPartGroup mpGroup = new MeasuredPartGroup();
-                               mpGroup.setMeasuredPart(PART_IMAGE);
-                               mpGroup.setDimensionSummary(PART_SUMMARY);
-                               mpGroup.setDimensionSubGroupList(new DimensionSubGroupList());
-                               List<DimensionSubGroup> dimensionSubGroupList = mpGroup.getDimensionSubGroupList()
-                                               .getDimensionSubGroup();
+               if (isBlobAnImage(nuxeoBlob)) {
+                       try {
+                               ImagingService service = Framework.getService(ImagingService.class);
+                               ImageInfo imageInfo = service.getImageInfo(nuxeoBlob);
+                               Map<String, Object> metadataMap = getMetadata(nuxeoBlob);
 
-                               //
-                               // Set the width
-                               //
-                               DimensionSubGroup widthDimension = new DimensionSubGroup();
-                               widthDimension.setDimension(WIDTH);
-                               widthDimension.setMeasurementUnit(UNIT_PIXELS);
-                               widthDimension.setValue(intToBigDecimal(imageInfo.getWidth()));
-                               widthDimension.setValueDate(valueDate);
-                               dimensionSubGroupList.add(widthDimension);
-                               //
-                               // Set the height
-                               //
-                               DimensionSubGroup heightDimension = new DimensionSubGroup();
-                               heightDimension.setDimension(HEIGHT);
-                               heightDimension.setMeasurementUnit(UNIT_PIXELS);
-                               heightDimension
-                                               .setValue(intToBigDecimal(imageInfo.getHeight()));
-                               heightDimension.setValueDate(valueDate);
-                               dimensionSubGroupList.add(heightDimension);
-                               //
-                               // Set the depth
-                               //
-                               DimensionSubGroup depthDimension = new DimensionSubGroup();
-                               depthDimension.setDimension(DEPTH);
-                               depthDimension.setMeasurementUnit(UNIT_BITS);
-                               depthDimension.setValue(intToBigDecimal(imageInfo.getDepth()));
-                               depthDimension.setValueDate(valueDate);
-                               dimensionSubGroupList.add(depthDimension);
-                               //
-                               // Now set out result
-                               //
-                               measuredPartGroupList.add(mpGroup);
-                       } else {
-                               if (logger.isWarnEnabled() == true) {
-                                       logger.warn("Could not synthesize a dimension list of the blob: "
-                                                       + documentModel.getName());
+                               if (imageInfo != null) {
+                                       //
+                                       // Create a timestamp to add to all the image's dimensions
+                                       //
+                                       String valueDate = GregorianCalendarDateTimeUtils.timestampUTC();
+
+                                       result = new MeasuredPartGroupList();
+                                       List<MeasuredPartGroup> measuredPartGroupList = (result).getMeasuredPartGroup();
+
+                                       //
+                                       // Create a new measured part for the "image"
+                                       //
+                                       MeasuredPartGroup mpGroup = new MeasuredPartGroup();
+                                       mpGroup.setMeasuredPart(PART_IMAGE);
+                                       mpGroup.setDimensionSummary(PART_SUMMARY);
+                                       mpGroup.setDimensionSubGroupList(new DimensionSubGroupList());
+                                       List<DimensionSubGroup> dimensionSubGroupList =
+                                               mpGroup.getDimensionSubGroupList().getDimensionSubGroup();
+
+                                       //
+                                       // Set the width
+                                       //
+                                       DimensionSubGroup widthDimension = new DimensionSubGroup();
+                                       widthDimension.setDimension(WIDTH);
+                                       widthDimension.setMeasurementUnit(UNIT_PIXELS);
+                                       widthDimension.setValue(intToBigDecimal(imageInfo.getWidth()));
+                                       widthDimension.setValueDate(valueDate);
+                                       dimensionSubGroupList.add(widthDimension);
+                                       //
+                                       // Set the height
+                                       //
+                                       DimensionSubGroup heightDimension = new DimensionSubGroup();
+                                       heightDimension.setDimension(HEIGHT);
+                                       heightDimension.setMeasurementUnit(UNIT_PIXELS);
+                                       heightDimension.setValue(intToBigDecimal(imageInfo.getHeight()));
+                                       heightDimension.setValueDate(valueDate);
+                                       dimensionSubGroupList.add(heightDimension);
+                                       //
+                                       // Set the depth
+                                       //
+                                       DimensionSubGroup depthDimension = new DimensionSubGroup();
+                                       depthDimension.setDimension(DEPTH);
+                                       depthDimension.setMeasurementUnit(UNIT_BITS);
+                                       depthDimension.setValue(intToBigDecimal(imageInfo.getDepth()));
+                                       depthDimension.setValueDate(valueDate);
+                                       dimensionSubGroupList.add(depthDimension);
+                                       //
+                                       // Now set out result
+                                       //
+                                       measuredPartGroupList.add(mpGroup);
+                               } else {
+                                       logger.warn("Could not synthesize a dimension list of the blob: {}", documentModel.getName());
                                }
+                       } catch (Exception e) {
+                               logger.warn("Could not extract image information for blob: {}", documentModel.getName(), e);
                        }
-               } catch (Exception e) {
-                       logger.warn("Could not extract image information for blob: "
-                                       + documentModel.getName(), e);
                }
 
                return result;
@@ -481,7 +466,7 @@ public class NuxeoBlobUtils {
                        Blob nuxeoBlob) {
                return createBlobsCommon(ctx, documentModel, nuxeoBlob, false);
        }
-       
+
        static private BlobsCommon createBlobsCommon(ServiceContext ctx, DocumentModel documentModel,
                        Blob nuxeoBlob, Boolean getContentFlag) {
                BlobsCommon result = new BlobsCommon();
@@ -503,7 +488,7 @@ public class NuxeoBlobUtils {
                                }
                        }
                        result.setDigest(digest);
-                       
+
                        //
                        // If getContentFlag is true then we're being asked for the blob's content, so we don't
                        // need the measurement info.  Getting the measurement info requires a call to Nuxeo which in turn
@@ -559,29 +544,29 @@ public class NuxeoBlobUtils {
         }
         return blob;
     }
-       
+
        /**
         * Gets the type service.  Not in use, but please keep for future reference
-        * 
+        *
         * @return the type service
         * @throws ClientException
         *             the client exception
         */
        private static TypeManager getTypeService() throws ClientException {
                TypeManager typeService = null;
-               
+
                try {
                        typeService = Framework.getService(TypeManager.class);
                } catch (Exception e) {
                        throw new ClientException(e);
                }
-               
+
                return typeService;
        }
 
        /**
         * Create a temporary Nuxeo FileBlob instance for processing.  Nuxeo will clean this up for us.
-        * 
+        *
         * @param file
         * @return
         * @throws Exception
@@ -592,14 +577,14 @@ public class NuxeoBlobUtils {
 
        /**
         * Gets Nuxeo's file manager service.
-        * 
+        *
         * @return the file manager service
         * @throws ClientException
         *             the client exception
         */
        private static FileManager getFileManager() throws ClientException {
                FileManager result = null;
-               
+
                try {
                        result = Framework.getService(FileManager.class);
                } catch (Exception e) {
@@ -607,20 +592,20 @@ public class NuxeoBlobUtils {
                        logger.error(msg, e);
                        throw new ClientException("msg", e);
                }
-               
+
                return result;
        }
-               
+
        /**
         * Gets Nuxeo's file manager service.
-        * 
+        *
         * @return the file manager service
         * @throws ClientException
         *             the client exception
         */
        private static FileManagerService getFileManagerService() throws ClientException {
                FileManagerService result = null;
-               
+
                try {
                        result = (FileManagerService)getFileManager();
                } catch (Exception e) {
@@ -628,54 +613,54 @@ public class NuxeoBlobUtils {
                        logger.error(msg, e);
                        throw new ClientException("msg", e);
                }
-               
+
                return result;
-       }       
-       
-       
+       }
+
+
        static private CoreSessionInterface getRepositorySession(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
                        RepositoryClient<PoxPayloadIn, PoxPayloadOut> repositoryClient) {
-               CoreSessionInterface result = null;             
+               CoreSessionInterface result = null;
                NuxeoRepositoryClientImpl nuxeoClient = (NuxeoRepositoryClientImpl)repositoryClient;
-               
+
                try {
                        result = nuxeoClient.getRepositorySession(ctx);
                } catch (Exception e) {
             logger.error("Could not get a repository session to the Nuxeo repository", e);
                }
-               
+
                return result;
        }
-       
+
        static private void releaseRepositorySession(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
                        RepositoryClient<PoxPayloadIn, PoxPayloadOut> repositoryClient,
                        CoreSessionInterface repoSession) throws TransactionException {
                NuxeoRepositoryClientImpl nuxeoClient = (NuxeoRepositoryClientImpl)repositoryClient;
                nuxeoClient.releaseRepositorySession(ctx, repoSession);
        }
-       
+
     static private MimetypeRegistry getMimeService() throws ClientException {
        MimetypeRegistry result = null;
-       
+
         try {
                result = Framework.getService(MimetypeRegistry.class);
         } catch (Exception e) {
             throw new ClientException(e);
         }
-               
+
         return result;
     }
-       
+
        private static DocumentModel createDocumentFromBlob(
                        CoreSessionInterface repoSession,
-            Blob inputStreamBlob, 
-            String blobLocation, 
-            boolean overwrite, 
-            String blobName, 
+            Blob inputStreamBlob,
+            String blobLocation,
+            boolean overwrite,
+            String blobName,
             boolean useNuxeoAdaptors) throws Exception {
                DocumentModel result = null;
-               
-               boolean createdFromAdaptor = false;             
+
+               boolean createdFromAdaptor = false;
                if (useNuxeoAdaptors == true) try {
                        //
                        // Use Nuxeo's high-level create method which looks for plugin adapters that match the MIME type.  For example,
@@ -689,25 +674,25 @@ public class NuxeoBlobUtils {
                        logger.warn(String.format("Tried but failed to use Nuxeo import adaptor to download '%s'.  Falling back to generic file importer",
                                        blobName));
                }
-               
+
                if (createdFromAdaptor == false) {
                        //
                        // User Nuxeo's default file importer/adapter explicitly.  This avoids specialized functionality from happening like
                        // image derivative creation.
                        //
                        String digestAlgorithm = getFileManager().getDigestAlgorithm(); // Only call this because we seem to need some way of initializing Nuxeo's FileManager with a call.
-                       
+
                        FileManagerService fileManagerService = getFileManagerService();
                        inputStreamBlob = checkMimeType(inputStreamBlob, blobName);
 
                        FileImporter defaultFileImporter = fileManagerService.getPluginByName("DefaultFileImporter");
                        result = defaultFileImporter.create(
-                                       repoSession.getCoreSession(), inputStreamBlob, blobLocation, overwrite, blobName, getTypeService());                    
+                                       repoSession.getCoreSession(), inputStreamBlob, blobLocation, overwrite, blobName, getTypeService());
                }
-               
+
                return result;
        }
-       
+
        static public BlobsCommon createBlobInRepository(
                        ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
                        RepositoryClient<PoxPayloadIn, PoxPayloadOut> repositoryClient,
@@ -722,19 +707,19 @@ public class NuxeoBlobUtils {
                        repoSession = getRepositorySession(ctx, repositoryClient);
                        repoSessionCleanup = true;
                }
-                               
+
                try {
                        // We'll store the blob inside the workspace directory of the calling service
                        String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
                        DocumentRef nuxeoWspace = new IdRef(nuxeoWspaceId);
                        DocumentModel blobLocation = repoSession.getDocument(nuxeoWspace);
-                       
+
                        Blob inputStreamBlob = new FileBlob(inputStream); // creates a temp file to hold the stream
                        DocumentModel documentModel = createDocumentFromBlob(
                                        repoSession,
-                           inputStreamBlob, 
-                           blobLocation.getPathAsString(), 
-                           false, 
+                           inputStreamBlob,
+                           blobLocation.getPathAsString(),
+                           false,
                            blobName,
                            useNuxeoAdaptors);
                        result = createBlobsCommon(ctx, documentModel, inputStreamBlob); // Now create the metadata about the Nuxeo blob document
@@ -746,13 +731,13 @@ public class NuxeoBlobUtils {
                                releaseRepositorySession(ctx, repositoryClient, repoSession);
                        }
                }
-               
+
                return result;
        }
-       
+
        /**
         * Creates the picture.
-        * 
+        *
         * @param ctx
         *            the ctx
         * @param repoSession
@@ -760,7 +745,7 @@ public class NuxeoBlobUtils {
         * @param filePath
         *            the file path
         * @return the string
-        * @throws Exception 
+        * @throws Exception
         */
        public static BlobsCommon createBlobInRepository(
                        ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
@@ -786,11 +771,11 @@ public class NuxeoBlobUtils {
                                        logger.debug(String.format("The file '%s''s name has characters that Nuxeo can't deal with.  Rather than renaming the file, we created a new temp file at '%s'",
                                                        originalFile.getName(), targetFile.getAbsolutePath()));
                                }
-                       }                       
-                       
+                       }
+
                        DocumentModel wspaceDoc = repoSession.getDocument(nuxeoWspace);
                        DocumentModel newBlobFolder = NuxeoUtils.createFolder(wspaceDoc, UUID.randomUUID().toString());
-                       
+
                        result = createBlobInRepository(ctx,
                                        repoSession,
                                        newBlobFolder,
@@ -807,7 +792,7 @@ public class NuxeoBlobUtils {
                        if (targetFile.equals(originalFile) == false) {
                                result.setName(originalFile.getName());
                        }
-                       
+
                } catch (Exception e) {
                        logger.error("Could not create image blob.", e);
                        throw e;
@@ -824,24 +809,24 @@ public class NuxeoBlobUtils {
 
                return result;
        }
-       
+
        /*
         * Find out if this document's blob/file-contents are allowed to be purged.  For instance, we currently
-        * only want to allow the purging the contents of Nuxeo "Picture" documents. 
+        * only want to allow the purging the contents of Nuxeo "Picture" documents.
         */
        static private boolean isPurgeAllowed(DocumentModel docModel) {
                boolean result = false;
-               
+
                if (docModel.hasFacet(ImagingDocumentConstants.PICTURE_FACET) == true) {
                        result = true; // Yes, delete/purge the original content
                }
-               
+
                return result;
        }
-       
+
        /**
         * Creates the image blob.
-        * 
+        *
         * @param nuxeoSession
         *            the nuxeo session
         * @param blobLocation
@@ -877,10 +862,10 @@ public class NuxeoBlobUtils {
 
                        // If the requester wants us to generate only derivatives, we need to purge/clear the original image file
                        if (purgeOriginal == true && isPurgeAllowed(documentModel) == true) {
-                               
+
                                // Empty the document model's "content" property -this does not delete the actual file/blob
                                //documentModel.setPropertyValue("file:content", (Serializable) null);
-                               
+
                                if (documentModel.hasFacet(ImagingDocumentConstants.PICTURE_FACET)) {
                                        //
                                        // We're going to use the "source" property field of the Dublin Core schema as a way of indicating to
@@ -897,14 +882,14 @@ public class NuxeoBlobUtils {
                                        }
                                        documentModel.setProperty(CommonAPI.NUXEO_DUBLINCORE_SCHEMANAME,
                                                        CommonAPI.NUXEO_DUBLINCORE_SOURCE, CommonAPI.URL_SOURCED_PICTURE);
-                                       
+
                                        // Now with no content, the derivative listener wants to update the derivatives. So to
                                        // prevent the listener, we remove the "Picture" facet from the document
                                        //NuxeoUtils.removeFacet(documentModel, ImagingDocumentConstants.PICTURE_FACET); // Removing this facet ensures the original derivatives are unchanged.
                                        // Now that we've emptied the document model's content field, we can add back the Picture facet
                                        //NuxeoUtils.addFacet(documentModel, ImagingDocumentConstants.PICTURE_FACET);
                                }
-                               
+
                                //nuxeoSession.saveDocument(documentModel);
                                // Next, we need to remove the actual file from Nuxeo's data directory
 //                             Blob blob = docBlobHolder.getBlob();
@@ -915,7 +900,7 @@ public class NuxeoBlobUtils {
 //                                     boolean deleteSuccess = NuxeoUtils.deleteFileOfBlob(docBlobHolder.getBlob());
 //                             }
                        }
-                       
+
                        //
                        // Persist/save any changes.
                        //
@@ -950,16 +935,16 @@ public class NuxeoBlobUtils {
        // }
        // }
        // }
-       
+
        public static InputStream getResource(String resourceName) {
                InputStream result = null;
-               
+
                try {
                        result = ServiceMain.getInstance().getResourceAsStream(resourceName);
                } catch (FileNotFoundException e) {
                        logger.error("Missing Services resource: " + resourceName, e);
                }
-        
+
                return result;
        }
 
@@ -968,21 +953,21 @@ public class NuxeoBlobUtils {
                        String repositoryId,
                        StringBuffer outMimeType) throws TransactionException, DocumentNotFoundException {
                BlobOutput result = null;
-               
+
                boolean repoSessionCleanup = false;
                CoreSessionInterface repoSession = (CoreSessionInterface)ctx.getCurrentRepositorySession();
                if (repoSession == null) {
                        repoSession = getRepositorySession(ctx, repositoryClient);
                        repoSessionCleanup = true;
                }
-               
+
                try {
                        result = getBlobOutput(ctx, repoSession, repositoryId, null, true, outMimeType);
                        if (outMimeType.length() == 0) {
                                BlobsCommon blobsCommon = result.getBlobsCommon();
                                String mimeType = blobsCommon.getMimeType();
                                outMimeType.append(mimeType);
-                       }                       
+                       }
                } catch (DocumentException e) {
                        if (logger.isDebugEnabled()) {
                                logger.debug(e.getMessage(), e);
@@ -994,17 +979,17 @@ public class NuxeoBlobUtils {
                                releaseRepositorySession(ctx, repositoryClient, repoSession);
                        }
                }
-               
+
                return result;
        }
-       
+
        //
        //  If the blob is not too big, we return a ByteArrayInputStream.  Otherwise, we return Nuxeo's InputStream
        //  which is usually a FileInputStream.
        //
        static private InputStream getInputStream(BlobsCommon blobsCommon, Blob blob) {
                InputStream result = null;
-               
+
                if (blob != null) {
                        try {
                                InputStream blobStream = blob.getStream(); // By default, the result will be whatever stream Nuxeo returns to us.
@@ -1025,16 +1010,16 @@ public class NuxeoBlobUtils {
                                        } catch (Exception x) {
                                                logger.debug(String.format("Exception encountered during InputStream cleanup of file %s", blobsCommon.getName()), x);
                                        }
-                               }                       
+                               }
                        }
                }
-               
+
                return result;
        }
-       
+
     static public Set<String> getPictureViewNameSet(CoreSessionInterface repoSession, String repositoryId) throws PropertyException {
         Set<String> result = null;
-        
+
         DocumentModel docModel = repoSession.getDocument(new IdRef(repositoryId));
        Collection<Property> views = docModel.getProperty(VIEWS_PROPERTY).getChildren();
        if (views != null) {
@@ -1043,13 +1028,13 @@ public class NuxeoBlobUtils {
                        result.add((String)property.getValue(TITLE_PROPERTY));
                }
        }
-        
+
         return result;
     }
-       
+
        /**
         * Gets the image.
-        * 
+        *
         * @param repoSession
         *            the repo session
         * @param repositoryId
@@ -1057,7 +1042,7 @@ public class NuxeoBlobUtils {
         * @param derivativeTerm
         *            the derivative term
         * @return the image
-        * @throws DocumentNotFoundException 
+        * @throws DocumentNotFoundException
         */
        static public BlobOutput getBlobOutput(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
                        CoreSessionInterface repoSession,
@@ -1103,16 +1088,16 @@ public class NuxeoBlobUtils {
                                                isNonImageDerivative = true;
                                        }
                                }
-                               
+
                                if (docBlob == null && logger.isWarnEnabled()) {
                                        String msg = String.format("Could not retrieve document blob from Nuxeo document ID='%s' type='%s' name='%s'",
                                                        repositoryId, documentModel.getType(), documentModel.getName());
-                                       
+
                                        if (docBlob == null && docBlobHolder instanceof PictureBlobHolder && derivativeTerm != null) {
                                                msg = String.format("Could not retrieve image blob for derivative '%s' of Picture document with Nuxeo ID='%s' and name='%s'",
                                                                derivativeTerm, repositoryId, documentModel.getName());
                                        }
-                                       
+
                                        if (msg != null) {
                                                logger.warn(msg);
                                        }
@@ -1171,10 +1156,8 @@ public class NuxeoBlobUtils {
                                                }
                                                outMimeType.append(MIME_JPEG);
                                        }
-//                                     BufferedInputStream bufferedInputStream = new BufferedInputStream(
-//                                                     remoteStream);  
-//                                     result.setBlobInputStream(bufferedInputStream);
                                        result.setBlobInputStream(remoteStream);
+                                       result.setBlobFile(docBlob.getFile());
                                }
                        } catch (DocumentNotFoundException d) {
                                throw d;
@@ -1187,7 +1170,7 @@ public class NuxeoBlobUtils {
 
                return result;
        }
-       
+
 }
 
 /*
@@ -1196,31 +1179,31 @@ public class NuxeoBlobUtils {
  */
 
 /*
- * 
- * 
+ *
+ *
  * MultiviewPictureAdapter org.nuxeo.ecm.platform.picture.api.adapters
  * PictureResourceAdapter pictureResourceAdapter = (PictureResourceAdapter)
  * documentModel.getAdapter(PictureResourceAdapter.class); String thumbnailPath
  * = pictureResourceAdapter.getViewXPath("Thumbnail");
- * 
+ *
  * Map<String,Serializable> blobHolderProps = docBlobHolder.getProperties();
  * String filePath = docBlobHolder.getFilePath(); List<Blob> docBlobs =
  * docBlobHolder.getBlobs();
- * 
+ *
  * stream = new FileInputStream(fileUploadHolder.getTempFile());
- * 
+ *
  * public String addFile(InputStream fileUpload, String fileName) fileName =
  * FileUtils.getCleanFileName(fileName); DocumentModel currentDocument =
  * navigationContext.getCurrentDocument(); String path =
  * currentDocument.getPathAsString(); Blob blob =
  * FileUtils.createSerializableBlob(fileUpload, fileName, null);
- * 
+ *
  * DocumentModel createdDoc = getFileManagerService().createDocumentFromBlob(
  * documentManager, blob, path, true, fileName);
  * eventManager.raiseEventsOnDocumentSelected(createdDoc);
- * 
+ *
  * protected FileManager fileManager;
- * 
+ *
  * protected FileManager getFileManagerService() throws ClientException { if
  * (fileManager == null) { try { fileManager =
  * Framework.getService(FileManager.class); } catch (Exception e) {
@@ -1237,7 +1220,7 @@ public class NuxeoBlobUtils {
  * repositoryManager.getDescriptor(repositoryName); DefaultBinaryManager
  * binaryManager = new DefaultBinaryManager(
  * SQLRepository.getDescriptor(descriptor)));
- * 
+ *
  * File storageDir = binaryManager.getStorageDir(); SQLBlob blob = (SQLBlob)
  * doc.getPropertyValue("schema:blobField"); File file =
  * binaryManager.getFileForDigest( blob.getBinary().getDigest(), false);
@@ -1245,49 +1228,48 @@ public class NuxeoBlobUtils {
 
 /*
  * RepositoryInstance.getStreamURI()
- * 
+ *
  * String getStreamURI(String blobPropertyId) throws ClientException
- * 
+ *
  * Returns an URI identifying the stream given the blob property id. This method
  * should be used by a client to download the data of a blob property.
- * 
+ *
  * The blob is fetched from the repository and the blob stream is registered
  * against the streaming service so the stream will be available remotely
  * through stream service API.
- * 
+ *
  * After the client has called this method, it will be able to download the
  * stream using streaming server API.
- * 
+ *
  * Returns: an URI identifying the remote stream Throws: ClientException
  */
 
 /*
  * A blob contains usually large data.
- * 
+ *
  * Document fields holding Blob data are by default fetched in a lazy manner.
- * 
+ *
  * A Blob object hides the data source and it also describes data properties
  * like the encoding or mime-type.
- * 
+ *
  * The encoding is used to decode Unicode text content that was stored in an
  * encoded form. If not encoding is specified, the default java encoding is
  * used. The encoding is ignored for binary content.
- * 
+ *
  * When retrieving the content from a document, it will be returned as source
  * content instead of returning the content bytes.
- * 
+ *
  * The same is true when setting the content for a document: you set a content
  * source and not directly the content bytes. Ex:
- * 
+ *
  * File file = new File("/tmp/index.html"); FileBlob fb = new FileBlob(file);
  * fb.setMimeType("text/html"); fb.setEncoding("UTF-8"); // this specifies that
  * content bytes will be stored as UTF-8 document.setProperty("file", "content",
  * fb);
- * 
- * 
+ *
+ *
  * Then you may want to retrieve the content as follow:
- * 
+ *
  * Blob blob = document.getProperty("file:content"); htmlDoc = blob.getString();
  * // the content is decoded from UTF-8 into a java string
  */
-