]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
7c944507011fb4be0aae43e6b2342ba97832c3b5
[tmp/jakarta-migration.git] /
1 /**     \r
2  * NuxeoImageUtils.java\r
3  *\r
4  * {Purpose of This Class}\r
5  *\r
6  * {Other Notes Relating to This Class (Optional)}\r
7  *\r
8  * $LastChangedBy: $\r
9  * $LastChangedRevision: $\r
10  * $LastChangedDate: $\r
11  *\r
12  * This document is a part of the source code and related artifacts\r
13  * for CollectionSpace, an open source collections management system\r
14  * for museums and related institutions:\r
15  *\r
16  * http://www.collectionspace.org\r
17  * http://wiki.collectionspace.org\r
18  *\r
19  * Copyright © 2009 {Contributing Institution}.\r
20  *\r
21  * Licensed under the Educational Community License (ECL), Version 2.0.\r
22  * You may not use this file except in compliance with this License.\r
23  *\r
24  * You may obtain a copy of the ECL 2.0 License at\r
25  * https://source.collectionspace.org/collection-space/LICENSE.txt\r
26  */\r
27 package org.collectionspace.services.common.imaging.nuxeo;\r
28 \r
29 import java.io.File;\r
30 import java.io.ByteArrayOutputStream;\r
31 import java.io.InputStream;\r
32 import java.io.BufferedInputStream;\r
33 import java.io.IOException;\r
34 import java.math.BigDecimal;\r
35 import java.math.BigInteger;\r
36 import java.util.HashMap;\r
37 import java.util.List;\r
38 import java.util.Map;\r
39 \r
40 import org.nuxeo.runtime.api.Framework;\r
41 //import org.nuxeo.runtime.api.ServiceManager;\r
42 //import org.nuxeo.runtime.api.ServiceDescriptor;\r
43 \r
44 //import org.nuxeo.common.utils.FileUtils;\r
45 \r
46 import org.nuxeo.ecm.platform.picture.api.ImageInfo;\r
47 import org.nuxeo.ecm.platform.picture.api.ImagingService;\r
48 import org.nuxeo.ecm.platform.picture.api.PictureView;\r
49 \r
50 import org.nuxeo.ecm.platform.mimetype.MimetypeDetectionException;\r
51 import org.nuxeo.ecm.platform.mimetype.interfaces.MimetypeRegistry;\r
52 import org.nuxeo.ecm.platform.picture.api.adapters.PictureBlobHolder;\r
53 import org.nuxeo.ecm.platform.filemanager.api.FileManager;\r
54 import org.nuxeo.ecm.platform.types.TypeManager;\r
55 \r
56 import org.nuxeo.ecm.core.repository.RepositoryDescriptor;\r
57 import org.nuxeo.ecm.core.repository.RepositoryManager;\r
58 \r
59 import org.nuxeo.ecm.core.repository.RepositoryService;\r
60 //import org.nuxeo.runtime.model.ComponentManager;\r
61 //import org.nuxeo.runtime.model.impl.ComponentManagerImpl;\r
62 //import org.nuxeo.ecm.core.api.ejb.DocumentManagerBean;\r
63 //import org.nuxeo.ecm.core.storage.sql.RepositoryImpl;\r
64 //import org.nuxeo.ecm.core.storage.sql.Repository;\r
65 import org.nuxeo.ecm.core.storage.sql.DefaultBinaryManager;\r
66 import org.nuxeo.ecm.core.storage.sql.coremodel.SQLRepository;\r
67 //import org.nuxeo.ecm.core.storage.sql.RepositoryDescriptor;\r
68 \r
69 //import org.nuxeo.ecm.core.api.DocumentResolver;\r
70 import org.nuxeo.ecm.core.api.IdRef;\r
71 import org.nuxeo.ecm.core.api.blobholder.BlobHolder;\r
72 import org.nuxeo.ecm.core.api.blobholder.DocumentBlobHolder;\r
73 import org.nuxeo.ecm.core.api.impl.blob.FileBlob;\r
74 import org.nuxeo.ecm.core.api.impl.blob.StreamingBlob;\r
75 import org.nuxeo.ecm.core.api.impl.blob.ByteArrayBlob;\r
76 import org.nuxeo.ecm.core.api.repository.RepositoryInstance;\r
77 import org.nuxeo.ecm.core.api.repository.Repository;\r
78 import org.nuxeo.ecm.core.api.Blob;\r
79 import org.nuxeo.ecm.core.api.ClientException;\r
80 import org.nuxeo.ecm.core.api.DocumentModel;\r
81 import org.nuxeo.ecm.core.api.DocumentRef;\r
82 \r
83 import org.nuxeo.ecm.core.schema.SchemaManager;\r
84 import org.nuxeo.ecm.core.schema.types.Schema;\r
85 \r
86 import org.slf4j.Logger;\r
87 import org.slf4j.LoggerFactory;\r
88 //import org.nuxeo.ecm.core.repository.jcr.testing.RepositoryOSGITestCase;\r
89 \r
90 import org.collectionspace.services.common.blob.BlobInput;\r
91 import org.collectionspace.services.common.context.ServiceContext;\r
92 import org.collectionspace.services.common.datetime.GregorianCalendarDateTimeUtils;\r
93 import org.collectionspace.services.blob.BlobsCommon;\r
94 import org.collectionspace.services.blob.DimensionSubGroup;\r
95 import org.collectionspace.services.blob.DimensionSubGroupList;\r
96 import org.collectionspace.services.blob.MeasuredPartGroup;\r
97 import org.collectionspace.services.blob.MeasuredPartGroupList;\r
98 //import org.collectionspace.services.blob.BlobsCommonList;\r
99 //import org.collectionspace.services.blob.BlobsCommonList.BlobListItem;\r
100 import org.collectionspace.services.jaxb.BlobJAXBSchema;\r
101 import org.collectionspace.services.nuxeo.client.java.CommonList;\r
102 import org.collectionspace.services.common.blob.BlobOutput;\r
103 \r
104 import org.collectionspace.services.config.service.ListResultField;\r
105 \r
106 //import org.collectionspace.ecm.platform.quote.api.QuoteManager;\r
107 \r
108 // TODO: Auto-generated Javadoc\r
109 /**\r
110  * The Class NuxeoImageUtils.\r
111  */\r
112 public class NuxeoImageUtils {\r
113         /** The Constant logger. */\r
114         private static final Logger logger = LoggerFactory\r
115                         .getLogger(NuxeoImageUtils.class);\r
116 \r
117         /*\r
118          * FIXME: REM - These constants should be coming from configuration and NOT\r
119          * hard coded.\r
120          */\r
121         public static final String DERIVATIVE_ORIGINAL = "Original";\r
122         public static final String DERIVATIVE_ORIGINAL_TAG = DERIVATIVE_ORIGINAL\r
123                         + "_";\r
124 \r
125         public static final String DERIVATIVE_ORIGINAL_JPEG = "OriginalJpeg";\r
126         public static final String DERIVATIVE_ORIGINAL_JPEG_TAG = DERIVATIVE_ORIGINAL_JPEG\r
127                         + "_";\r
128 \r
129         public static final String DERIVATIVE_MEDIUM = "Medium";\r
130         public static final String DERIVATIVE_MEDIUM_TAG = DERIVATIVE_MEDIUM + "_";\r
131 \r
132         public static final String DERIVATIVE_THUMBNAIL = "Thumbnail";\r
133         public static final String DERIVATIVE_THUMBNAIL_TAG = DERIVATIVE_THUMBNAIL\r
134                         + "_";\r
135 \r
136         public static final String DERIVATIVE_UNKNOWN = "_UNKNOWN_DERIVATIVE_NAME_";\r
137 \r
138         //\r
139         // Image Dimension fields\r
140         //\r
141         public static final String PART_IMAGE = "digitalImage";\r
142         public static final String PART_SUMMARY = "The dimensions of a digital image -width, height, and pixel depth.";\r
143         public static final String WIDTH = "width";\r
144         public static final String HEIGHT = "height";\r
145         public static final String DEPTH = "depth";\r
146         public static final String UNIT_PIXELS = "pixels";\r
147         public static final String UNIT_BITS = "bits";\r
148         //\r
149         // Image Metadata schemas - These are Nuxeo defined schemas\r
150         //\r
151         public static final String SCHEMA_IPTC = "iptc";\r
152         public static final String SCHEMA_IMAGE_METADATA = "image_metadata";\r
153 \r
154         // static DefaultBinaryManager binaryManager = new DefaultBinaryManager();\r
155         // //can we get this from Nuxeo? i.e.,\r
156         // Framework.getService(BinaryManger.class)\r
157 \r
158         // /** The temp file name. */\r
159         // static String tempFileName = "sunset.jpg";\r
160         //\r
161         // /** The file separator. */\r
162         // static String fileSeparator = System.getProperty("file.separator");\r
163         //\r
164         // /** The cur dir. */\r
165         // static String curDir = System.getProperty("user.dir");\r
166 \r
167         /**\r
168          * Instantiates a new nuxeo image utils.\r
169          */\r
170         NuxeoImageUtils() {\r
171                 // empty constructor\r
172         }\r
173 \r
174         private static String toStringPictureView(PictureView pictureView) {\r
175                 StringBuffer strBuffer = new StringBuffer();\r
176                 strBuffer.append("Description: " + pictureView.getDescription() + '\n');\r
177                 strBuffer.append("FileName: " + pictureView.getFilename() + '\n');\r
178                 strBuffer.append("Height: " + pictureView.getHeight() + '\n');\r
179                 strBuffer.append("Width: " + pictureView.getWidth() + '\n');\r
180                 strBuffer.append("Tag: " + pictureView.getTag() + '\n');\r
181                 strBuffer.append("Title: " + pictureView.getTitle() + '\n');\r
182                 return strBuffer.toString();\r
183         }\r
184 \r
185         // FIXME: REM - This needs to be configuration-bases and NOT hard coded!\r
186         // FIXME: REM - Use MultiviewPicture adapter to get some of this information\r
187         static private String getDerivativeUri(String uri, String derivativeName) {\r
188                 String result = DERIVATIVE_UNKNOWN;\r
189 \r
190                 if (derivativeName.startsWith(DERIVATIVE_ORIGINAL_TAG) == true) {\r
191                         result = DERIVATIVE_ORIGINAL;\r
192                 } else if (derivativeName.startsWith(DERIVATIVE_ORIGINAL_JPEG_TAG) == true) {\r
193                         result = DERIVATIVE_ORIGINAL_JPEG;\r
194                 } else if (derivativeName.startsWith(DERIVATIVE_MEDIUM_TAG) == true) {\r
195                         result = DERIVATIVE_MEDIUM;\r
196                 } else if (derivativeName.startsWith(DERIVATIVE_THUMBNAIL_TAG) == true) {\r
197                         result = DERIVATIVE_THUMBNAIL;\r
198                 }\r
199 \r
200                 return uri + result + "/" + BlobInput.URI_CONTENT_PATH;\r
201         }\r
202 \r
203         static private HashMap<String, Object> createBlobListItem(Blob blob,\r
204                         String uri) {\r
205                 HashMap<String, Object> item = new HashMap<String, Object>();\r
206 \r
207                 String value = blob.getEncoding();\r
208                 if (value != null && !value.trim().isEmpty()) {\r
209                         item.put(BlobJAXBSchema.encoding, value);\r
210                 }\r
211                 value = Long.toString(blob.getLength());\r
212                 if (value != null && !value.trim().isEmpty()) {\r
213                         item.put(BlobJAXBSchema.length, value);\r
214                 }\r
215                 value = blob.getMimeType();\r
216                 if (value != null && !value.trim().isEmpty()) {\r
217                         item.put(BlobJAXBSchema.mimeType, value);\r
218                 }\r
219                 value = blob.getFilename();\r
220                 if (value != null && !value.trim().isEmpty()) {\r
221                         item.put(BlobJAXBSchema.name, value);\r
222                 }\r
223                 value = getDerivativeUri(uri, blob.getFilename());\r
224                 if (value != null && !value.trim().isEmpty()) {\r
225                         item.put(BlobJAXBSchema.uri, value);\r
226                 }\r
227 \r
228                 return item;\r
229         }\r
230 \r
231         static public CommonList getBlobDerivatives(RepositoryInstance repoSession,\r
232                         String repositoryId, List<ListResultField> resultsFields, String uri)\r
233                         throws Exception {\r
234                 CommonList commonList = new CommonList();\r
235                 int nFields = resultsFields.size() + 2;\r
236                 String fields[] = new String[nFields];// FIXME: REM - Patrick needs to fix this hack.  It is a "common list" issue\r
237                 fields[0] = "csid";\r
238                 fields[1] = "uri";\r
239                 for (int i = 2; i < nFields; i++) {\r
240                         ListResultField field = resultsFields.get(i - 2);\r
241                         fields[i] = field.getElement();\r
242                 }\r
243                 commonList.setFieldsReturned(fields);\r
244 \r
245                 IdRef documentRef = new IdRef(repositoryId);\r
246                 DocumentModel documentModel = repoSession.getDocument(documentRef);\r
247                 DocumentBlobHolder docBlobHolder = (DocumentBlobHolder) documentModel\r
248                                 .getAdapter(BlobHolder.class);\r
249                 List<Blob> docBlobs = docBlobHolder.getBlobs();\r
250                 // List<BlobListItem> blobListItems = result.getBlobListItem();\r
251                 HashMap<String, Object> item = null;\r
252                 for (Blob blob : docBlobs) {\r
253                         item = createBlobListItem(blob, uri);\r
254                         commonList.addItem(item);\r
255                 }\r
256 \r
257                 return commonList;\r
258         }\r
259 \r
260         /*\r
261          * [dublincore, uid, picture, iptc, common, image_metadata]\r
262          */\r
263         static private Map<String, Object> getMetadata(Blob nuxeoBlob)\r
264                         throws Exception {\r
265                 ImagingService service = Framework.getService(ImagingService.class);\r
266                 Map<String, Object> metadataMap = service.getImageMetadata(nuxeoBlob);\r
267                 return metadataMap;\r
268         }\r
269 \r
270         static private MeasuredPartGroupList getDimensions(\r
271                         DocumentModel documentModel, Blob nuxeoBlob) {\r
272                 MeasuredPartGroupList result = null;\r
273                 try {\r
274                         ImagingService service = Framework.getService(ImagingService.class);\r
275                         ImageInfo imageInfo = service.getImageInfo(nuxeoBlob);\r
276                         Map<String, Object> metadataMap = getMetadata(nuxeoBlob);\r
277 \r
278                         if (imageInfo != null) {\r
279                                 //\r
280                                 // Create a timestamp to add to all the image's dimensions\r
281                                 //\r
282                                 String valueDate = GregorianCalendarDateTimeUtils\r
283                                                 .timestampUTC();\r
284                                 \r
285                                 result = new MeasuredPartGroupList();\r
286                                 List<MeasuredPartGroup> measuredPartGroupList = \r
287                                                 (result).getMeasuredPartGroup();\r
288                                 //\r
289                                 // Create a new measured part for the "image"\r
290                                 //\r
291                                 MeasuredPartGroup mpGroup = new MeasuredPartGroup();\r
292                                 mpGroup.setMeasuredPart(PART_IMAGE);\r
293                                 mpGroup.setDimensionSummary(PART_SUMMARY);\r
294                                 mpGroup.setDimensionSubGroupList(new DimensionSubGroupList());\r
295                                 List<DimensionSubGroup> dimensionSubGroupList = mpGroup.getDimensionSubGroupList()\r
296                                                 .getDimensionSubGroup();\r
297 \r
298                                 //\r
299                                 // Set the width\r
300                                 //\r
301                                 DimensionSubGroup widthDimension = new DimensionSubGroup();\r
302                                 widthDimension.setDimension(WIDTH);\r
303                                 widthDimension.setMeasurementUnit(UNIT_PIXELS);\r
304                                 widthDimension.setValue(intToBigDecimal(imageInfo.getWidth()));\r
305                                 widthDimension.setValueDate(valueDate);\r
306                                 dimensionSubGroupList.add(widthDimension);\r
307                                 //\r
308                                 // Set the height\r
309                                 //\r
310                                 DimensionSubGroup heightDimension = new DimensionSubGroup();\r
311                                 heightDimension.setDimension(HEIGHT);\r
312                                 heightDimension.setMeasurementUnit(UNIT_PIXELS);\r
313                                 heightDimension\r
314                                                 .setValue(intToBigDecimal(imageInfo.getHeight()));\r
315                                 heightDimension.setValueDate(valueDate);\r
316                                 dimensionSubGroupList.add(heightDimension);\r
317                                 //\r
318                                 // Set the depth\r
319                                 //\r
320                                 DimensionSubGroup depthDimension = new DimensionSubGroup();\r
321                                 depthDimension.setDimension(DEPTH);\r
322                                 depthDimension.setMeasurementUnit(UNIT_BITS);\r
323                                 depthDimension.setValue(intToBigDecimal(imageInfo.getDepth()));\r
324                                 depthDimension.setValueDate(valueDate);\r
325                                 dimensionSubGroupList.add(depthDimension);\r
326                                 //\r
327                                 // Now set out result\r
328                                 //\r
329                                 measuredPartGroupList.add(mpGroup);\r
330                         } else {\r
331                                 if (logger.isWarnEnabled() == true) {\r
332                                         logger.warn("Could not synthesize a dimension list of the blob: "\r
333                                                         + documentModel.getName());\r
334                                 }\r
335                         }\r
336                 } catch (Exception e) {\r
337                         logger.warn("Could not extract image information for blob: "\r
338                                         + documentModel.getName(), e);\r
339                 }\r
340 \r
341                 return result;\r
342         }\r
343 \r
344         // FIXME: Add error checking here, as none of these calls return an\r
345         // Exception\r
346         static private BigDecimal intToBigDecimal(int i) {\r
347                 BigInteger bigint = BigInteger.valueOf(i);\r
348                 BigDecimal bigdec = new BigDecimal(bigint);\r
349                 return bigdec;\r
350         }\r
351 \r
352         static private BlobsCommon createBlobsCommon(DocumentModel documentModel,\r
353                         Blob nuxeoBlob) {\r
354                 BlobsCommon result = new BlobsCommon();\r
355 \r
356                 if (documentModel != null) {\r
357                         result.setMimeType(nuxeoBlob.getMimeType());\r
358                         result.setName(nuxeoBlob.getFilename());\r
359                         result.setLength(Long.toString(nuxeoBlob.getLength()));\r
360                         result.setRepositoryId(documentModel.getId());\r
361                         MeasuredPartGroupList measuredPartGroupList = getDimensions(\r
362                                         documentModel, nuxeoBlob);\r
363                         if (measuredPartGroupList != null) {\r
364                                 result.setMeasuredPartGroupList(measuredPartGroupList);\r
365                         }\r
366                 }\r
367 \r
368                 return result;\r
369         }\r
370 \r
371         /*\r
372          * This is a prototype method that is not currently used as of 1/1/2012.  However,\r
373          * it may be useful now that we've transitioned to using an embedded Nuxeo server.\r
374          */\r
375         static private File getBlobFile(RepositoryInstance ri,\r
376                         DocumentModel documentModel, Blob blob) {\r
377                 DefaultBinaryManager binaryManager = null;\r
378                 RepositoryDescriptor descriptor = null;\r
379 \r
380                 try {\r
381                         RepositoryService repositoryService1 = (RepositoryService) Framework\r
382                                         .getRuntime().getComponent(RepositoryService.NAME);\r
383 \r
384                         String repositoryName = documentModel.getRepositoryName();\r
385                         RepositoryManager repositoryManager = repositoryService1\r
386                                         .getRepositoryManager();\r
387                         descriptor = repositoryManager.getDescriptor(repositoryName);\r
388 \r
389 //                      binaryManager = new DefaultBinaryManager();\r
390 //\r
391 //                      File storageDir = binaryManager.getStorageDir();\r
392 //                      // SQLBlob blob = (SQLBlob)\r
393 //                      // doc.getPropertyValue("schema:blobField");\r
394 //                      File file = binaryManager.getFileForDigest(blob.getDigest(), false);\r
395 \r
396                 } catch (Exception e) {\r
397                         e.printStackTrace();\r
398                 }\r
399 \r
400                 try {\r
401                         binaryManager.initialize(SQLRepository.getDescriptor(descriptor));\r
402                 } catch (IOException e) {\r
403                         // TODO Auto-generated catch block\r
404                         e.printStackTrace();\r
405                 } catch (Exception e) {\r
406                         // TODO Auto-generated catch block\r
407                         e.printStackTrace();\r
408                 }\r
409 \r
410                 File storageDir = binaryManager.getStorageDir();\r
411                 // SQLBlob blob = (SQLBlob)\r
412                 // documentModel.getPropertyValue("schema:blobField");\r
413                 File file = binaryManager.getFileForDigest(blob.getDigest(), false);\r
414 \r
415                 return file;\r
416         }\r
417 \r
418         /**\r
419          * Returns a schema, given the name of a schema.\r
420          * \r
421          * @param schemaName\r
422          *            a schema name.\r
423          * @return a schema.\r
424          */\r
425         private static Schema getSchemaFromName(String schemaName) {\r
426                 SchemaManager schemaManager = null;\r
427                 try {\r
428                         schemaManager = Framework.getService(SchemaManager.class);\r
429                 } catch (Exception e) {\r
430                         // TODO Auto-generated catch block\r
431                         e.printStackTrace();\r
432                 }\r
433                 return schemaManager != null ? schemaManager.getSchema(schemaName)\r
434                                 : null;\r
435         }\r
436 \r
437         /**\r
438          * Gets the blob.\r
439          * \r
440          * @param nuxeoSession\r
441          *            the nuxeo session\r
442          * @param id\r
443          *            the id\r
444          * @return the blob\r
445          */\r
446         static private Blob getBlob(RepositoryInstance nuxeoSession, String id) {\r
447                 Blob result = null;\r
448 \r
449                 try {\r
450                         Repository repository = nuxeoSession.getRepository();\r
451                         // binaryManager.initialize(new RepositoryDescriptor());\r
452                         // binaryManager.getBinary("a4cac052ae0281979f2dcf5ab2e61a6c");\r
453                         // DocumentResolver.resolveReference(nuxeoSession, documentRef);\r
454                         // binaryManager = repository.getBinaryManager();\r
455                         // documentModel.getr\r
456                 } catch (Exception x) {\r
457                         x.printStackTrace();\r
458                 }\r
459 \r
460                 return result;\r
461         }\r
462 \r
463         /**\r
464          * Gets the type service.\r
465          * \r
466          * @return the type service\r
467          * @throws ClientException\r
468          *             the client exception\r
469          */\r
470         private static TypeManager getTypeService() throws ClientException {\r
471                 TypeManager typeService = null;\r
472                 try {\r
473                         typeService = Framework.getService(TypeManager.class);\r
474                 } catch (Exception e) {\r
475                         throw new ClientException(e);\r
476                 }\r
477                 return typeService;\r
478         }\r
479 \r
480         /**\r
481          * Gets the bytes.\r
482          * \r
483          * @param fis\r
484          *            the fis\r
485          * @return the bytes\r
486          */\r
487         private static byte[] getBytes(InputStream fis) {\r
488                 ByteArrayOutputStream bos = new ByteArrayOutputStream();\r
489                 byte[] buf = new byte[128 * 1024];\r
490                 try {\r
491                         for (int readNum; (readNum = fis.read(buf)) != -1;) {\r
492                                 bos.write(buf, 0, readNum);\r
493                                 // no doubt here is 0\r
494                                 /*\r
495                                  * Writes len bytes from the specified byte array starting at\r
496                                  * offset off to this byte array output stream.\r
497                                  */\r
498                                 System.out.println("read " + readNum + " bytes,");\r
499                         }\r
500                 } catch (IOException ex) {\r
501                         logger.error(ex.getMessage(), ex);\r
502                 }\r
503                 byte[] bytes = bos.toByteArray();\r
504                 // bytes is the ByteArray we need\r
505                 return bytes;\r
506         }\r
507 \r
508         /**\r
509          * Creates the serializable blob.\r
510          * \r
511          * @param fileInputStream\r
512          *            the file input stream\r
513          * @param filename\r
514          *            the filename\r
515          * @param mimeType\r
516          *            the mime type\r
517          * @return the blob\r
518          */\r
519         private static Blob createSerializableBlob(InputStream fileInputStream,\r
520                         String filename, String mimeType) {\r
521                 Blob blob = null;\r
522                 try {\r
523                         // persisting the blob makes it possible to read the binary content\r
524                         // of the request stream several times (mimetype sniffing, digest\r
525                         // computation, core binary storage)\r
526                         byte[] bytes = getBytes(fileInputStream);\r
527                         blob = new ByteArrayBlob(bytes);\r
528                         // filename\r
529                         if (filename != null) {\r
530                                 filename = getCleanFileName(filename);\r
531                         }\r
532                         blob.setFilename(filename);\r
533                         // mimetype detection\r
534                         MimetypeRegistry mimeService = Framework\r
535                                         .getService(MimetypeRegistry.class);\r
536                         String detectedMimeType = mimeService\r
537                                         .getMimetypeFromFilenameAndBlobWithDefault(filename, blob,\r
538                                                         null);\r
539                         if (detectedMimeType == null) {\r
540                                 if (mimeType != null) {\r
541                                         detectedMimeType = mimeType;\r
542                                 } else {\r
543                                         // default\r
544                                         detectedMimeType = "application/octet-stream";\r
545                                 }\r
546                         }\r
547                         blob.setMimeType(detectedMimeType);\r
548                 } catch (MimetypeDetectionException e) {\r
549                         logger.error(String.format("could not fetch mimetype for file %s",\r
550                                         filename), e);\r
551                 } catch (Exception e) {\r
552                         logger.error("", e);\r
553                 }\r
554                 return blob;\r
555         }\r
556 \r
557         /**\r
558          * Creates a serializable blob from a stream, with filename and mimetype\r
559          * detection.\r
560          * \r
561          * <p>\r
562          * Creates an in-memory blob if data is under 64K, otherwise constructs a\r
563          * serializable FileBlob which stores data in a temporary file on the hard\r
564          * disk.\r
565          * </p>\r
566          * \r
567          * @param file\r
568          *            the input stream holding data\r
569          * @param filename\r
570          *            the file name. Will be set on the blob and will used for\r
571          *            mimetype detection.\r
572          * @param mimeType\r
573          *            the detected mimetype at upload. Can be null. Will be verified\r
574          *            by the mimetype service.\r
575          * @return the blob\r
576          */\r
577         private static Blob createStreamingBlob(File file, String filename,\r
578                         String mimeType) {\r
579                 Blob blob = null;\r
580                 try {\r
581                         // persisting the blob makes it possible to read the binary content\r
582                         // of the request stream several times (mimetype sniffing, digest\r
583                         // computation, core binary storage)\r
584                         blob = StreamingBlob.createFromFile(file, mimeType).persist();\r
585                         // filename\r
586                         if (filename != null) {\r
587                                 filename = getCleanFileName(filename);\r
588                         }\r
589                         blob.setFilename(filename);\r
590                         // mimetype detection\r
591                         MimetypeRegistry mimeService = Framework\r
592                                         .getService(MimetypeRegistry.class);\r
593                         String detectedMimeType = mimeService\r
594                                         .getMimetypeFromFilenameAndBlobWithDefault(filename, blob,\r
595                                                         null);\r
596                         if (detectedMimeType == null) {\r
597                                 if (mimeType != null) {\r
598                                         detectedMimeType = mimeType;\r
599                                 } else {\r
600                                         // default\r
601                                         detectedMimeType = "application/octet-stream";\r
602                                 }\r
603                         }\r
604                         blob.setMimeType(detectedMimeType);\r
605                 } catch (MimetypeDetectionException e) {\r
606                         logger.error(String.format("could not fetch mimetype for file %s",\r
607                                         filename), e);\r
608                 } catch (IOException e) {\r
609                         logger.error("", e);\r
610                 } catch (Exception e) {\r
611                         logger.error("", e);\r
612                 }\r
613                 return blob;\r
614         }\r
615 \r
616         private static Blob createFileBlob(File file) {\r
617                 Blob result = null;\r
618 \r
619                 result = new FileBlob(file);\r
620                 return result;\r
621         }\r
622 \r
623         /**\r
624          * Returns a clean filename, stripping upload path on client side.\r
625          * <p>\r
626          * Fixes NXP-544\r
627          * </p>\r
628          * \r
629          * @param filename\r
630          *            the filename\r
631          * @return the clean file name\r
632          */\r
633         private static String getCleanFileName(String filename) {\r
634                 String res = null;\r
635                 int lastWinSeparator = filename.lastIndexOf('\\');\r
636                 int lastUnixSeparator = filename.lastIndexOf('/');\r
637                 int lastSeparator = Math.max(lastWinSeparator, lastUnixSeparator);\r
638                 if (lastSeparator != -1) {\r
639                         res = filename.substring(lastSeparator + 1, filename.length());\r
640                 } else {\r
641                         res = filename;\r
642                 }\r
643                 return res;\r
644         }\r
645 \r
646         /**\r
647          * Gets Nuxeo's file manager service.\r
648          * \r
649          * @return the file manager service\r
650          * @throws ClientException\r
651          *             the client exception\r
652          */\r
653         private static FileManager getFileManagerService() throws ClientException {\r
654                 FileManager result = null;\r
655                 try {\r
656                         result = Framework.getService(FileManager.class);\r
657                 } catch (Exception e) {\r
658                         String msg = "Unable to get Nuxeo's FileManager service.";\r
659                         logger.error(msg, e);\r
660                         throw new ClientException("msg", e);\r
661                 }\r
662                 return result;\r
663         }\r
664 \r
665         /**\r
666          * Creates the picture.\r
667          * \r
668          * @param ctx\r
669          *            the ctx\r
670          * @param repoSession\r
671          *            the repo session\r
672          * @param filePath\r
673          *            the file path\r
674          * @return the string\r
675          */\r
676         public static BlobsCommon createPicture(ServiceContext ctx,\r
677                         RepositoryInstance repoSession, BlobInput blobInput) {\r
678                 BlobsCommon result = null;\r
679 \r
680                 try {\r
681                         File blobFile = blobInput.getBlobFile();\r
682                         String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();\r
683                         DocumentRef nuxeoWspace = new IdRef(nuxeoWspaceId);\r
684                         DocumentModel wspaceDoc = repoSession.getDocument(nuxeoWspace);\r
685 \r
686                         // FileInputStream inputStream = new FileInputStream(blobFile);\r
687                         // //FIXME: REM - With an embedded Nuxeo server, we may no longer\r
688                         // need to pass in a stream but instead just pass them the File\r
689                         // instance\r
690                         // if (inputStream != null) {\r
691                         result = createImage(repoSession, wspaceDoc,\r
692                         /* inputStream, */blobFile, null);\r
693                         // }\r
694                 } catch (Exception e) {\r
695                         logger.error("Could not create image blob", e); //FIXME: REM - We should probably be re-throwing the exception?\r
696                 }\r
697 \r
698                 return result;\r
699         }\r
700 \r
701         /**\r
702          * Creates the image blob.\r
703          * \r
704          * @param nuxeoSession\r
705          *            the nuxeo session\r
706          * @param blobLocation\r
707          *            the blob location\r
708          * @param file\r
709          *            the file\r
710          * @param fileName\r
711          *            the file name\r
712          * @param mimeType\r
713          *            the mime type\r
714          * @return the string\r
715          */\r
716         static public BlobsCommon createImage(RepositoryInstance nuxeoSession,\r
717                         DocumentModel blobLocation,\r
718                         // InputStream file,\r
719                         File file, String mimeType) {\r
720                 BlobsCommon result = null;\r
721 \r
722                 try {\r
723                         // Blob fileBlob = createStreamingBlob(blobFile, blobFile.getName(),\r
724                         // mimeType);\r
725                         Blob fileBlob = createFileBlob(file);\r
726                         String digestAlgorithm = getFileManagerService()\r
727                                         .getDigestAlgorithm(); // Need some way on initializing the\r
728                                                                                         // FileManager with a call.\r
729                         \r
730                         logger.debug("Start --> Calling Nuxeo to create an image blob.");\r
731                         DocumentModel documentModel = getFileManagerService()\r
732                                         .createDocumentFromBlob(nuxeoSession, fileBlob,\r
733                                                         blobLocation.getPathAsString(), true,\r
734                                                         file.getName());\r
735                         logger.debug("Stop --> Calling Nuxeo to create an image blob.");\r
736                         \r
737                         result = createBlobsCommon(documentModel, fileBlob);\r
738                 } catch (Exception e) {\r
739                         result = null;\r
740                         logger.error("Could not create new image blob", e); //FIXME: REM - This should probably be re-throwing the exception?\r
741                 }\r
742 \r
743                 return result;\r
744         }\r
745 \r
746         // /*\r
747         // * This is an alternate approach to getting information about an image\r
748         // * and its corresponding derivatives.\r
749         // */\r
750         // // MultiviewPictureAdapter multiviewPictureAdapter =\r
751         // documentModel.getAdapter(MultiviewPictureAdapter.class);\r
752         // MultiviewPictureAdapterFactory multiviewPictureAdapterFactory = new\r
753         // MultiviewPictureAdapterFactory();\r
754         // MultiviewPictureAdapter multiviewPictureAdapter =\r
755         // (MultiviewPictureAdapter)multiviewPictureAdapterFactory.getAdapter(documentModel,\r
756         // null);\r
757         // if (multiviewPictureAdapter != null) {\r
758         // PictureView[] pictureViewArray = multiviewPictureAdapter.getViews();\r
759         // for (PictureView pictureView : pictureViewArray) {\r
760         // if (logger.isDebugEnabled() == true) {\r
761         // logger.debug("-------------------------------------");\r
762         // logger.debug(toStringPictureView(pictureView));\r
763         // }\r
764         // }\r
765         // }\r
766 \r
767         /**\r
768          * Gets the image.\r
769          * \r
770          * @param repoSession\r
771          *            the repo session\r
772          * @param repositoryId\r
773          *            the repository id\r
774          * @param derivativeTerm\r
775          *            the derivative term\r
776          * @return the image\r
777          */\r
778         static public BlobOutput getBlobOutput(ServiceContext ctx,\r
779                         RepositoryInstance repoSession, String repositoryId,\r
780                         String derivativeTerm, Boolean getContentFlag) {\r
781                 BlobOutput result = new BlobOutput();\r
782 \r
783                 if (repositoryId != null && repositoryId.isEmpty() == false)\r
784                         try {\r
785                                 IdRef documentRef = new IdRef(repositoryId);\r
786                                 DocumentModel documentModel = repoSession\r
787                                                 .getDocument(documentRef);\r
788 \r
789                                 Blob docBlob = null;\r
790                                 DocumentBlobHolder docBlobHolder = (DocumentBlobHolder) documentModel\r
791                                                 .getAdapter(BlobHolder.class);\r
792                                 if (docBlobHolder instanceof PictureBlobHolder) { // if it is a\r
793                                                                                                                                         // PictureDocument\r
794                                                                                                                                         // then it\r
795                                                                                                                                         // has these\r
796                                                                                                                                         // Nuxeo\r
797                                                                                                                                         // schemas:\r
798                                                                                                                                         // [dublincore,\r
799                                                                                                                                         // uid,\r
800                                                                                                                                         // picture,\r
801                                                                                                                                         // iptc,\r
802                                                                                                                                         // common,\r
803                                                                                                                                         // image_metadata]\r
804                                         //\r
805                                         // Need to add the "MultiviewPictureAdapter" support here to\r
806                                         // get the view data, see above.\r
807                                         //\r
808                                         PictureBlobHolder pictureBlobHolder = (PictureBlobHolder) docBlobHolder;\r
809                                         if (derivativeTerm != null) {\r
810                                                 docBlob = pictureBlobHolder.getBlob(derivativeTerm);\r
811                                         } else {\r
812                                                 docBlob = pictureBlobHolder.getBlob();\r
813                                         }\r
814                                 } else {\r
815                                         docBlob = docBlobHolder.getBlob();\r
816                                 }\r
817 \r
818                                 //\r
819                                 // Create the result instance that will contain the blob\r
820                                 // metadata\r
821                                 // and an InputStream with the bits if the 'getContentFlag' is\r
822                                 // set\r
823                                 //\r
824                                 BlobsCommon blobsCommon = createBlobsCommon(documentModel,\r
825                                                 docBlob);\r
826                                 result.setBlobsCommon(blobsCommon);\r
827                                 if (getContentFlag == true) {\r
828                                         InputStream remoteStream = docBlob.getStream();\r
829                                         BufferedInputStream bufferedInputStream = new BufferedInputStream(\r
830                                                         remoteStream); // FIXME: REM - To improve\r
831                                                                                         // performance, try\r
832                                                                                         // BufferedInputStream(InputStream\r
833                                                                                         // in, int size)\r
834                                         result.setBlobInputStream(bufferedInputStream); // the input\r
835                                                                                                                                         // stream of\r
836                                                                                                                                         // blob bits\r
837                                 }\r
838 \r
839                         } catch (Exception e) {\r
840                                 if (logger.isErrorEnabled() == true) {\r
841                                         logger.error(e.getMessage(), e);\r
842                                 }\r
843                                 result = null;\r
844                         }\r
845 \r
846                 return result;\r
847         }\r
848 }\r
849 \r
850 /*\r
851  * Notes and code snippets about Nuxeo's support for binaries and image\r
852  * documents.\r
853  */\r
854 \r
855 /*\r
856  * \r
857  * \r
858  * MultiviewPictureAdapter org.nuxeo.ecm.platform.picture.api.adapters\r
859  * PictureResourceAdapter pictureResourceAdapter = (PictureResourceAdapter)\r
860  * documentModel.getAdapter(PictureResourceAdapter.class); String thumbnailPath\r
861  * = pictureResourceAdapter.getViewXPath("Thumbnail");\r
862  * \r
863  * Map<String,Serializable> blobHolderProps = docBlobHolder.getProperties();\r
864  * String filePath = docBlobHolder.getFilePath(); List<Blob> docBlobs =\r
865  * docBlobHolder.getBlobs();\r
866  * \r
867  * stream = new FileInputStream(fileUploadHolder.getTempFile());\r
868  * \r
869  * public String addFile(InputStream fileUpload, String fileName) fileName =\r
870  * FileUtils.getCleanFileName(fileName); DocumentModel currentDocument =\r
871  * navigationContext.getCurrentDocument(); String path =\r
872  * currentDocument.getPathAsString(); Blob blob =\r
873  * FileUtils.createSerializableBlob(fileUpload, fileName, null);\r
874  * \r
875  * DocumentModel createdDoc = getFileManagerService().createDocumentFromBlob(\r
876  * documentManager, blob, path, true, fileName);\r
877  * eventManager.raiseEventsOnDocumentSelected(createdDoc);\r
878  * \r
879  * protected FileManager fileManager;\r
880  * \r
881  * protected FileManager getFileManagerService() throws ClientException { if\r
882  * (fileManager == null) { try { fileManager =\r
883  * Framework.getService(FileManager.class); } catch (Exception e) {\r
884  * log.error("Unable to get FileManager service ", e); throw new\r
885  * ClientException("Unable to get FileManager service ", e); } } return\r
886  * fileManager; }\r
887  */\r
888 \r
889 /*\r
890  * RepositoryService repositoryService = (RepositoryService)\r
891  * Framework.getRuntime().getComponent( RepositoryService.NAME);\r
892  * RepositoryManager repositoryManager =\r
893  * repositoryService.getRepositoryManager(); RepositoryDescriptor descriptor =\r
894  * repositoryManager.getDescriptor(repositoryName); DefaultBinaryManager\r
895  * binaryManager = new DefaultBinaryManager(\r
896  * SQLRepository.getDescriptor(descriptor)));\r
897  * \r
898  * File storageDir = binaryManager.getStorageDir(); SQLBlob blob = (SQLBlob)\r
899  * doc.getPropertyValue("schema:blobField"); File file =\r
900  * binaryManager.getFileForDigest( blob.getBinary().getDigest(), false);\r
901  */\r
902 \r
903 /*\r
904  * RepositoryInstance.getStreamURI()\r
905  * \r
906  * String getStreamURI(String blobPropertyId) throws ClientException\r
907  * \r
908  * Returns an URI identifying the stream given the blob property id. This method\r
909  * should be used by a client to download the data of a blob property.\r
910  * \r
911  * The blob is fetched from the repository and the blob stream is registered\r
912  * against the streaming service so the stream will be available remotely\r
913  * through stream service API.\r
914  * \r
915  * After the client has called this method, it will be able to download the\r
916  * stream using streaming server API.\r
917  * \r
918  * Returns: an URI identifying the remote stream Throws: ClientException\r
919  */\r
920 \r
921 /*\r
922  * A blob contains usually large data.\r
923  * \r
924  * Document fields holding Blob data are by default fetched in a lazy manner.\r
925  * \r
926  * A Blob object hides the data source and it also describes data properties\r
927  * like the encoding or mime-type.\r
928  * \r
929  * The encoding is used to decode Unicode text content that was stored in an\r
930  * encoded form. If not encoding is specified, the default java encoding is\r
931  * used. The encoding is ignored for binary content.\r
932  * \r
933  * When retrieving the content from a document, it will be returned as source\r
934  * content instead of returning the content bytes.\r
935  * \r
936  * The same is true when setting the content for a document: you set a content\r
937  * source and not directly the content bytes. Ex:\r
938  * \r
939  * File file = new File("/tmp/index.html"); FileBlob fb = new FileBlob(file);\r
940  * fb.setMimeType("text/html"); fb.setEncoding("UTF-8"); // this specifies that\r
941  * content bytes will be stored as UTF-8 document.setProperty("file", "content",\r
942  * fb);\r
943  * \r
944  * \r
945  * Then you may want to retrieve the content as follow:\r
946  * \r
947  * Blob blob = document.getProperty("file:content"); htmlDoc = blob.getString();\r
948  * // the content is decoded from UTF-8 into a java string\r
949  */\r