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