From 47e5dba304e743141f95e9296dc21d1893c98aa8 Mon Sep 17 00:00:00 2001 From: Richard Millet Date: Tue, 10 Jul 2012 17:27:30 -0700 Subject: [PATCH] CSPACE-5386: Dealing with MIME type issues related to JAX-RS as well as with Nuxeo image derivatives --- .../services/blob/BlobResource.java | 33 ++++++++++++------- .../blob/nuxeo/BlobDocumentModelHandler.java | 12 +++++-- .../services/common/FileUtils.java | 33 +++++++++++++++++++ .../services/common/blob/BlobInput.java | 9 +++++ .../services/common/blob/BlobOutput.java | 11 +++++-- .../common/imaging/nuxeo/NuxeoImageUtils.java | 33 ++++++++++++++++--- .../services/media/MediaResource.java | 18 +++++----- 7 files changed, 119 insertions(+), 30 deletions(-) diff --git a/services/blob/service/src/main/java/org/collectionspace/services/blob/BlobResource.java b/services/blob/service/src/main/java/org/collectionspace/services/blob/BlobResource.java index 21819006d..7ed7b396a 100644 --- a/services/blob/service/src/main/java/org/collectionspace/services/blob/BlobResource.java +++ b/services/blob/service/src/main/java/org/collectionspace/services/blob/BlobResource.java @@ -116,7 +116,7 @@ public class BlobResource extends ResourceBase { return result; } - private InputStream getBlobContent(String csid, String derivativeTerm) throws WebApplicationException { + private InputStream getBlobContent(String csid, String derivativeTerm, StringBuffer outMimeType) throws WebApplicationException { InputStream result = null; try { @@ -132,7 +132,12 @@ public class BlobResource extends ResourceBase { // // 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 + } result = BlobUtil.getBlobInput(ctx).getContentStream(); } catch (Exception e) { throw bigReThrow(e, ServiceMessages.CREATE_FAILED); @@ -235,23 +240,29 @@ public class BlobResource extends ResourceBase { @GET @Path("{csid}/content") - @Produces({"image/jpeg", "image/png", "image/tiff", "application/pdf"}) - public InputStream getBlobContent( - @PathParam("csid") String csid) { - InputStream result = null; - result = getBlobContent(csid, null /*derivative term*/); + public Response getBlobContent( @PathParam("csid") String csid) { + Response result = null; + + StringBuffer mimeType = new StringBuffer(); + InputStream contentStream = getBlobContent(csid, null /*derivative term*/, mimeType /*will get set*/); + Response.ResponseBuilder responseBuilder = Response.ok(contentStream, mimeType.toString()); + + result = responseBuilder.build(); return result; } @GET @Path("{csid}/derivatives/{derivativeTerm}/content") - @Produces({"image/jpeg", "image/png", "image/tiff"}) - public InputStream getDerivativeContent( + public Response getDerivativeContent( @PathParam("csid") String csid, @PathParam("derivativeTerm") String derivativeTerm) { - InputStream result = null; - result = getBlobContent(csid, derivativeTerm); + Response result = null; + + StringBuffer mimeType = new StringBuffer(); + InputStream contentStream = getBlobContent(csid, derivativeTerm, mimeType); + Response.ResponseBuilder responseBuilder = Response.ok(contentStream, mimeType.toString()); + result = responseBuilder.build(); return result; } diff --git a/services/blob/service/src/main/java/org/collectionspace/services/blob/nuxeo/BlobDocumentModelHandler.java b/services/blob/service/src/main/java/org/collectionspace/services/blob/nuxeo/BlobDocumentModelHandler.java index 6e48cfdeb..f2156b0c8 100644 --- a/services/blob/service/src/main/java/org/collectionspace/services/blob/nuxeo/BlobDocumentModelHandler.java +++ b/services/blob/service/src/main/java/org/collectionspace/services/blob/nuxeo/BlobDocumentModelHandler.java @@ -136,7 +136,7 @@ extends DocHandlerBase { public void extractAllParts(DocumentWrapper wrapDoc) throws Exception { ServiceContext ctx = this.getServiceContext(); - BlobInput blobInput = BlobUtil.getBlobInput(ctx); + BlobInput blobInput = BlobUtil.getBlobInput(ctx); // the blobInput was set by the Blob JAX-RS resource code and put into the service context RepositoryInstance repoSession = this.getRepositorySession(); DocumentModel docModel = wrapDoc.getWrappedObject(); BlobsCommon blobsCommon = this.getCommonPartProperties(docModel); @@ -160,8 +160,9 @@ extends DocHandlerBase { // fall into this block of code. Otherwise, we'll just call our parent to deal with a plain-old-blob payload. // if (derivativeTerm != null || getContentFlag == true) { + StringBuffer mimeTypeBuffer = new StringBuffer(); BlobOutput blobOutput = NuxeoImageUtils.getBlobOutput(ctx, repoSession, //FIXME: REM - If the blob's binary has been removed from the file system, then this call will return null. We need to at least spit out a meaningful error/warning message - blobRepositoryId, derivativeTerm, getContentFlag); + blobRepositoryId, derivativeTerm, getContentFlag, mimeTypeBuffer); if (getContentFlag == true) { blobInput.setContentStream(blobOutput.getBlobInputStream()); } @@ -173,6 +174,13 @@ extends DocHandlerBase { derivativeTerm + "/" + BlobInput.URI_CONTENT_PATH); } + String mimeType = mimeTypeBuffer.toString(); + if (mimeType != null && !mimeType.isEmpty()) { // MIME type for derivatives might be different from original + blobInput.setMimeType(mimeType); + } else { + blobInput.setMimeType(blobsCommon.getMimeType()); + } + blobsCommon.setRepositoryId(null); //hide the repository id from the GET results payload since it is private this.setCommonPartProperties(docModel, blobsCommon); // finish extracting the other parts by calling the parent diff --git a/services/common/src/main/java/org/collectionspace/services/common/FileUtils.java b/services/common/src/main/java/org/collectionspace/services/common/FileUtils.java index 8a89e2cd5..529308d52 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/FileUtils.java +++ b/services/common/src/main/java/org/collectionspace/services/common/FileUtils.java @@ -41,6 +41,12 @@ import java.util.UUID; //import javax.servlet.ServletException; //import javax.servlet.http.HttpServlet; +import net.sf.jmimemagic.Magic; +import net.sf.jmimemagic.MagicException; +import net.sf.jmimemagic.MagicMatch; +import net.sf.jmimemagic.MagicMatchNotFoundException; +import net.sf.jmimemagic.MagicParseException; + import org.apache.commons.fileupload.FileItemFactory; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.servlet.ServletFileUpload; @@ -96,6 +102,33 @@ public class FileUtils { return result; } + static public String getMimeType(File file) { + String result = null; + + Magic parser = new Magic() ; + // getMagicMatch accepts Files or byte[], + // which is nice if you want to test streams + MagicMatch match = null; + try { + match = parser.getMagicMatch(file, true); + } catch (MagicParseException e) { + logger.debug("MagicParseException encountered trying to get MIME type for " + + file.getAbsolutePath(), e); + } catch (MagicMatchNotFoundException e) { + logger.debug("MagicMatchNotFoundException encountered trying to get MIME type for " + + file.getAbsolutePath(), e); + } catch (MagicException e) { + logger.debug("MagicException encountered trying to get MIME type for " + + file.getAbsolutePath(), e); + } + + if (match != null) { + result = match.getMimeType(); + } + + return result; + } + /** * Look for an uploaded file from the HTTP request of type "multipart/form-data". * diff --git a/services/common/src/main/java/org/collectionspace/services/common/blob/BlobInput.java b/services/common/src/main/java/org/collectionspace/services/common/blob/BlobInput.java index ba7613170..446db9ea0 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/blob/BlobInput.java +++ b/services/common/src/main/java/org/collectionspace/services/common/blob/BlobInput.java @@ -27,6 +27,7 @@ public class BlobInput { private String blobCsid = null; private File blobFile = null; private String blobUri = null; + private String blobMimeType = null; private String derivativeTerm; private boolean derivativeListRequested = false; @@ -168,6 +169,14 @@ public class BlobInput { } this.setBlobFile(theBlobFile); this.setBlobUri(blobUri); + } + + public String getMimeType() { + return blobMimeType; + } + + public void setMimeType(String mimeType) { + this.blobMimeType = mimeType; } } diff --git a/services/common/src/main/java/org/collectionspace/services/common/blob/BlobOutput.java b/services/common/src/main/java/org/collectionspace/services/common/blob/BlobOutput.java index de71337ba..a9325d853 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/blob/BlobOutput.java +++ b/services/common/src/main/java/org/collectionspace/services/common/blob/BlobOutput.java @@ -4,8 +4,9 @@ import java.io.InputStream; import org.collectionspace.services.blob.BlobsCommon; public class BlobOutput { - BlobsCommon blobsCommon; - InputStream blobInputStream; + private String mimeType; + private BlobsCommon blobsCommon; + private InputStream blobInputStream; public BlobsCommon getBlobsCommon() { return blobsCommon; @@ -19,4 +20,10 @@ public class BlobOutput { public void setBlobInputStream(InputStream blobInputStream) { this.blobInputStream = blobInputStream; } + public String getMimeType() { + return mimeType; + } + public void setMimeType(String mimeType) { + this.mimeType = mimeType; + } } diff --git a/services/common/src/main/java/org/collectionspace/services/common/imaging/nuxeo/NuxeoImageUtils.java b/services/common/src/main/java/org/collectionspace/services/common/imaging/nuxeo/NuxeoImageUtils.java index bc97cc837..641b500b4 100644 --- a/services/common/src/main/java/org/collectionspace/services/common/imaging/nuxeo/NuxeoImageUtils.java +++ b/services/common/src/main/java/org/collectionspace/services/common/imaging/nuxeo/NuxeoImageUtils.java @@ -115,6 +115,7 @@ public class NuxeoImageUtils { private static final Logger logger = LoggerFactory .getLogger(NuxeoImageUtils.class); + private static final String MIME_JPEG = "image/jpeg"; /* * FIXME: REM - These constants should be coming from configuration and NOT * hard coded. @@ -271,10 +272,29 @@ public class NuxeoImageUtils { return metadataMap; } + private static String[] imageTypes = {"jpeg", "bmp", "gif", "png", "tiff", "octet-stream"}; + static private boolean isImageMedia(Blob nuxeoBlob) { + boolean result = false; + + String mimeType = nuxeoBlob.getMimeType().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; - try { + + if (isImageMedia(nuxeoBlob) == true) try { ImagingService service = Framework.getService(ImagingService.class); ImageInfo imageInfo = service.getImageInfo(nuxeoBlob); Map metadataMap = getMetadata(nuxeoBlob); @@ -692,12 +712,12 @@ public class NuxeoImageUtils { DocumentRef nuxeoWspace = new IdRef(nuxeoWspaceId); DocumentModel wspaceDoc = repoSession.getDocument(nuxeoWspace); - if (logger.isDebugEnabled()) { + if (logger.isTraceEnabled()) { for (String facet : wspaceDoc.getFacets()) { - logger.debug("Facet: " + facet); + logger.trace("Facet: " + facet); } for (String docType : wspaceDoc.getDocumentType().getChildrenTypes()) { - logger.debug("Child type: " + docType); + logger.trace("Child type: " + docType); } } @@ -790,7 +810,8 @@ public class NuxeoImageUtils { RepositoryInstance repoSession, String repositoryId, String derivativeTerm, - Boolean getContentFlag) { + Boolean getContentFlag, + StringBuffer outMimeType) { BlobOutput result = new BlobOutput(); if (repositoryId != null && repositoryId.isEmpty() == false) @@ -811,6 +832,8 @@ public class NuxeoImageUtils { PictureBlobHolder pictureBlobHolder = (PictureBlobHolder) docBlobHolder; if (derivativeTerm != null) { docBlob = pictureBlobHolder.getBlob(derivativeTerm); + // Nuxeo derivatives are all JPEG + outMimeType.append(MIME_JPEG); } else { docBlob = pictureBlobHolder.getBlob(); } diff --git a/services/media/service/src/main/java/org/collectionspace/services/media/MediaResource.java b/services/media/service/src/main/java/org/collectionspace/services/media/MediaResource.java index 4f16a9f3d..9d1cd1865 100644 --- a/services/media/service/src/main/java/org/collectionspace/services/media/MediaResource.java +++ b/services/media/service/src/main/java/org/collectionspace/services/media/MediaResource.java @@ -157,7 +157,7 @@ public class MediaResource extends ResourceBase { // // First, create the blob // - ServiceContext blobContext = createServiceContext(BlobUtil.BLOB_RESOURCE_NAME, input); + ServiceContext blobContext = createServiceContext(BlobClient.SERVICE_NAME, input); BlobInput blobInput = BlobUtil.getBlobInput(blobContext); blobInput.createBlobFile(req, null); response = this.create(input, blobContext); @@ -185,7 +185,7 @@ public class MediaResource extends ResourceBase { try { String blobCsid = this.getBlobCsid(csid); - ServiceContext blobContext = createServiceContext(BlobUtil.BLOB_RESOURCE_NAME); + ServiceContext blobContext = createServiceContext(BlobClient.SERVICE_NAME); result = this.get(blobCsid, blobContext); } catch (Exception e) { throw bigReThrow(e, ServiceMessages.READ_FAILED, csid); @@ -196,10 +196,9 @@ public class MediaResource extends ResourceBase { @GET @Path("{csid}/blob/content") - @Produces({"image/jpeg", "image/png", "image/tiff"}) - public InputStream getBlobContent( + public Response getBlobContent( @PathParam("csid") String csid) { - InputStream result = null; + Response result = null; try { ensureCSID(csid, READ); @@ -214,11 +213,10 @@ public class MediaResource extends ResourceBase { @GET @Path("{csid}/blob/derivatives/{derivativeTerm}/content") - @Produces({"image/jpeg", "image/png", "image/tiff"}) - public InputStream getDerivativeContent( + public Response getDerivativeContent( @PathParam("csid") String csid, @PathParam("derivativeTerm") String derivativeTerm) { - InputStream result = null; + Response result = null; try { ensureCSID(csid, READ); @@ -240,7 +238,7 @@ public class MediaResource extends ResourceBase { try { ensureCSID(csid, READ); String blobCsid = this.getBlobCsid(csid); - ServiceContext blobContext = createServiceContext(BlobUtil.BLOB_RESOURCE_NAME); + ServiceContext blobContext = createServiceContext(BlobClient.SERVICE_NAME); String xmlPayload = getBlobResource().getDerivative(blobCsid, derivativeTerm); result = new PoxPayloadOut(xmlPayload.getBytes()); } catch (Exception e) { @@ -260,7 +258,7 @@ public class MediaResource extends ResourceBase { try { ensureCSID(csid, READ); String blobCsid = this.getBlobCsid(csid); - ServiceContext blobContext = createServiceContext(BlobUtil.BLOB_RESOURCE_NAME); + ServiceContext blobContext = createServiceContext(BlobClient.SERVICE_NAME); result = getBlobResource().getDerivatives(blobCsid); } catch (Exception e) { throw bigReThrow(e, ServiceMessages.READ_FAILED, csid); -- 2.47.3