]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
8c0d3a85383d33d09f991ce383d2cb75d9cc006a
[tmp/jakarta-migration.git] /
1 /**
2  *  This document is a part of the source code and related artifacts
3  *  for CollectionSpace, an open source collections management system
4  *  for museums and related institutions:
5
6  *  http://www.collectionspace.org
7  *  http://wiki.collectionspace.org
8
9  *  Copyright 2009 University of California at Berkeley
10
11  *  Licensed under the Educational Community License (ECL), Version 2.0.
12  *  You may not use this file except in compliance with this License.
13
14  *  You may obtain a copy of the ECL 2.0 License at
15
16  *  https://source.collectionspace.org/collection-space/LICENSE.txt
17
18  *  Unless required by applicable law or agreed to in writing, software
19  *  distributed under the License is distributed on an "AS IS" BASIS,
20  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  *  See the License for the specific language governing permissions and
22  *  limitations under the License.
23  */
24 package org.collectionspace.services.blob.nuxeo;
25
26 import org.collectionspace.services.blob.BlobsCommon;
27 import org.collectionspace.services.nuxeo.client.java.DocHandlerBase;
28 import org.collectionspace.services.client.BlobClient;
29 import org.collectionspace.services.client.PayloadOutputPart;
30 import org.collectionspace.services.client.PoxPayloadIn;
31 import org.collectionspace.services.client.PoxPayloadOut;
32 import org.collectionspace.services.common.blob.BlobInput;
33 import org.collectionspace.services.common.blob.BlobOutput;
34 import org.collectionspace.services.common.blob.BlobUtil;
35 import org.collectionspace.services.common.context.ServiceContext;
36 import org.collectionspace.services.common.document.DocumentUtils;
37 import org.collectionspace.services.common.document.DocumentWrapper;
38 import org.collectionspace.services.common.imaging.nuxeo.NuxeoBlobUtils;
39 import org.collectionspace.services.config.service.ListResultField;
40 import org.collectionspace.services.config.service.ObjectPartType;
41 import org.collectionspace.services.jaxb.BlobJAXBSchema;
42 import org.collectionspace.services.nuxeo.client.java.CommonList;
43
44
45 import org.collectionspace.services.nuxeo.client.java.RepositoryInstanceInterface;
46 import org.nuxeo.ecm.core.api.ClientException;
47 import org.nuxeo.ecm.core.api.DocumentModel;
48 import org.nuxeo.ecm.core.api.IdRef;
49 import org.nuxeo.ecm.core.api.repository.RepositoryInstance;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 import java.util.List;
54 import java.util.Map;
55
56 import javax.ws.rs.core.MultivaluedMap;
57
58 import org.dom4j.Element;
59
60 /**
61  * The Class BlobDocumentModelHandler.
62  */
63 public class BlobDocumentModelHandler
64 extends DocHandlerBase<BlobsCommon> {
65
66         /** The logger. */
67         private final Logger logger = LoggerFactory.getLogger(BlobDocumentModelHandler.class);
68
69     //==============================================================================
70
71         private String getDerivativePathBase(DocumentModel docModel) {
72                 return getServiceContextPath() + docModel.getName() + "/" +
73                         BlobInput.URI_DERIVATIVES_PATH + "/";
74         }
75
76         private BlobsCommon getCommonPartProperties(DocumentModel docModel) throws Exception {
77                 String label = getServiceContext().getCommonPartLabel();
78                 BlobsCommon result = new BlobsCommon();
79                 
80                 result.setData((String) 
81                                 docModel.getProperty(label, BlobJAXBSchema.data));
82                 result.setDigest((String)
83                                 docModel.getProperty(label, BlobJAXBSchema.digest));
84                 result.setEncoding((String)
85                                 docModel.getProperty(label, BlobJAXBSchema.encoding));
86                 result.setLength((String)
87                                 docModel.getProperty(label, BlobJAXBSchema.length));
88                 result.setMimeType((String)
89                                 docModel.getProperty(label, BlobJAXBSchema.mimeType));
90                 result.setName((String)
91                                 docModel.getProperty(label, BlobJAXBSchema.name));
92                 result.setRepositoryId((String)
93                                 docModel.getProperty(label, BlobJAXBSchema.repositoryId));
94                 result.setUri(getServiceContextPath() + docModel.getName() + "/" +
95                                 BlobInput.URI_CONTENT_PATH);
96                 
97                 return result;
98         }
99         
100         private void setCommonPartProperties(DocumentModel documentModel,
101                         BlobsCommon blobsCommon) throws ClientException {
102                 try {
103                         String schemaName = getServiceContext().getCommonPartLabel();
104                         PayloadOutputPart outputPart = new PayloadOutputPart(schemaName, blobsCommon);
105                         Element element = outputPart.asElement();
106                         Map<String, Object> propertyMap = DocumentUtils.parseProperties(schemaName, element, getServiceContext());
107                         documentModel.setProperties(schemaName, propertyMap);
108                 } catch (Exception e) {
109                         throw new ClientException(e);
110                 }               
111         }
112         
113         private void extractMetadata(String nuxeoImageID, String metadataLabel) {               
114         Map<String, ObjectPartType> partsMetaMap = getServiceContext().getPartsMetadata();
115         ObjectPartType partMeta = partsMetaMap.get(metadataLabel);
116
117         if (partMeta != null) {
118                 RepositoryInstanceInterface repoSession = this.getRepositorySession();
119                         if (nuxeoImageID != null && nuxeoImageID.isEmpty() == false) try {
120                                 IdRef documentRef = new IdRef(nuxeoImageID);
121                                 DocumentModel docModel = repoSession.getDocument(documentRef);
122                     Map<String, Object> unQObjectProperties = extractPart(docModel, metadataLabel);
123                     if (unQObjectProperties != null) {
124                         addOutputPart(unQObjectProperties, metadataLabel, partMeta);
125                     }
126                         } catch (Exception e) {
127                                 logger.warn("Metadata extraction failed: " + e.getMessage());
128                         }
129         } else {
130                 logger.warn("Metadata extraction failed: Could not find tenant binding for schema type = " + metadataLabel);
131         }
132         }
133
134         /* (non-Javadoc)
135          * @see org.collectionspace.services.nuxeo.client.java.DocumentModelHandler#extractAllParts(org.collectionspace.services.common.document.DocumentWrapper)
136          */
137         @Override
138         public void extractAllParts(DocumentWrapper<DocumentModel> wrapDoc)
139                         throws Exception {
140                 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = this.getServiceContext();
141                 BlobInput blobInput = BlobUtil.getBlobInput(ctx); // the blobInput was set by the Blob JAX-RS resource code and put into the service context
142                 RepositoryInstanceInterface repoSession = this.getRepositorySession();
143                 DocumentModel docModel = wrapDoc.getWrappedObject();
144                 BlobsCommon blobsCommon = this.getCommonPartProperties(docModel);               
145                 String blobRepositoryId = blobsCommon.getRepositoryId(); //cache the value to pass to the blob retriever
146                 //
147                 // We're being asked for a list of blob derivatives, not the payload for a blob record.  FIXME: REM - This should be handled in a class called DerivativeDocumentHandler (need to create).
148                 //
149                 if (blobInput.isDerivativeListRequested() == true) {
150                 List<ListResultField> resultsFields = getListItemsArray();
151                         CommonList blobsCommonList = NuxeoBlobUtils.getBlobDerivatives( //FIXME: REM - Need to replace "NuxeoImageUtils" with something more general like "BlobUtils" since we may support other blob types.
152                                         repoSession, blobRepositoryId, resultsFields, getDerivativePathBase(docModel));
153 //                      ctx.setProperty(BlobInput.BLOB_DERIVATIVE_LIST_KEY, blobsCommonList);
154                         blobInput.setDerivativeList(blobsCommonList);
155                         return;  //FIXME: REM - Don't like this exit point.  Perhaps derivatives should be a sub-resource with its own DerivativeDocumentHandler doc handler?
156                 }               
157
158                 String derivativeTerm = blobInput.getDerivativeTerm();
159                 Boolean getContentFlag = blobInput.isContentRequested();
160                 //
161                 // If we're being asked for either the content of the blob, the content of a derivative, or the payload for a derivative then
162                 // fall into this block of code.  Otherwise, we'll just call our parent to deal with a plain-old-blob payload.
163                 //
164                 if (derivativeTerm != null || getContentFlag == true) {
165                         StringBuffer mimeTypeBuffer = new StringBuffer();
166                         BlobOutput blobOutput = NuxeoBlobUtils.getBlobOutput(ctx, repoSession,
167                                         blobRepositoryId, derivativeTerm, getContentFlag, mimeTypeBuffer);
168                         if (getContentFlag == true) {
169                                 if (blobOutput != null) {
170                                         blobInput.setContentStream(blobOutput.getBlobInputStream());
171                                 } else {
172                                         // If we can't find the blob's content, we'll return a "missing document" image
173                                         blobInput.setContentStream(NuxeoBlobUtils.getResource(NuxeoBlobUtils.DOCUMENT_MISSING_PLACEHOLDER_IMAGE));
174                                         mimeTypeBuffer.append(NuxeoBlobUtils.MIME_JPEG);
175                                 }
176                         }
177         
178                         if (derivativeTerm != null) {
179                                 // reset 'blobsCommon' if we have a derivative request
180                                 blobsCommon = blobOutput.getBlobsCommon();
181                                 blobsCommon.setUri(getDerivativePathBase(docModel) +
182                                                 derivativeTerm + "/" + BlobInput.URI_CONTENT_PATH);                             
183                         }
184                         
185                         String mimeType = mimeTypeBuffer.toString();
186                         if (mimeType != null && !mimeType.isEmpty()) { // MIME type for derivatives might be different from original
187                                 blobInput.setMimeType(mimeType);
188                                 blobsCommon.setMimeType(mimeType);
189                         } else {
190                                 blobInput.setMimeType(blobsCommon.getMimeType());  // Set the MIME type to the one in blobsCommon
191                         }
192                         
193                         blobsCommon.setRepositoryId(null); //hide the repository id from the GET results payload since it is private
194                         this.setCommonPartProperties(docModel, blobsCommon);
195                         // finish extracting the other parts by calling the parent
196                 } else {
197                         extractMetadata(blobRepositoryId, NuxeoBlobUtils.SCHEMA_IMAGE_METADATA);
198                         extractMetadata(blobRepositoryId, NuxeoBlobUtils.SCHEMA_IPTC);
199                 }
200                 
201                 //
202                 // Hide the Nuxeo repository ID of the Nuxeo blob since this is private
203                 //
204                 docModel.setProperty(ctx.getCommonPartLabel(), BlobJAXBSchema.repositoryId, null);      
205                 super.extractAllParts(wrapDoc);
206         }
207
208         @Override
209         public void fillAllParts(DocumentWrapper<DocumentModel> wrapDoc, Action action) throws Exception {
210                 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx = this.getServiceContext();
211                 BlobInput blobInput = BlobUtil.getBlobInput(ctx); // The blobInput should have been put into the context by the Blob or Media resource
212                 if (blobInput != null && blobInput.getBlobFile() != null) {             
213                         boolean purgeOriginal = false;
214                         MultivaluedMap<String, String> queryParams = ctx.getQueryParams();
215                         String purgeOriginalStr = queryParams.getFirst(BlobClient.BLOB_PURGE_ORIGINAL);
216                         if (purgeOriginalStr != null && purgeOriginalStr.isEmpty() == false) { // Find our if the caller wants us to purge/delete the original
217                                 purgeOriginal = true;
218                         }
219                         //
220                         // If blobInput has a file then we just received a multipart/form-data file post or a URI query parameter
221                         //
222                         DocumentModel documentModel = wrapDoc.getWrappedObject();
223                         RepositoryInstanceInterface repoSession = this.getRepositorySession();
224                 
225                         BlobsCommon blobsCommon = NuxeoBlobUtils.createBlobInRepository(ctx, repoSession, blobInput, purgeOriginal, true);
226                         blobInput.setBlobCsid(documentModel.getName()); //Assumption here is that the documentModel "name" field is storing a CSID
227
228                 PoxPayloadIn input = ctx.getInput();
229                 //
230                 // If the input payload is null, then we're creating a new blob from a post or a uri.  This means there
231                 // is no "input" payload for our framework to process.  Therefore we need to synthesize a payload from
232                 // the BlobsCommon instance we just filled out.
233                 //
234                 if (input == null) {
235                         PoxPayloadOut output = new PoxPayloadOut(BlobClient.SERVICE_PAYLOAD_NAME);
236                         PayloadOutputPart commonPart = new PayloadOutputPart(BlobClient.SERVICE_COMMON_PART_NAME, blobsCommon);
237                         output.addPart(commonPart);
238                         input = new PoxPayloadIn(output.toXML());
239                         ctx.setInput(input);
240                 } else {
241                         // At this point, we've created a blob document in the Nuxeo repository.  Usually, we use the blob to create and instance of BlobsCommon and use
242                         // that to populate the resource record.  However, since the "input" var is not null the requester provided their own resource record data
243                         // so we'll use it rather than deriving one from the blob.
244                         logger.warn("A resource record payload was provided along with the actually blob binary file.  This payload is usually derived from the blob binary.  Since a payload was provided, we're creating the resource record from the payload and not from the corresponding blob binary." +
245                                         " The data in blob resource record fields may not correspond completely with the persisted blob binary file.");
246                 }               
247                 }
248
249                 super.fillAllParts(wrapDoc, action);
250         }    
251 }
252