]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
9ccb51be18f9603be1e3f25cbc1afd1cb0cf1457
[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                     "RemoteRepositoryClient.create: docType is missing");
79         }
80         if (handler == null) {
81             throw new IllegalArgumentException(
82                     "RemoteRepositoryClient.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                     "RemoteRepositoryClient.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                     "RemoteRepositoryClient.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                     "RemoteRepositoryClient.getFiltered: handler is missing");
239         }
240         DocumentFilter docFilter = handler.getDocumentFilter();
241         if (docFilter == null) {
242             throw new IllegalArgumentException(
243                     "RemoteRepositoryClient.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             }
268             DocumentModelList docList = null;
269             if ((docFilter.getOffset() > 0) || (docFilter.getPageSize() > 0)) {
270                 docList = repoSession.query(query.toString(), null,
271                         docFilter.getPageSize(), docFilter.getOffset(), false);
272             } else {
273                 docList = repoSession.query(query.toString());
274             }
275             //set repoSession to handle the document
276             ((DocumentModelHandler) handler).setRepositorySession(repoSession);
277             DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
278             handler.handle(Action.GET_ALL, wrapDoc);
279             handler.complete(Action.GET_ALL, wrapDoc);
280         } catch (DocumentException de) {
281             throw de;
282         } catch (Exception e) {
283             if (logger.isDebugEnabled()) {
284                 logger.debug("Caught exception ", e);
285             }
286             throw new DocumentException(e);
287         } finally {
288             if (repoSession != null) {
289                 releaseRepositorySession(repoSession);
290             }
291         }
292     }
293
294     /**
295      * update given document in the Nuxeo repository
296      *
297      * @param ctx service context under which this method is invoked
298      * @param id
299      *            of the document
300      * @param handler
301      *            should be used by the caller to provide and transform the
302      *            document
303      * @throws DocumentException
304      */
305     @Override
306     public void update(ServiceContext ctx, String id, DocumentHandler handler)
307             throws BadRequestException, DocumentNotFoundException,
308             DocumentException {
309         if (id == null) {
310             throw new BadRequestException(
311                     "RemoteRepositoryClient.update: id is missing");
312         }
313         if (handler == null) {
314             throw new IllegalArgumentException(
315                     "RemoteRepositoryClient.update: handler is missing");
316         }
317         RepositoryInstance repoSession = null;
318         try {
319             handler.prepare(Action.UPDATE);
320             repoSession = getRepositorySession();
321             DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
322             DocumentModel doc = null;
323             try {
324                 doc = repoSession.getDocument(docRef);
325             } catch (ClientException ce) {
326                 String msg = "Could not find document to update with id=" + id;
327                 logger.error(msg, ce);
328                 throw new DocumentNotFoundException(msg, ce);
329             }
330             //set reposession to handle the document
331             ((DocumentModelHandler) handler).setRepositorySession(repoSession);
332             DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
333             handler.handle(Action.UPDATE, wrapDoc);
334             repoSession.saveDocument(doc);
335             repoSession.save();
336             handler.complete(Action.UPDATE, wrapDoc);
337         } catch (DocumentException de) {
338             throw de;
339         } catch (Exception e) {
340             if (logger.isDebugEnabled()) {
341                 logger.debug("Caught exception ", e);
342             }
343             throw new DocumentException(e);
344         } finally {
345             if (repoSession != null) {
346                 releaseRepositorySession(repoSession);
347             }
348         }
349     }
350
351     /**
352      * delete a document from the Nuxeo repository
353      * @param ctx service context under which this method is invoked
354      * @param id
355      *            of the document
356      * @throws DocumentException
357      */
358     @Override
359     public void delete(ServiceContext ctx, String id) throws DocumentNotFoundException,
360             DocumentException {
361
362         if (logger.isDebugEnabled()) {
363             logger.debug("deleting document with id=" + id);
364         }
365         RepositoryInstance repoSession = null;
366         try {
367             repoSession = getRepositorySession();
368             DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
369             try {
370                 repoSession.removeDocument(docRef);
371             } catch (ClientException ce) {
372                 String msg = "could not find document to delete with id=" + id;
373                 logger.error(msg, ce);
374                 throw new DocumentNotFoundException(msg, ce);
375             }
376             repoSession.save();
377         } catch (DocumentException de) {
378             throw de;
379         } catch (Exception e) {
380             if (logger.isDebugEnabled()) {
381                 logger.debug("Caught exception ", e);
382             }
383             throw new DocumentException(e);
384         } finally {
385             if (repoSession != null) {
386                 releaseRepositorySession(repoSession);
387             }
388         }
389     }
390
391     @Override
392     public String createWorkspace(String tenantDomain, String workspaceName) throws Exception {
393         RepositoryInstance repoSession = null;
394         String workspaceId = null;
395         try {
396             repoSession = getRepositorySession();
397             DocumentRef docRef = new PathRef(
398                     "/" + tenantDomain +
399                     "/" + "workspaces");
400             DocumentModel parent = repoSession.getDocument(docRef);
401             DocumentModel doc = repoSession.createDocumentModel(parent.getPathAsString(),
402                     workspaceName, "Workspace");
403             doc.setPropertyValue("dc:title", workspaceName);
404             doc.setPropertyValue("dc:description", "A CollectionSpace workspace for " +
405                     workspaceName);
406             doc = repoSession.createDocument(doc);
407             workspaceId = doc.getId();
408             repoSession.save();
409             if (logger.isDebugEnabled()) {
410                 logger.debug("created workspace name=" + workspaceName +
411                         " id=" + workspaceId);
412             }
413         } catch (Exception e) {
414             if (logger.isDebugEnabled()) {
415                 logger.debug("createWorkspace caught exception ", e);
416             }
417             throw e;
418         } finally {
419             if (repoSession != null) {
420                 releaseRepositorySession(repoSession);
421             }
422         }
423         return workspaceId;
424     }
425
426     @Override
427     public String getWorkspaceId(String tenantDomain, String workspaceName) throws Exception {
428         String workspaceId = null;
429         RepositoryInstance repoSession = null;
430         try {
431             repoSession = getRepositorySession();
432             DocumentRef docRef = new PathRef(
433                     "/" + tenantDomain +
434                     "/" + "workspaces" +
435                     "/" + workspaceName);
436             DocumentModel workspace = repoSession.getDocument(docRef);
437             workspaceId = workspace.getId();
438         } catch (DocumentException de) {
439             throw de;
440         } catch (Exception e) {
441             if (logger.isDebugEnabled()) {
442                 logger.debug("Caught exception ", e);
443             }
444             throw new DocumentException(e);
445         } finally {
446             if (repoSession != null) {
447                 releaseRepositorySession(repoSession);
448             }
449         }
450         return workspaceId;
451     }
452
453     private RepositoryInstance getRepositorySession() throws Exception {
454         // FIXME: is it possible to reuse repository session?
455         // Authentication failures happen while trying to reuse the session
456         NuxeoClient client = NuxeoConnector.getInstance().getClient();
457         RepositoryInstance repoSession = client.openRepository();
458         if (logger.isDebugEnabled()) {
459             logger.debug("getRepository() repository root: " + repoSession.getRootDocument());
460         }
461         return repoSession;
462     }
463
464     private void releaseRepositorySession(RepositoryInstance repoSession) {
465         try {
466             NuxeoClient client = NuxeoConnector.getInstance().getClient();
467             // release session
468             client.releaseRepository(repoSession);
469         } catch (Exception e) {
470             logger.error("Could not close the repository session", e);
471         // no need to throw this service specific exception
472         }
473     }
474 }