]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
15f9b03620165b2df7d3a70d7bf473629b8f05b9
[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 package org.collectionspace.services.nuxeo.client.java;
19
20 import java.util.UUID;
21
22 import org.collectionspace.services.common.context.ServiceContext;
23 import org.collectionspace.services.common.document.BadRequestException;
24 import org.collectionspace.services.common.document.DocumentException;
25 import org.collectionspace.services.common.document.DocumentFilter;
26 import org.collectionspace.services.common.document.DocumentHandler;
27 import org.collectionspace.services.common.document.DocumentNotFoundException;
28 import org.collectionspace.services.common.repository.RepositoryClient;
29 import org.collectionspace.services.common.document.DocumentHandler.Action;
30 import org.collectionspace.services.common.document.DocumentWrapper;
31 import org.collectionspace.services.common.document.DocumentWrapperImpl;
32 import org.collectionspace.services.nuxeo.util.NuxeoUtils;
33 import org.nuxeo.common.utils.IdUtils;
34 import org.nuxeo.ecm.core.api.ClientException;
35 import org.nuxeo.ecm.core.api.DocumentModel;
36 import org.nuxeo.ecm.core.api.DocumentModelList;
37 import org.nuxeo.ecm.core.api.DocumentRef;
38 import org.nuxeo.ecm.core.api.IdRef;
39 import org.nuxeo.ecm.core.api.PathRef;
40 import org.nuxeo.ecm.core.api.repository.RepositoryInstance;
41 import org.nuxeo.ecm.core.client.NuxeoClient;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 /**
46  * RepositoryJavaClient is used to perform CRUD operations on documents in Nuxeo
47  * repository using Remote Java APIs. It uses @see DocumentHandler as IOHandler
48  * with the client.
49  * 
50  * $LastChangedRevision: $ $LastChangedDate: $
51  */
52 public class RepositoryJavaClient implements RepositoryClient {
53
54     private final Logger logger = LoggerFactory.getLogger(RepositoryJavaClient.class);
55
56     public RepositoryJavaClient() {
57     }
58
59     /**
60      * create document in the Nuxeo repository
61      *
62      * @param ctx service context under which this method is invoked
63      * @param docType
64      *            of the document created
65      * @param handler
66      *            should be used by the caller to provide and transform the
67      *            document
68      * @return id in repository of the newly created document
69      * @throws DocumentException
70      */
71     @Override
72     public String create(ServiceContext ctx,
73             DocumentHandler handler) throws BadRequestException,
74             DocumentException {
75
76         if (ctx.getDocumentType() == null) {
77             throw new IllegalArgumentException(
78                     "RepositoryJavaClient.create: docType is missing");
79         }
80         if (handler == null) {
81             throw new IllegalArgumentException(
82                     "RepositoryJavaClient.create: handler is missing");
83         }
84         String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
85         if (nuxeoWspaceId == null) {
86             throw new DocumentNotFoundException(
87                     "Unable to find workspace for service " + ctx.getServiceName() +
88                     " check if the workspace exists in the Nuxeo repository");
89         }
90         RepositoryInstance repoSession = null;
91         try {
92             handler.prepare(Action.CREATE);
93             repoSession = getRepositorySession();
94             DocumentRef nuxeoWspace = new IdRef(nuxeoWspaceId);
95             DocumentModel wspaceDoc = repoSession.getDocument(nuxeoWspace);
96             String wspacePath = wspaceDoc.getPathAsString();
97             //give our own ID so PathRef could be constructed later on
98             String id = IdUtils.generateId(UUID.randomUUID().toString());
99             // create document model
100             DocumentModel doc = repoSession.createDocumentModel(wspacePath, id,
101                     ctx.getDocumentType());
102             ((DocumentModelHandler) handler).setRepositorySession(repoSession);
103             DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
104             handler.handle(Action.CREATE, wrapDoc);
105             // create document with documentmodel
106             doc = repoSession.createDocument(doc);
107             repoSession.save();
108             handler.complete(Action.CREATE, wrapDoc);
109             return id;
110         } catch (Exception e) {
111             if (logger.isDebugEnabled()) {
112                 logger.debug("Caught exception ", e);
113             }
114             throw new DocumentException(e);
115         } finally {
116             if (repoSession != null) {
117                 releaseRepositorySession(repoSession);
118             }
119         }
120
121     }
122
123     /**
124      * get document from the Nuxeo repository
125      * @param ctx service context under which this method is invoked
126      * @param id
127      *            of the document to retrieve
128      * @param handler
129      *            should be used by the caller to provide and transform the
130      *            document
131      * @throws DocumentException
132      */
133     @Override
134     public void get(ServiceContext ctx, String id, DocumentHandler handler)
135             throws DocumentNotFoundException, DocumentException {
136
137         if (handler == null) {
138             throw new IllegalArgumentException(
139                     "RepositoryJavaClient.get: handler is missing");
140         }
141         RepositoryInstance repoSession = null;
142
143         try {
144             handler.prepare(Action.GET);
145             repoSession = getRepositorySession();
146             DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
147             DocumentModel doc = null;
148             try {
149                 doc = repoSession.getDocument(docRef);
150             } catch (ClientException ce) {
151                 String msg = "could not find document with id=" + id;
152                 logger.error(msg, ce);
153                 throw new DocumentNotFoundException(msg, ce);
154             }
155             //set reposession to handle the document
156             ((DocumentModelHandler) handler).setRepositorySession(repoSession);
157             DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
158             handler.handle(Action.GET, wrapDoc);
159             handler.complete(Action.GET, wrapDoc);
160         } catch (IllegalArgumentException iae) {
161             throw iae;
162         } catch (DocumentException de) {
163             throw de;
164         } catch (Exception e) {
165             if (logger.isDebugEnabled()) {
166                 logger.debug("Caught exception ", e);
167             }
168             throw new DocumentException(e);
169         } finally {
170             if (repoSession != null) {
171                 releaseRepositorySession(repoSession);
172             }
173         }
174     }
175
176     /**
177      * getAll get all documents for an entity entity service from the Nuxeo
178      * repository
179      *
180      * @param ctx service context under which this method is invoked
181      * @param handler
182      *            should be used by the caller to provide and transform the
183      *            document
184      * @throws DocumentException
185      */
186     @Override
187     public void getAll(ServiceContext ctx, DocumentHandler handler)
188             throws DocumentNotFoundException, DocumentException {
189         if (handler == null) {
190             throw new IllegalArgumentException(
191                     "RepositoryJavaClient.getAll: handler is missing");
192         }
193         String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
194         if (nuxeoWspaceId == null) {
195             throw new DocumentNotFoundException(
196                     "Unable to find workspace for service " +
197                     ctx.getServiceName() +
198                     " check if the workspace exists in the Nuxeo repository");
199         }
200         RepositoryInstance repoSession = null;
201
202         try {
203             handler.prepare(Action.GET_ALL);
204             repoSession = getRepositorySession();
205             DocumentRef wsDocRef = new IdRef(nuxeoWspaceId);
206             DocumentModelList docList = repoSession.getChildren(wsDocRef);
207             //set reposession to handle the document
208             ((DocumentModelHandler) handler).setRepositorySession(repoSession);
209             DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
210             handler.handle(Action.GET_ALL, wrapDoc);
211             handler.complete(Action.GET_ALL, wrapDoc);
212         } catch (DocumentException de) {
213             throw de;
214         } catch (Exception e) {
215             if (logger.isDebugEnabled()) {
216                 logger.debug("Caught exception ", e);
217             }
218             throw new DocumentException(e);
219         } finally {
220             if (repoSession != null) {
221                 releaseRepositorySession(repoSession);
222             }
223         }
224     }
225
226     /**
227      * getFiltered get all documents for an entity service from the Document repository,
228      * given filter parameters specified by the handler. 
229      * @param ctx service context under which this method is invoked
230      * @param handler should be used by the caller to provide and transform the document
231      * @throws DocumentNotFoundException if workspace not found
232      * @throws DocumentException
233      */
234     public void getFiltered(ServiceContext ctx, DocumentHandler handler)
235             throws DocumentNotFoundException, DocumentException {
236         if (handler == null) {
237             throw new IllegalArgumentException(
238                     "RepositoryJavaClient.getFiltered: handler is missing");
239         }
240         DocumentFilter docFilter = handler.getDocumentFilter();
241         if (docFilter == null) {
242             throw new IllegalArgumentException(
243                     "RepositoryJavaClient.getFiltered: handler has no Filter specified");
244         }
245         String docType = ctx.getDocumentType();
246         if (docType == null) {
247             throw new DocumentNotFoundException(
248                     "Unable to find DocumentType for service " + ctx.getServiceName());
249         }
250         String domain = ctx.getRepositoryDomainName();
251         if (domain == null) {
252             throw new DocumentNotFoundException(
253                     "Unable to find Domain for service " + ctx.getServiceName());
254         }
255         RepositoryInstance repoSession = null;
256         try {
257             handler.prepare(Action.GET_ALL);
258             repoSession = getRepositorySession();
259             StringBuilder query = new StringBuilder("SELECT * FROM ");
260             query.append(docType);
261             String where = docFilter.getWhereClause();
262             // TODO This is a slow method for tenant-filter
263             // We should make this a property that is indexed.
264             query.append(" WHERE ecm:path STARTSWITH '/" + domain + "'");
265             if ((null != where) && (where.length() > 0)) {
266 //              query.append(" AND " + where);
267                 query.append(" AND " + where + "AND ecm:isProxy = 0");                
268             }
269             DocumentModelList docList = null;
270             if ((docFilter.getOffset() > 0) || (docFilter.getPageSize() > 0)) {
271                 docList = repoSession.query(query.toString(), null,
272                         docFilter.getPageSize(), docFilter.getOffset(), false);
273             } else {
274                 docList = repoSession.query(query.toString());
275             }
276             //set repoSession to handle the document
277             ((DocumentModelHandler) handler).setRepositorySession(repoSession);
278             DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
279             handler.handle(Action.GET_ALL, wrapDoc);
280             handler.complete(Action.GET_ALL, wrapDoc);
281         } catch (DocumentException de) {
282             throw de;
283         } catch (Exception e) {
284             if (logger.isDebugEnabled()) {
285                 logger.debug("Caught exception ", e);
286             }
287             throw new DocumentException(e);
288         } finally {
289             if (repoSession != null) {
290                 releaseRepositorySession(repoSession);
291             }
292         }
293     }
294
295     /**
296      * update given document in the Nuxeo repository
297      *
298      * @param ctx service context under which this method is invoked
299      * @param id
300      *            of the document
301      * @param handler
302      *            should be used by the caller to provide and transform the
303      *            document
304      * @throws DocumentException
305      */
306     @Override
307     public void update(ServiceContext ctx, String id, DocumentHandler handler)
308             throws BadRequestException, DocumentNotFoundException,
309             DocumentException {
310         if (handler == null) {
311             throw new IllegalArgumentException(
312                     "RepositoryJavaClient.update: handler is missing");
313         }
314         RepositoryInstance repoSession = null;
315         try {
316             handler.prepare(Action.UPDATE);
317             repoSession = getRepositorySession();
318             DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
319             DocumentModel doc = null;
320             try {
321                 doc = repoSession.getDocument(docRef);
322             } catch (ClientException ce) {
323                 String msg = "Could not find document to update with id=" + id;
324                 logger.error(msg, ce);
325                 throw new DocumentNotFoundException(msg, ce);
326             }
327             //set reposession to handle the document
328             ((DocumentModelHandler) handler).setRepositorySession(repoSession);
329             DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
330             handler.handle(Action.UPDATE, wrapDoc);
331             repoSession.saveDocument(doc);
332             repoSession.save();
333             handler.complete(Action.UPDATE, wrapDoc);
334         } catch (DocumentException de) {
335             throw de;
336         } catch (Exception e) {
337             if (logger.isDebugEnabled()) {
338                 logger.debug("Caught exception ", e);
339             }
340             throw new DocumentException(e);
341         } finally {
342             if (repoSession != null) {
343                 releaseRepositorySession(repoSession);
344             }
345         }
346     }
347
348     /**
349      * delete a document from the Nuxeo repository
350      * @param ctx service context under which this method is invoked
351      * @param id
352      *            of the document
353      * @throws DocumentException
354      */
355     @Override
356     public void delete(ServiceContext ctx, String id) throws DocumentNotFoundException,
357             DocumentException {
358
359         if (logger.isDebugEnabled()) {
360             logger.debug("deleting document with id=" + id);
361         }
362         RepositoryInstance repoSession = null;
363         try {
364             repoSession = getRepositorySession();
365             DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
366             try {
367                 repoSession.removeDocument(docRef);
368             } catch (ClientException ce) {
369                 String msg = "could not find document to delete with id=" + id;
370                 logger.error(msg, ce);
371                 throw new DocumentNotFoundException(msg, ce);
372             }
373             repoSession.save();
374         } catch (DocumentException de) {
375             throw de;
376         } catch (Exception e) {
377             if (logger.isDebugEnabled()) {
378                 logger.debug("Caught exception ", e);
379             }
380             throw new DocumentException(e);
381         } finally {
382             if (repoSession != null) {
383                 releaseRepositorySession(repoSession);
384             }
385         }
386     }
387
388     @Override
389     public String createWorkspace(String tenantDomain, String workspaceName) throws Exception {
390         RepositoryInstance repoSession = null;
391         String workspaceId = null;
392         try {
393             repoSession = getRepositorySession();
394             DocumentRef docRef = new PathRef(
395                     "/" + tenantDomain +
396                     "/" + "workspaces");
397             DocumentModel parent = repoSession.getDocument(docRef);
398             DocumentModel doc = repoSession.createDocumentModel(parent.getPathAsString(),
399                     workspaceName, "Workspace");
400             doc.setPropertyValue("dc:title", workspaceName);
401             doc.setPropertyValue("dc:description", "A CollectionSpace workspace for " +
402                     workspaceName);
403             doc = repoSession.createDocument(doc);
404             workspaceId = doc.getId();
405             repoSession.save();
406             if (logger.isDebugEnabled()) {
407                 logger.debug("created workspace name=" + workspaceName +
408                         " id=" + workspaceId);
409             }
410         } catch (Exception e) {
411             if (logger.isDebugEnabled()) {
412                 logger.debug("createWorkspace caught exception ", e);
413             }
414             throw e;
415         } finally {
416             if (repoSession != null) {
417                 releaseRepositorySession(repoSession);
418             }
419         }
420         return workspaceId;
421     }
422
423     @Override
424     public String getWorkspaceId(String tenantDomain, String workspaceName) throws Exception {
425         String workspaceId = null;
426         RepositoryInstance repoSession = null;
427         try {
428             repoSession = getRepositorySession();
429             DocumentRef docRef = new PathRef(
430                     "/" + tenantDomain +
431                     "/" + "workspaces" +
432                     "/" + workspaceName);
433             DocumentModel workspace = repoSession.getDocument(docRef);
434             workspaceId = workspace.getId();
435         } catch (DocumentException de) {
436             throw de;
437         } catch (Exception e) {
438             if (logger.isDebugEnabled()) {
439                 logger.debug("Caught exception ", e);
440             }
441             throw new DocumentException(e);
442         } finally {
443             if (repoSession != null) {
444                 releaseRepositorySession(repoSession);
445             }
446         }
447         return workspaceId;
448     }
449
450     private RepositoryInstance getRepositorySession() throws Exception {
451         // FIXME: is it possible to reuse repository session?
452         // Authentication failures happen while trying to reuse the session
453         NuxeoClient client = NuxeoConnector.getInstance().getClient();
454         RepositoryInstance repoSession = client.openRepository();
455         if (logger.isDebugEnabled()) {
456             logger.debug("getRepository() repository root: " + repoSession.getRootDocument());
457         }
458         return repoSession;
459     }
460
461     private void releaseRepositorySession(RepositoryInstance repoSession) {
462         try {
463             NuxeoClient client = NuxeoConnector.getInstance().getClient();
464             // release session
465             client.releaseRepository(repoSession);
466         } catch (Exception e) {
467             logger.error("Could not close the repository session", e);
468         // no need to throw this service specific exception
469         }
470     }
471 }