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