]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
27f475394dacab08a01ae331f0dd46630bc90579
[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 (BadRequestException bre) {
111             throw bre;
112         } catch (Exception e) {
113             if (logger.isDebugEnabled()) {
114                 logger.debug("Caught exception ", e);
115             }
116             throw new DocumentException(e);
117         } finally {
118             if (repoSession != null) {
119                 releaseRepositorySession(repoSession);
120             }
121         }
122
123     }
124
125     /**
126      * get document from the Nuxeo repository
127      * @param ctx service context under which this method is invoked
128      * @param id
129      *            of the document to retrieve
130      * @param handler
131      *            should be used by the caller to provide and transform the
132      *            document
133      * @throws DocumentException
134      */
135     @Override
136     public void get(ServiceContext ctx, String id, DocumentHandler handler)
137             throws DocumentNotFoundException, DocumentException {
138
139         if (handler == null) {
140             throw new IllegalArgumentException(
141                     "RepositoryJavaClient.get: handler is missing");
142         }
143         RepositoryInstance repoSession = null;
144
145         try {
146             handler.prepare(Action.GET);
147             repoSession = getRepositorySession();
148             DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
149             DocumentModel doc = null;
150             try {
151                 doc = repoSession.getDocument(docRef);
152             } catch (ClientException ce) {
153                 String msg = "could not find document with id=" + id;
154                 logger.error(msg, ce);
155                 throw new DocumentNotFoundException(msg, ce);
156             }
157             //set reposession to handle the document
158             ((DocumentModelHandler) handler).setRepositorySession(repoSession);
159             DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
160             handler.handle(Action.GET, wrapDoc);
161             handler.complete(Action.GET, wrapDoc);
162         } catch (IllegalArgumentException iae) {
163             throw iae;
164         } catch (DocumentException de) {
165             throw de;
166         } catch (Exception e) {
167             if (logger.isDebugEnabled()) {
168                 logger.debug("Caught exception ", e);
169             }
170             throw new DocumentException(e);
171         } finally {
172             if (repoSession != null) {
173                 releaseRepositorySession(repoSession);
174             }
175         }
176     }
177
178     /**
179      * getAll get all documents for an entity entity service from the Nuxeo
180      * repository
181      *
182      * @param ctx service context under which this method is invoked
183      * @param handler
184      *            should be used by the caller to provide and transform the
185      *            document
186      * @throws DocumentException
187      */
188     @Override
189     public void getAll(ServiceContext ctx, DocumentHandler handler)
190             throws DocumentNotFoundException, DocumentException {
191         if (handler == null) {
192             throw new IllegalArgumentException(
193                     "RepositoryJavaClient.getAll: handler is missing");
194         }
195         String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
196         if (nuxeoWspaceId == null) {
197             throw new DocumentNotFoundException(
198                     "Unable to find workspace for service "
199                     + ctx.getServiceName()
200                     + " check if the workspace exists in the Nuxeo repository");
201         }
202         RepositoryInstance repoSession = null;
203
204         try {
205             handler.prepare(Action.GET_ALL);
206             repoSession = getRepositorySession();
207             DocumentRef wsDocRef = new IdRef(nuxeoWspaceId);
208             DocumentModelList docList = repoSession.getChildren(wsDocRef);
209             //set reposession to handle the document
210             ((DocumentModelHandler) handler).setRepositorySession(repoSession);
211             DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
212             handler.handle(Action.GET_ALL, wrapDoc);
213             handler.complete(Action.GET_ALL, wrapDoc);
214         } catch (DocumentException de) {
215             throw de;
216         } catch (Exception e) {
217             if (logger.isDebugEnabled()) {
218                 logger.debug("Caught exception ", e);
219             }
220             throw new DocumentException(e);
221         } finally {
222             if (repoSession != null) {
223                 releaseRepositorySession(repoSession);
224             }
225         }
226     }
227
228     /**
229      * getFiltered get all documents for an entity service from the Document repository,
230      * given filter parameters specified by the handler. 
231      * @param ctx service context under which this method is invoked
232      * @param handler should be used by the caller to provide and transform the document
233      * @throws DocumentNotFoundException if workspace not found
234      * @throws DocumentException
235      */
236     public void getFiltered(ServiceContext ctx, DocumentHandler handler)
237             throws DocumentNotFoundException, DocumentException {
238         if (handler == null) {
239             throw new IllegalArgumentException(
240                     "RepositoryJavaClient.getFiltered: handler is missing");
241         }
242         DocumentFilter docFilter = handler.getDocumentFilter();
243         if (docFilter == null) {
244             throw new IllegalArgumentException(
245                     "RepositoryJavaClient.getFiltered: handler has no Filter specified");
246         }
247         String docType = ctx.getDocumentType();
248         if (docType == null) {
249             throw new DocumentNotFoundException(
250                     "Unable to find DocumentType for service " + ctx.getServiceName());
251         }
252         String domain = ctx.getRepositoryDomainName();
253         if (domain == null) {
254             throw new DocumentNotFoundException(
255                     "Unable to find Domain for service " + ctx.getServiceName());
256         }
257         RepositoryInstance repoSession = null;
258         try {
259             handler.prepare(Action.GET_ALL);
260             repoSession = getRepositorySession();
261             StringBuilder query = new StringBuilder("SELECT * FROM ");
262             query.append(docType);
263             String where = docFilter.getWhereClause();
264             // TODO This is a slow method for tenant-filter
265             // We should make this a property that is indexed.
266             query.append(" WHERE ecm:path STARTSWITH '/" + domain + "'");
267             if ((null != where) && (where.length() > 0)) {
268 //              query.append(" AND " + where);
269                 query.append(" AND " + where + "AND ecm:isProxy = 0");
270             }
271             DocumentModelList docList = null;
272             if ((docFilter.getOffset() > 0) || (docFilter.getPageSize() > 0)) {
273                 docList = repoSession.query(query.toString(), null,
274                         docFilter.getPageSize(), docFilter.getOffset(), false);
275             } else {
276                 docList = repoSession.query(query.toString());
277             }
278             //set repoSession to handle the document
279             ((DocumentModelHandler) handler).setRepositorySession(repoSession);
280             DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
281             handler.handle(Action.GET_ALL, wrapDoc);
282             handler.complete(Action.GET_ALL, wrapDoc);
283         } catch (DocumentException de) {
284             throw de;
285         } catch (Exception e) {
286             if (logger.isDebugEnabled()) {
287                 logger.debug("Caught exception ", e);
288             }
289             throw new DocumentException(e);
290         } finally {
291             if (repoSession != null) {
292                 releaseRepositorySession(repoSession);
293             }
294         }
295     }
296
297     /**
298      * update given document in the Nuxeo repository
299      *
300      * @param ctx service context under which this method is invoked
301      * @param id
302      *            of the document
303      * @param handler
304      *            should be used by the caller to provide and transform the
305      *            document
306      * @throws DocumentException
307      */
308     @Override
309     public void update(ServiceContext ctx, String id, DocumentHandler handler)
310             throws BadRequestException, DocumentNotFoundException,
311             DocumentException {
312         if (handler == null) {
313             throw new IllegalArgumentException(
314                     "RepositoryJavaClient.update: handler is missing");
315         }
316         RepositoryInstance repoSession = null;
317         try {
318             handler.prepare(Action.UPDATE);
319             repoSession = getRepositorySession();
320             DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
321             DocumentModel doc = null;
322             try {
323                 doc = repoSession.getDocument(docRef);
324             } catch (ClientException ce) {
325                 String msg = "Could not find document to update with id=" + id;
326                 logger.error(msg, ce);
327                 throw new DocumentNotFoundException(msg, ce);
328             }
329             //set reposession to handle the document
330             ((DocumentModelHandler) handler).setRepositorySession(repoSession);
331             DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
332             handler.handle(Action.UPDATE, wrapDoc);
333             repoSession.saveDocument(doc);
334             repoSession.save();
335             handler.complete(Action.UPDATE, wrapDoc);
336         } catch (BadRequestException bre) {
337             throw bre;
338         } catch (DocumentException de) {
339             throw de;
340         } catch (Exception e) {
341             if (logger.isDebugEnabled()) {
342                 logger.debug("Caught exception ", e);
343             }
344             throw new DocumentException(e);
345         } finally {
346             if (repoSession != null) {
347                 releaseRepositorySession(repoSession);
348             }
349         }
350     }
351
352     /**
353      * delete a document from the Nuxeo repository
354      * @param ctx service context under which this method is invoked
355      * @param id
356      *            of the document
357      * @throws DocumentException
358      */
359     @Override
360     public void delete(ServiceContext ctx, String id) throws DocumentNotFoundException,
361             DocumentException {
362
363         if (logger.isDebugEnabled()) {
364             logger.debug("deleting document with id=" + id);
365         }
366         RepositoryInstance repoSession = null;
367         try {
368             repoSession = getRepositorySession();
369             DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
370             try {
371                 repoSession.removeDocument(docRef);
372             } catch (ClientException ce) {
373                 String msg = "could not find document to delete with id=" + id;
374                 logger.error(msg, ce);
375                 throw new DocumentNotFoundException(msg, ce);
376             }
377             repoSession.save();
378         } catch (DocumentException de) {
379             throw de;
380         } catch (Exception e) {
381             if (logger.isDebugEnabled()) {
382                 logger.debug("Caught exception ", e);
383             }
384             throw new DocumentException(e);
385         } finally {
386             if (repoSession != null) {
387                 releaseRepositorySession(repoSession);
388             }
389         }
390     }
391
392     @Override
393     public String createWorkspace(String tenantDomain, String workspaceName) throws Exception {
394         RepositoryInstance repoSession = null;
395         String workspaceId = null;
396         try {
397             repoSession = getRepositorySession();
398             DocumentRef docRef = new PathRef(
399                     "/" + tenantDomain
400                     + "/" + "workspaces");
401             DocumentModel parent = repoSession.getDocument(docRef);
402             DocumentModel doc = repoSession.createDocumentModel(parent.getPathAsString(),
403                     workspaceName, "Workspace");
404             doc.setPropertyValue("dc:title", workspaceName);
405             doc.setPropertyValue("dc:description", "A CollectionSpace workspace for "
406                     + workspaceName);
407             doc = repoSession.createDocument(doc);
408             workspaceId = doc.getId();
409             repoSession.save();
410             if (logger.isDebugEnabled()) {
411                 logger.debug("created workspace name=" + workspaceName
412                         + " id=" + workspaceId);
413             }
414         } catch (Exception e) {
415             if (logger.isDebugEnabled()) {
416                 logger.debug("createWorkspace caught exception ", e);
417             }
418             throw e;
419         } finally {
420             if (repoSession != null) {
421                 releaseRepositorySession(repoSession);
422             }
423         }
424         return workspaceId;
425     }
426
427     @Override
428     public String getWorkspaceId(String tenantDomain, String workspaceName) throws Exception {
429         String workspaceId = null;
430         RepositoryInstance repoSession = null;
431         try {
432             repoSession = getRepositorySession();
433             DocumentRef docRef = new PathRef(
434                     "/" + tenantDomain
435                     + "/" + "workspaces"
436                     + "/" + workspaceName);
437             DocumentModel workspace = repoSession.getDocument(docRef);
438             workspaceId = workspace.getId();
439         } catch (DocumentException de) {
440             throw de;
441         } catch (Exception e) {
442             if (logger.isDebugEnabled()) {
443                 logger.debug("Caught exception ", e);
444             }
445             throw new DocumentException(e);
446         } finally {
447             if (repoSession != null) {
448                 releaseRepositorySession(repoSession);
449             }
450         }
451         return workspaceId;
452     }
453
454     private RepositoryInstance getRepositorySession() throws Exception {
455         // FIXME: is it possible to reuse repository session?
456         // Authentication failures happen while trying to reuse the session
457         NuxeoClient client = NuxeoConnector.getInstance().getClient();
458         RepositoryInstance repoSession = client.openRepository();
459         if (logger.isDebugEnabled()) {
460             logger.debug("getRepository() repository root: " + repoSession.getRootDocument());
461         }
462         return repoSession;
463     }
464
465     private void releaseRepositorySession(RepositoryInstance repoSession) {
466         try {
467             NuxeoClient client = NuxeoConnector.getInstance().getClient();
468             // release session
469             client.releaseRepository(repoSession);
470         } catch (Exception e) {
471             logger.error("Could not close the repository session", e);
472             // no need to throw this service specific exception
473         }
474     }
475 }