2 * NuxeoImageUtils.java
\r
4 * {Purpose of This Class}
\r
6 * {Other Notes Relating to This Class (Optional)}
\r
9 * $LastChangedRevision: $
\r
10 * $LastChangedDate: $
\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
16 * http://www.collectionspace.org
\r
17 * http://wiki.collectionspace.org
\r
19 * Copyright © 2009 {Contributing Institution}
\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
24 * You may obtain a copy of the ECL 2.0 License at
\r
25 * https://source.collectionspace.org/collection-space/LICENSE.txt
\r
27 package org.collectionspace.services.common.imaging.nuxeo;
\r
29 import java.io.File;
\r
30 import java.io.ByteArrayOutputStream;
\r
31 import java.io.InputStream;
\r
32 import java.io.FileInputStream;
\r
33 import java.io.BufferedInputStream;
\r
34 import java.io.IOException;
\r
36 import java.io.Serializable;
\r
37 import java.util.ArrayList;
\r
38 import java.util.HashMap;
\r
39 import java.util.List;
\r
40 import java.util.Map;
\r
42 import org.nuxeo.runtime.api.Framework;
\r
43 import org.nuxeo.runtime.api.ServiceManager;
\r
44 import org.nuxeo.runtime.api.ServiceDescriptor;
\r
45 import org.nuxeo.runtime.services.streaming.RemoteInputStream;
\r
47 //import org.nuxeo.common.utils.FileUtils;
\r
49 import org.nuxeo.ecm.platform.picture.api.adapters.PictureResourceAdapter;
\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.picture.extension.ImagePlugin;
\r
54 import org.nuxeo.ecm.platform.filemanager.api.FileManager;
\r
55 import org.nuxeo.ecm.platform.filemanager.service.FileManagerService;
\r
56 import org.nuxeo.ecm.platform.types.TypeManager;
\r
57 import org.nuxeo.ecm.platform.picture.api.adapters.PictureBlobHolderFactory;
\r
58 import org.nuxeo.ecm.platform.picture.api.adapters.PictureBlobHolder;
\r
60 import org.nuxeo.ecm.core.repository.RepositoryDescriptor;
\r
61 import org.nuxeo.ecm.core.repository.RepositoryManager;
\r
63 import org.nuxeo.ecm.core.repository.RepositoryService;
\r
64 import org.nuxeo.runtime.model.ComponentManager;
\r
65 import org.nuxeo.runtime.model.ComponentInstance;
\r
66 import org.nuxeo.runtime.model.impl.ComponentManagerImpl;
\r
67 //import org.nuxeo.ecm.core.api.ejb.DocumentManagerBean;
\r
68 //import org.nuxeo.ecm.core.storage.sql.RepositoryImpl;
\r
69 //import org.nuxeo.ecm.core.storage.sql.Repository;
\r
70 import org.nuxeo.ecm.core.storage.sql.BinaryManager;
\r
71 import org.nuxeo.ecm.core.storage.sql.DefaultBinaryManager;
\r
72 import org.nuxeo.ecm.core.storage.sql.coremodel.SQLRepository;
\r
73 import org.nuxeo.ecm.core.storage.sql.coremodel.SQLBlob;
\r
74 //import org.nuxeo.ecm.core.storage.sql.RepositoryDescriptor;
\r
76 //import org.nuxeo.ecm.core.api.DocumentResolver;
\r
77 import org.nuxeo.ecm.core.api.IdRef;
\r
78 import org.nuxeo.ecm.core.api.blobholder.BlobHolder;
\r
79 import org.nuxeo.ecm.core.api.blobholder.DocumentBlobHolder;
\r
80 import org.nuxeo.ecm.core.api.impl.blob.FileBlob;
\r
81 import org.nuxeo.ecm.core.api.impl.blob.StreamingBlob;
\r
82 import org.nuxeo.ecm.core.api.impl.blob.ByteArrayBlob;
\r
83 import org.nuxeo.ecm.core.api.repository.RepositoryInstance;
\r
84 import org.nuxeo.ecm.core.api.repository.Repository;
\r
85 import org.nuxeo.ecm.core.api.Blob;
\r
86 import org.nuxeo.ecm.core.api.ClientException;
\r
87 import org.nuxeo.ecm.core.api.DocumentModel;
\r
88 import org.nuxeo.ecm.core.api.DocumentRef;
\r
89 import org.nuxeo.ecm.core.api.blobholder.BlobHolder;
\r
90 import org.nuxeo.ecm.core.api.blobholder.BlobHolderAdapterService;
\r
91 import org.nuxeo.ecm.core.api.impl.DocumentModelImpl;
\r
92 import org.nuxeo.ecm.core.api.impl.blob.FileBlob;
\r
94 import org.nuxeo.ecm.core.model.Document;
\r
95 import org.nuxeo.ecm.core.schema.SchemaManager;
\r
96 import org.nuxeo.ecm.core.schema.types.Schema;
\r
98 import org.slf4j.Logger;
\r
99 import org.slf4j.LoggerFactory;
\r
100 //import org.nuxeo.ecm.core.repository.jcr.testing.RepositoryOSGITestCase;
\r
102 import org.collectionspace.services.common.ServiceMain;
\r
103 import org.collectionspace.services.common.blob.BlobInput;
\r
104 import org.collectionspace.services.common.context.ServiceContext;
\r
105 import org.collectionspace.services.common.document.DocumentUtils;
\r
106 import org.collectionspace.services.common.FileUtils;
\r
107 import org.collectionspace.services.blob.BlobsCommon;
\r
109 // TODO: Auto-generated Javadoc
\r
111 * The Class NuxeoImageUtils.
\r
113 public class NuxeoImageUtils {
\r
114 /** The Constant logger. */
\r
115 private static final Logger logger = LoggerFactory.getLogger(NuxeoImageUtils.class);
\r
117 // static DefaultBinaryManager binaryManager = new DefaultBinaryManager(); //can we get this from Nuxeo? i.e., Framework.getService(BinaryManger.class)
\r
119 // /** The temp file name. */
\r
120 //static String tempFileName = "sunset.jpg";
\r
122 // /** The file separator. */
\r
123 // static String fileSeparator = System.getProperty("file.separator");
\r
125 // /** The cur dir. */
\r
126 // static String curDir = System.getProperty("user.dir");
\r
129 * Instantiates a new nuxeo image utils.
\r
131 NuxeoImageUtils() {
\r
132 //empty constructor
\r
138 public static void loggerSetup() {
\r
142 static private BlobsCommon createBlobCommon(DocumentModel documentModel, Blob nuxeoBlob) {
\r
143 BlobsCommon result = new BlobsCommon();
\r
144 if (documentModel != null) {
\r
145 result.setMimeType(nuxeoBlob.getMimeType());
\r
146 result.setName(nuxeoBlob.getFilename());
\r
147 result.setLength(Long.toString(nuxeoBlob.getLength()));
\r
148 result.setRepositoryId(documentModel.getId());
\r
153 static private File getBlobFile(RepositoryInstance ri, DocumentModel documentModel, Blob blob) {
\r
154 DefaultBinaryManager binaryManager = null;
\r
155 RepositoryDescriptor descriptor = null;
\r
159 ServiceManager sm = (ServiceManager) Framework.getService(ServiceManager.class);
\r
160 ServiceDescriptor[] sd = sm.getServiceDescriptors();
\r
162 RepositoryService repositoryService1 = (RepositoryService) Framework.getRuntime().getComponent(
\r
163 RepositoryService.NAME);
\r
164 RepositoryService repositoryService2 = (RepositoryService) Framework.getRuntime().getService(
\r
165 RepositoryService.class);
\r
166 RepositoryService repositoryService3 = (RepositoryService) Framework.getService(
\r
167 RepositoryService.class);
\r
168 RepositoryService repositoryService4 = (RepositoryService) Framework.getLocalService(
\r
169 RepositoryService.class);
\r
170 ComponentManager componentManager1 = (ComponentManager) Framework.getService(ComponentManager.class);
\r
171 ComponentManager componentManager2 = (ComponentManager) Framework.getService(ComponentManagerImpl.class);
\r
174 // RepositoryManager repositoryManager2 = (RepositoryManager) Framework.getService(RepositoryManager.class);
\r
175 // Repository repository = repositoryManager2.getDefaultRepository();
\r
176 // Map<String, String> repositoryMap = repository.getProperties();
\r
177 // String streamURI = ri.getStreamURI(arg0)
\r
179 String repositoryName = documentModel.getRepositoryName();
\r
180 // RepositoryManager repositoryManager2 = (RepositoryManager) Framework.getService(RepositoryManager.class);
\r
181 RepositoryManager repositoryManager = repositoryService1.getRepositoryManager();
\r
182 descriptor = repositoryManager.getDescriptor(repositoryName);
\r
184 binaryManager = new DefaultBinaryManager();
\r
186 File storageDir = binaryManager.getStorageDir();
\r
187 // SQLBlob blob = (SQLBlob) doc.getPropertyValue("schema:blobField");
\r
188 File file = binaryManager.getFileForDigest(
\r
189 blob.getDigest(), false);
\r
191 // binaryManager = new DefaultBinaryManager();
\r
192 } catch (Exception e) {
\r
193 e.printStackTrace();
\r
197 binaryManager.initialize(
\r
198 SQLRepository.getDescriptor(descriptor));
\r
199 } catch (IOException e) {
\r
200 // TODO Auto-generated catch block
\r
201 e.printStackTrace();
\r
202 } catch (Exception e) {
\r
203 // TODO Auto-generated catch block
\r
204 e.printStackTrace();
\r
207 File storageDir = binaryManager.getStorageDir();
\r
208 // SQLBlob blob = (SQLBlob) documentModel.getPropertyValue("schema:blobField");
\r
209 File file = binaryManager.getFileForDigest(
\r
210 blob.getDigest(), false);
\r
216 * Returns a schema, given the name of a schema.
\r
218 * @param schemaName a schema name.
\r
219 * @return a schema.
\r
221 private static Schema getSchemaFromName(String schemaName) {
\r
222 SchemaManager schemaManager = null;
\r
224 schemaManager = Framework.getService(SchemaManager.class);
\r
225 } catch (Exception e) {
\r
226 // TODO Auto-generated catch block
\r
227 e.printStackTrace();
\r
229 return schemaManager != null ? schemaManager.getSchema(schemaName) : null;
\r
235 * @param nuxeoSession the nuxeo session
\r
239 static private Blob getBlob(RepositoryInstance nuxeoSession, String id) {
\r
240 Blob result = null;
\r
243 Repository repository = nuxeoSession.getRepository();
\r
244 // binaryManager.initialize(new RepositoryDescriptor());
\r
245 // binaryManager.getBinary("a4cac052ae0281979f2dcf5ab2e61a6c");
\r
246 // DocumentResolver.resolveReference(nuxeoSession, documentRef);
\r
247 //binaryManager = repository.getBinaryManager();
\r
248 // documentModel.getr
\r
249 } catch (Exception x) {
\r
250 x.printStackTrace();
\r
257 * Gets the type service.
\r
259 * @return the type service
\r
260 * @throws ClientException the client exception
\r
262 private static TypeManager getTypeService() throws ClientException {
\r
263 TypeManager typeService = null;
\r
265 typeService = Framework.getService(TypeManager.class);
\r
266 } catch (Exception e) {
\r
267 throw new ClientException(e);
\r
269 return typeService;
\r
275 * @param fis the fis
\r
276 * @return the bytes
\r
278 private static byte[] getBytes(InputStream fis) {
\r
279 ByteArrayOutputStream bos = new ByteArrayOutputStream();
\r
280 byte[] buf = new byte[128 * 1024];
\r
282 for (int readNum; (readNum = fis.read(buf)) != -1;) {
\r
283 bos.write(buf, 0, readNum);
\r
284 //no doubt here is 0
\r
285 /*Writes len bytes from the specified byte array starting at offset
\r
286 off to this byte array output stream.*/
\r
287 System.out.println("read " + readNum + " bytes,");
\r
289 } catch (IOException ex) {
\r
290 logger.error(ex.getMessage(), ex);
\r
292 byte[] bytes = bos.toByteArray();
\r
293 //bytes is the ByteArray we need
\r
298 * Creates the serializable blob.
\r
300 * @param fileInputStream the file input stream
\r
301 * @param filename the filename
\r
302 * @param mimeType the mime type
\r
305 private static Blob createSerializableBlob(InputStream fileInputStream,
\r
306 String filename, String mimeType) {
\r
309 // persisting the blob makes it possible to read the binary content
\r
310 // of the request stream several times (mimetype sniffing, digest
\r
311 // computation, core binary storage)
\r
312 byte[] bytes = getBytes(fileInputStream);
\r
313 blob = new ByteArrayBlob(bytes);
\r
315 if (filename != null) {
\r
316 filename = getCleanFileName(filename);
\r
318 blob.setFilename(filename);
\r
319 // mimetype detection
\r
320 MimetypeRegistry mimeService = Framework.getService(MimetypeRegistry.class);
\r
321 String detectedMimeType = mimeService.getMimetypeFromFilenameAndBlobWithDefault(
\r
322 filename, blob, null);
\r
323 if (detectedMimeType == null) {
\r
324 if (mimeType != null) {
\r
325 detectedMimeType = mimeType;
\r
328 detectedMimeType = "application/octet-stream";
\r
331 blob.setMimeType(detectedMimeType);
\r
332 } catch (MimetypeDetectionException e) {
\r
333 logger.error(String.format("could not fetch mimetype for file %s",
\r
335 } catch (Exception e) {
\r
336 logger.error("", e);
\r
342 * Creates a serializable blob from a stream, with filename and mimetype
\r
346 * Creates an in-memory blob if data is under 64K, otherwise constructs a
\r
347 * serializable FileBlob which stores data in a temporary file on the hard
\r
351 * @param file the input stream holding data
\r
352 * @param filename the file name. Will be set on the blob and will used for
\r
353 * mimetype detection.
\r
354 * @param mimeType the detected mimetype at upload. Can be null. Will be
\r
355 * verified by the mimetype service.
\r
358 private static Blob createStreamingBlob(InputStream file,
\r
359 String filename, String mimeType) {
\r
362 // persisting the blob makes it possible to read the binary content
\r
363 // of the request stream several times (mimetype sniffing, digest
\r
364 // computation, core binary storage)
\r
365 blob = StreamingBlob.createFromStream(file, mimeType).persist();
\r
367 if (filename != null) {
\r
368 filename = getCleanFileName(filename);
\r
370 blob.setFilename(filename);
\r
371 // mimetype detection
\r
372 MimetypeRegistry mimeService = Framework.getService(MimetypeRegistry.class);
\r
373 String detectedMimeType = mimeService.getMimetypeFromFilenameAndBlobWithDefault(
\r
374 filename, blob, null);
\r
375 if (detectedMimeType == null) {
\r
376 if (mimeType != null) {
\r
377 detectedMimeType = mimeType;
\r
380 detectedMimeType = "application/octet-stream";
\r
383 blob.setMimeType(detectedMimeType);
\r
384 } catch (MimetypeDetectionException e) {
\r
385 logger.error(String.format("could not fetch mimetype for file %s",
\r
387 } catch (IOException e) {
\r
388 logger.error("", e);
\r
389 } catch (Exception e) {
\r
390 logger.error("", e);
\r
396 * Returns a clean filename, stripping upload path on client side.
\r
401 * @param filename the filename
\r
402 * @return the clean file name
\r
404 private static String getCleanFileName(String filename) {
\r
406 int lastWinSeparator = filename.lastIndexOf('\\');
\r
407 int lastUnixSeparator = filename.lastIndexOf('/');
\r
408 int lastSeparator = Math.max(lastWinSeparator, lastUnixSeparator);
\r
409 if (lastSeparator != -1) {
\r
410 res = filename.substring(lastSeparator + 1, filename.length());
\r
418 * Gets Nuxeo's file manager service.
\r
420 * @return the file manager service
\r
421 * @throws ClientException the client exception
\r
423 private static FileManager getFileManagerService() throws ClientException {
\r
424 FileManager result = null;
\r
426 result = Framework.getService(FileManager.class);
\r
427 } catch (Exception e) {
\r
428 String msg = "Unable to get Nuxeo's FileManager service.";
\r
429 logger.error(msg, e);
\r
430 throw new ClientException("msg", e);
\r
436 * Creates the picture.
\r
438 * @param ctx the ctx
\r
439 * @param repoSession the repo session
\r
440 * @param filePath the file path
\r
441 * @return the string
\r
443 public static BlobsCommon createPicture(ServiceContext ctx,
\r
444 RepositoryInstance repoSession,
\r
445 BlobInput blobInput) {
\r
446 BlobsCommon result = null;
\r
449 File blobFile = blobInput.getBlobFile();
\r
450 String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
\r
451 DocumentRef nuxeoWspace = new IdRef(nuxeoWspaceId);
\r
452 DocumentModel wspaceDoc = repoSession.getDocument(nuxeoWspace);
\r
454 FileInputStream inputStream = new FileInputStream(blobFile);
\r
455 if (inputStream != null) {
\r
456 result = createImage(repoSession, wspaceDoc,
\r
457 inputStream, blobFile.getName(), null);
\r
459 } catch (Exception e) {
\r
460 logger.error("Could not create image blob", e);
\r
467 * Creates the image blob.
\r
469 * @param nuxeoSession the nuxeo session
\r
470 * @param blobLocation the blob location
\r
471 * @param file the file
\r
472 * @param fileName the file name
\r
473 * @param mimeType the mime type
\r
474 * @return the string
\r
476 static public BlobsCommon createImage(RepositoryInstance nuxeoSession,
\r
477 DocumentModel blobLocation,
\r
481 BlobsCommon result = null;
\r
484 Blob fileBlob = createStreamingBlob(file, fileName, mimeType);
\r
485 String digestAlgorithm = getFileManagerService().getDigestAlgorithm(); //Need some way on initializing the FileManager with a call.
\r
486 DocumentModel documentModel = getFileManagerService().createDocumentFromBlob(nuxeoSession,
\r
487 fileBlob, blobLocation.getPathAsString(), true, fileName);
\r
488 result = createBlobCommon(documentModel, fileBlob);
\r
489 } catch (Exception e) {
\r
491 logger.error("Could not create new image blob", e);
\r
499 * Gets the picture.
\r
501 * @param ctx the ctx
\r
502 * @param repoSession the repo session
\r
503 * @param blobId the blob id
\r
504 * @param derivativeTerm the derivative term
\r
505 * @return the picture
\r
507 public static InputStream getPicture(ServiceContext ctx, RepositoryInstance repoSession,
\r
508 String blobId, String derivativeTerm) {
\r
509 return getImage(repoSession, blobId, derivativeTerm);
\r
515 * @param repoSession the repo session
\r
516 * @param repositoryId the repository id
\r
517 * @param derivativeTerm the derivative term
\r
518 * @return the image
\r
520 static public InputStream getImage(RepositoryInstance repoSession,
\r
521 String repositoryId, String derivativeTerm) {
\r
522 InputStream result = null;
\r
525 IdRef documentRef = new IdRef(repositoryId);
\r
526 DocumentModel documentModel = repoSession.getDocument(documentRef);
\r
528 // documentModel.getAdapter(PictureResourceAdapter.class);
\r
529 // DocumentBlobHolder docBlobHolder = (DocumentBlobHolder)documentModel.getAdapter(BlobHolder.class);
\r
530 // Blob docBlob = docBlobHolder.getBlob();
\r
531 // Map<String,Serializable> blobHolderProps = docBlobHolder.getProperties();
\r
532 // String filePath = docBlobHolder.getFilePath();
\r
533 // List<Blob> docBlobs = docBlobHolder.getBlobs();
\r
535 PictureBlobHolderFactory blobHolderFactory = new PictureBlobHolderFactory();
\r
536 PictureBlobHolder pictureBlobHolder = (PictureBlobHolder) blobHolderFactory.getBlobHolder(documentModel);
\r
537 Blob pictureBlob = null;
\r
538 if (derivativeTerm != null) {
\r
539 pictureBlob = pictureBlobHolder.getBlob(derivativeTerm);
\r
541 pictureBlob = pictureBlobHolder.getBlob();
\r
544 InputStream remoteStream = pictureBlob.getStream();
\r
545 BufferedInputStream bufferedInputStream = new BufferedInputStream(remoteStream);
\r
546 result = bufferedInputStream;
\r
547 // File tmpFile = FileUtils.createTmpFile(remoteStream);
\r
548 // result = new FileInputStream(tmpFile);
\r
549 } catch (Exception e) {
\r
550 logger.error(e.getMessage(), e);
\r
558 stream = new FileInputStream(fileUploadHolder.getTempFile());
\r
560 public String addFile(InputStream fileUpload, String fileName)
\r
561 fileName = FileUtils.getCleanFileName(fileName);
\r
562 DocumentModel currentDocument = navigationContext.getCurrentDocument();
\r
563 String path = currentDocument.getPathAsString();
\r
564 Blob blob = FileUtils.createSerializableBlob(fileUpload, fileName,
\r
567 DocumentModel createdDoc = getFileManagerService().createDocumentFromBlob(
\r
568 documentManager, blob, path, true, fileName);
\r
569 eventManager.raiseEventsOnDocumentSelected(createdDoc);
\r
571 protected FileManager fileManager;
\r
573 protected FileManager getFileManagerService() throws ClientException {
\r
574 if (fileManager == null) {
\r
576 fileManager = Framework.getService(FileManager.class);
\r
577 } catch (Exception e) {
\r
578 log.error("Unable to get FileManager service ", e);
\r
579 throw new ClientException("Unable to get FileManager service ",
\r
583 return fileManager;
\r
588 RepositoryService repositoryService = (RepositoryService) Framework.getRuntime().getComponent(
\r
589 RepositoryService.NAME);
\r
590 RepositoryManager repositoryManager = repositoryService.getRepositoryManager();
\r
591 RepositoryDescriptor descriptor = repositoryManager.getDescriptor(repositoryName);
\r
592 DefaultBinaryManager binaryManager = new DefaultBinaryManager(
\r
593 SQLRepository.getDescriptor(descriptor)));
\r
595 File storageDir = binaryManager.getStorageDir();
\r
596 SQLBlob blob = (SQLBlob) doc.getPropertyValue("schema:blobField");
\r
597 File file = binaryManager.getFileForDigest(
\r
598 blob.getBinary().getDigest(), false);
\r
602 RepositoryInstance.getStreamURI()
\r
604 String getStreamURI(String blobPropertyId)
\r
605 throws ClientException
\r
607 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.
\r
609 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.
\r
611 After the client has called this method, it will be able to download the stream using streaming server API.
\r
614 an URI identifying the remote stream
\r
621 A blob contains usually large data.
\r
623 Document fields holding Blob data are by default fetched in a lazy manner.
\r
625 A Blob object hides the data source and it also describes data properties like the encoding or mime-type.
\r
627 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.
\r
629 When retrieving the content from a document, it will be returned as source content instead of returning the content bytes.
\r
631 The same is true when setting the content for a document: you set a content source and not directly the content bytes. Ex:
\r
633 File file = new File("/tmp/index.html");
\r
634 FileBlob fb = new FileBlob(file);
\r
635 fb.setMimeType("text/html");
\r
636 fb.setEncoding("UTF-8"); // this specifies that content bytes will be stored as UTF-8
\r
637 document.setProperty("file", "content", fb);
\r
640 Then you may want to retrieve the content as follow:
\r
642 Blob blob = document.getProperty("file:content");
\r
643 htmlDoc = blob.getString(); // the content is decoded from UTF-8 into a java string
\r