]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
422569706d28f8235c2e80c743d4cb615921e247
[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 RepositoryJavaClientImpl implements RepositoryClient {
55
56     private final Logger logger = LoggerFactory.getLogger(RepositoryJavaClientImpl.class);
57
58     public RepositoryJavaClientImpl() {
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     /**
181      * get document from the Nuxeo repository, using the docFilter params.
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. Handler must have a docFilter set to return a single item.
186      * @throws DocumentException
187      */
188     @Override
189     public void get(ServiceContext ctx, DocumentHandler handler)
190             throws DocumentNotFoundException, DocumentException {
191
192         if (handler == null) {
193             throw new IllegalArgumentException(
194                     "RepositoryJavaClient.get: handler is missing");
195         }
196         DocumentFilter docFilter = handler.getDocumentFilter();
197         if (docFilter == null) {
198             throw new IllegalArgumentException(
199                     "RepositoryJavaClient.get: handler has no Filter specified");
200         }
201         if (docFilter.getPageSize() != 1) {
202             logger.warn("RepositoryJavaClient.get: forcing docFilter pagesize to 1.");
203         }
204         String docType = ctx.getDocumentType();
205         if (docType == null) {
206             throw new DocumentNotFoundException(
207                     "Unable to find DocumentType for service " + ctx.getServiceName());
208         }
209         String domain = ctx.getRepositoryDomainName();
210         if (domain == null) {
211             throw new DocumentNotFoundException(
212                     "Unable to find Domain for service " + ctx.getServiceName());
213         }
214         RepositoryInstance repoSession = null;
215
216         try {
217             handler.prepare(Action.GET);
218             repoSession = getRepositorySession();
219
220             DocumentModelList docList = null;
221             // force limit to 1, and ignore totalSize
222             String query = buildNXQLQuery(docType, docFilter.getWhereClause(), domain);
223             docList = repoSession.query(query, null, 1, 0, false);
224             if (docList.size() != 1) {
225                 throw new DocumentNotFoundException("No document found matching filter params.");
226             }
227             DocumentModel doc = docList.get(0);
228
229             if (logger.isDebugEnabled()) {
230                 logger.debug("Executed NXQL query: " + query);
231             }
232
233             //set reposession to handle the document
234             ((DocumentModelHandler) handler).setRepositorySession(repoSession);
235             DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
236             handler.handle(Action.GET, wrapDoc);
237             handler.complete(Action.GET, wrapDoc);
238         } catch (IllegalArgumentException iae) {
239             throw iae;
240         } catch (DocumentException de) {
241             throw de;
242         } catch (Exception e) {
243             if (logger.isDebugEnabled()) {
244                 logger.debug("Caught exception ", e);
245             }
246             throw new DocumentException(e);
247         } finally {
248             if (repoSession != null) {
249                 releaseRepositorySession(repoSession);
250             }
251         }
252     }
253
254     /**
255      * get wrapped documentModel from the Nuxeo repository
256      * @param ctx service context under which this method is invoked
257      * @param id
258      *            of the document to retrieve
259      * @throws DocumentException
260      */
261     @Override
262     public DocumentWrapper<DocumentModel> getDoc(
263             ServiceContext ctx, String id)
264             throws DocumentNotFoundException, DocumentException {
265         RepositoryInstance repoSession = null;
266         DocumentWrapper<DocumentModel> wrapDoc = null;
267
268         try {
269             repoSession = getRepositorySession();
270             DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
271             DocumentModel doc = null;
272             try {
273                 doc = repoSession.getDocument(docRef);
274             } catch (ClientException ce) {
275                 String msg = "could not find document with id=" + id;
276                 logger.error(msg, ce);
277                 throw new DocumentNotFoundException(msg, ce);
278             }
279             wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
280         } catch (IllegalArgumentException iae) {
281             throw iae;
282         } catch (DocumentException de) {
283             throw de;
284         } catch (Exception e) {
285             if (logger.isDebugEnabled()) {
286                 logger.debug("Caught exception ", e);
287             }
288             throw new DocumentException(e);
289         } finally {
290             if (repoSession != null) {
291                 releaseRepositorySession(repoSession);
292             }
293         }
294         return wrapDoc;
295     }
296
297     /**
298      * find wrapped documentModel from the Nuxeo repository
299      * @param ctx service context under which this method is invoked
300      * @param where NXQL where clause to get the document
301      * @throws DocumentException
302      */
303     @Override
304     public DocumentWrapper<DocumentModel> findDoc(
305             ServiceContext ctx, String where)
306             throws DocumentNotFoundException, DocumentException {
307         RepositoryInstance repoSession = null;
308         DocumentWrapper<DocumentModel> wrapDoc = null;
309
310         try {
311             String docType = ctx.getDocumentType();
312             if (docType == null) {
313                 throw new DocumentNotFoundException(
314                         "Unable to find DocumentType for service " + ctx.getServiceName());
315             }
316             String domain = ctx.getRepositoryDomainName();
317             if (domain == null) {
318                 throw new DocumentNotFoundException(
319                         "Unable to find Domain for service " + ctx.getServiceName());
320             }
321             repoSession = getRepositorySession();
322             DocumentModelList docList = null;
323             // force limit to 1, and ignore totalSize
324             String query = buildNXQLQuery(docType, where, domain);
325             docList = repoSession.query(query, null, 1, 0, false);
326             if (docList.size() != 1) {
327                 if (logger.isDebugEnabled()) {
328                     logger.debug("findDoc: Query found: " + docList.size() + " items.");
329                     logger.debug(" Query: " + query);
330                 }
331                 throw new DocumentNotFoundException("No document found matching filter params.");
332             }
333             DocumentModel doc = docList.get(0);
334             wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
335         } catch (IllegalArgumentException iae) {
336             throw iae;
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         return wrapDoc;
350     }
351
352     /**
353      * find doc and return CSID from the Nuxeo repository
354      * @param ctx service context under which this method is invoked
355      * @param where NXQL where clause to get the document
356      * @throws DocumentException
357      */
358     public String findDocCSID(
359             ServiceContext ctx, String where)
360             throws DocumentNotFoundException, DocumentException {
361         String csid = null;
362         try {
363             DocumentWrapper<DocumentModel> wrapDoc = findDoc(ctx, where);
364             DocumentModel docModel = wrapDoc.getWrappedObject();
365             csid = NuxeoUtils.extractId(docModel.getPathAsString());
366         } catch (DocumentNotFoundException dnfe) {
367             throw dnfe;
368         } catch (IllegalArgumentException iae) {
369             throw iae;
370         } catch (DocumentException de) {
371             throw de;
372         } catch (Exception e) {
373             if (logger.isDebugEnabled()) {
374                 logger.debug("Caught exception ", e);
375             }
376             throw new DocumentException(e);
377         }
378         return csid;
379     }
380
381     /**
382      * Find a list of documentModels from the Nuxeo repository
383      * @param docTypes a list of DocType names to match
384      * @param where the clause to qualify on
385      * @param domain the domain for the associated services
386      * @return
387      */
388     @Override
389     public DocumentWrapper<DocumentModelList> findDocs(
390             List<String> docTypes, String where, String domain,
391             int pageSize, int pageNum, boolean computeTotal)
392             throws DocumentNotFoundException, DocumentException {
393         RepositoryInstance repoSession = null;
394         DocumentWrapper<DocumentModelList> wrapDoc = null;
395
396         try {
397             if (docTypes == null || docTypes.size() < 1) {
398                 throw new DocumentNotFoundException(
399                         "findDocs must specify at least one DocumentType.");
400             }
401             if (domain == null) {
402                 throw new DocumentNotFoundException("findDocs must specify Domain.");
403             }
404             repoSession = getRepositorySession();
405             DocumentModelList docList = null;
406             // force limit to 1, and ignore totalSize
407             String query = buildNXQLQuery(docTypes, where, domain);
408             docList = repoSession.query(query, null, pageSize, pageNum, computeTotal);
409             wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
410         } catch (IllegalArgumentException iae) {
411             throw iae;
412         } catch (Exception e) {
413             if (logger.isDebugEnabled()) {
414                 logger.debug("Caught exception ", e);
415             }
416             throw new DocumentException(e);
417         } finally {
418             if (repoSession != null) {
419                 releaseRepositorySession(repoSession);
420             }
421         }
422         return wrapDoc;
423     }
424
425     @Override
426     public void get(ServiceContext ctx, List<String> csidList, DocumentHandler handler)
427             throws DocumentNotFoundException, DocumentException {
428         if (handler == null) {
429             throw new IllegalArgumentException(
430                     "RepositoryJavaClient.getAll: handler is missing");
431         }
432
433         RepositoryInstance repoSession = null;
434
435         try {
436             handler.prepare(Action.GET_ALL);
437             repoSession = getRepositorySession();
438             DocumentModelList docModelList = new DocumentModelListImpl();
439             //FIXME: Should be using NuxeoUtils.createPathRef for security reasons
440             for (String csid : csidList) {
441                 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, csid);
442                 DocumentModel docModel = repoSession.getDocument(docRef);
443                 docModelList.add(docModel);
444             }
445
446             //set reposession to handle the document
447             ((DocumentModelHandler) handler).setRepositorySession(repoSession);
448             DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docModelList);
449             handler.handle(Action.GET_ALL, wrapDoc);
450             handler.complete(Action.GET_ALL, wrapDoc);
451         } catch (DocumentException de) {
452             throw de;
453         } catch (Exception e) {
454             if (logger.isDebugEnabled()) {
455                 logger.debug("Caught exception ", e);
456             }
457             throw new DocumentException(e);
458         } finally {
459             if (repoSession != null) {
460                 releaseRepositorySession(repoSession);
461             }
462         }
463     }
464
465     /**
466      * getAll get all documents for an entity entity service from the Nuxeo
467      * repository
468      *
469      * @param ctx service context under which this method is invoked
470      * @param handler
471      *            should be used by the caller to provide and transform the
472      *            document
473      * @throws DocumentException
474      */
475     @Override
476     public void getAll(ServiceContext ctx, DocumentHandler handler)
477             throws DocumentNotFoundException, DocumentException {
478         if (handler == null) {
479             throw new IllegalArgumentException(
480                     "RepositoryJavaClient.getAll: handler is missing");
481         }
482         String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
483         if (nuxeoWspaceId == null) {
484             throw new DocumentNotFoundException(
485                     "Unable to find workspace for service "
486                     + ctx.getServiceName()
487                     + " check if the workspace exists in the Nuxeo repository");
488         }
489         RepositoryInstance repoSession = null;
490
491         try {
492             handler.prepare(Action.GET_ALL);
493             repoSession = getRepositorySession();
494             DocumentRef wsDocRef = new IdRef(nuxeoWspaceId);
495             DocumentModelList docList = repoSession.getChildren(wsDocRef);
496             //set reposession to handle the document
497             ((DocumentModelHandler) handler).setRepositorySession(repoSession);
498             DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
499             handler.handle(Action.GET_ALL, wrapDoc);
500             handler.complete(Action.GET_ALL, wrapDoc);
501         } catch (DocumentException de) {
502             throw de;
503         } catch (Exception e) {
504             if (logger.isDebugEnabled()) {
505                 logger.debug("Caught exception ", e);
506             }
507             throw new DocumentException(e);
508         } finally {
509             if (repoSession != null) {
510                 releaseRepositorySession(repoSession);
511             }
512         }
513     }
514
515     /**
516      * getFiltered get all documents for an entity service from the Document repository,
517      * given filter parameters specified by the handler. 
518      * @param ctx service context under which this method is invoked
519      * @param handler should be used by the caller to provide and transform the document
520      * @throws DocumentNotFoundException if workspace not found
521      * @throws DocumentException
522      */
523     public void getFiltered(ServiceContext ctx, DocumentHandler handler)
524             throws DocumentNotFoundException, DocumentException {
525         if (handler == null) {
526             throw new IllegalArgumentException(
527                     "RepositoryJavaClient.getFiltered: handler is missing");
528         }
529         DocumentFilter docFilter = handler.getDocumentFilter();
530         if (docFilter == null) {
531             throw new IllegalArgumentException(
532                     "RepositoryJavaClient.getFiltered: handler has no Filter specified");
533         }
534         String docType = ctx.getDocumentType();
535         if (docType == null) {
536             throw new DocumentNotFoundException(
537                     "Unable to find DocumentType for service " + ctx.getServiceName());
538         }
539         String domain = ctx.getRepositoryDomainName();
540         if (domain == null) {
541             throw new DocumentNotFoundException(
542                     "Unable to find Domain for service " + ctx.getServiceName());
543         }
544         RepositoryInstance repoSession = null;
545         try {
546             handler.prepare(Action.GET_ALL);
547             repoSession = getRepositorySession();
548             DocumentModelList docList = null;
549             String query = buildNXQLQuery(docType, docFilter.getWhereClause(), domain);
550
551             // If we have limit and/or offset, then pass true to get totalSize
552             // in returned DocumentModelList.
553             if ((docFilter.getOffset() > 0) || (docFilter.getPageSize() > 0)) {
554                 docList = repoSession.query(query, null,
555                         docFilter.getPageSize(), docFilter.getOffset(), true);
556             } else {
557                 docList = repoSession.query(query);
558             }
559
560             if (logger.isDebugEnabled()) {
561                 logger.debug("Executed NXQL query: " + query.toString());
562             }
563
564             //set repoSession to handle the document
565             ((DocumentModelHandler) handler).setRepositorySession(repoSession);
566             DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
567             handler.handle(Action.GET_ALL, wrapDoc);
568             handler.complete(Action.GET_ALL, wrapDoc);
569         } catch (DocumentException de) {
570             throw de;
571         } catch (Exception e) {
572             if (logger.isDebugEnabled()) {
573                 logger.debug("Caught exception ", e);
574             }
575             throw new DocumentException(e);
576         } finally {
577             if (repoSession != null) {
578                 releaseRepositorySession(repoSession);
579             }
580         }
581     }
582
583     /**
584      * update given document in the Nuxeo repository
585      *
586      * @param ctx service context under which this method is invoked
587      * @param id
588      *            of the document
589      * @param handler
590      *            should be used by the caller to provide and transform the
591      *            document
592      * @throws DocumentException
593      */
594     @Override
595     public void update(ServiceContext ctx, String id, DocumentHandler handler)
596             throws BadRequestException, DocumentNotFoundException,
597             DocumentException {
598         if (handler == null) {
599             throw new IllegalArgumentException(
600                     "RepositoryJavaClient.update: handler is missing");
601         }
602         RepositoryInstance repoSession = null;
603         try {
604             handler.prepare(Action.UPDATE);
605             repoSession = getRepositorySession();
606             DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
607             DocumentModel doc = null;
608             try {
609                 doc = repoSession.getDocument(docRef);
610             } catch (ClientException ce) {
611                 String msg = "Could not find document to update with id=" + id;
612                 logger.error(msg, ce);
613                 throw new DocumentNotFoundException(msg, ce);
614             }
615             //set reposession to handle the document
616             ((DocumentModelHandler) handler).setRepositorySession(repoSession);
617             DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
618             handler.handle(Action.UPDATE, wrapDoc);
619             repoSession.saveDocument(doc);
620             repoSession.save();
621             handler.complete(Action.UPDATE, wrapDoc);
622         } catch (BadRequestException bre) {
623             throw bre;
624         } catch (DocumentException de) {
625             throw de;
626         } catch (Exception e) {
627             if (logger.isDebugEnabled()) {
628                 logger.debug("Caught exception ", e);
629             }
630             throw new DocumentException(e);
631         } finally {
632             if (repoSession != null) {
633                 releaseRepositorySession(repoSession);
634             }
635         }
636     }
637
638     /**
639      * delete a document from the Nuxeo repository
640      * @param ctx service context under which this method is invoked
641      * @param id
642      *            of the document
643      * @throws DocumentException
644      */
645     @Override
646     public void delete(ServiceContext ctx, String id) throws DocumentNotFoundException,
647             DocumentException {
648
649         if (logger.isDebugEnabled()) {
650             logger.debug("deleting document with id=" + id);
651         }
652         RepositoryInstance repoSession = null;
653         try {
654             repoSession = getRepositorySession();
655             DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
656             try {
657                 repoSession.removeDocument(docRef);
658             } catch (ClientException ce) {
659                 String msg = "could not find document to delete with id=" + id;
660                 logger.error(msg, ce);
661                 throw new DocumentNotFoundException(msg, ce);
662             }
663             repoSession.save();
664         } catch (DocumentException de) {
665             throw de;
666         } catch (Exception e) {
667             if (logger.isDebugEnabled()) {
668                 logger.debug("Caught exception ", e);
669             }
670             throw new DocumentException(e);
671         } finally {
672             if (repoSession != null) {
673                 releaseRepositorySession(repoSession);
674             }
675         }
676     }
677
678     @Override
679     public void delete(ServiceContext ctx, String id, DocumentHandler handler)
680             throws DocumentNotFoundException, DocumentException {
681         throw new UnsupportedOperationException();
682     }
683
684     @Override
685     public String createWorkspace(String tenantDomain, String workspaceName) throws Exception {
686         RepositoryInstance repoSession = null;
687         String workspaceId = null;
688         try {
689             repoSession = getRepositorySession();
690             DocumentRef docRef = new PathRef(
691                     "/" + tenantDomain
692                     + "/" + "workspaces");
693             DocumentModel parent = repoSession.getDocument(docRef);
694             DocumentModel doc = repoSession.createDocumentModel(parent.getPathAsString(),
695                     workspaceName, "Workspace");
696             doc.setPropertyValue("dc:title", workspaceName);
697             doc.setPropertyValue("dc:description", "A CollectionSpace workspace for "
698                     + workspaceName);
699             doc = repoSession.createDocument(doc);
700             workspaceId = doc.getId();
701             repoSession.save();
702             if (logger.isDebugEnabled()) {
703                 logger.debug("created workspace name=" + workspaceName
704                         + " id=" + workspaceId);
705             }
706         } catch (Exception e) {
707             if (logger.isDebugEnabled()) {
708                 logger.debug("createWorkspace caught exception ", e);
709             }
710             throw e;
711         } finally {
712             if (repoSession != null) {
713                 releaseRepositorySession(repoSession);
714             }
715         }
716         return workspaceId;
717     }
718
719     @Override
720     public String getWorkspaceId(String tenantDomain, String workspaceName) throws Exception {
721         String workspaceId = null;
722         RepositoryInstance repoSession = null;
723         try {
724             repoSession = getRepositorySession();
725             DocumentRef docRef = new PathRef(
726                     "/" + tenantDomain
727                     + "/" + "workspaces"
728                     + "/" + workspaceName);
729             DocumentModel workspace = repoSession.getDocument(docRef);
730             workspaceId = workspace.getId();
731         } catch (DocumentException de) {
732             throw de;
733         } catch (Exception e) {
734             if (logger.isDebugEnabled()) {
735                 logger.debug("Caught exception ", e);
736             }
737             throw new DocumentException(e);
738         } finally {
739             if (repoSession != null) {
740                 releaseRepositorySession(repoSession);
741             }
742         }
743         return workspaceId;
744     }
745
746     private final void appendNXQLWhere(StringBuilder query, String where, String domain) {
747         // TODO This is a slow method for tenant-filter
748         // We should make this a property that is indexed.
749         query.append(" WHERE ecm:path STARTSWITH '/" + domain + "'");
750         if ((null != where) && (where.length() > 0)) {
751             // Due to an apparent bug/issue in how Nuxeo translates the NXQL query string
752             // into SQL, we need to parenthesize our 'where' clause
753             query.append(" AND " + "(" + where + ")");
754         }
755         query.append(" AND ecm:isProxy = 0");
756     }
757
758     private final String buildNXQLQuery(String docType, String where, String domain) {
759         StringBuilder query = new StringBuilder("SELECT * FROM ");
760         query.append(docType);
761         appendNXQLWhere(query, where, domain);
762         return query.toString();
763     }
764
765     private final String buildNXQLQuery(List<String> docTypes, String where, String domain) {
766         StringBuilder query = new StringBuilder("SELECT * FROM ");
767         boolean fFirst = true;
768         for (String docType : docTypes) {
769             if (fFirst) {
770                 fFirst = false;
771             } else {
772                 query.append(",");
773             }
774             query.append(docType);
775         }
776         appendNXQLWhere(query, where, domain);
777         return query.toString();
778     }
779
780     private RepositoryInstance getRepositorySession() throws Exception {
781         // FIXME: is it possible to reuse repository session?
782         // Authentication failures happen while trying to reuse the session
783         NuxeoClient client = NuxeoConnector.getInstance().getClient();
784         RepositoryInstance repoSession = client.openRepository();
785         if (logger.isDebugEnabled()) {
786             logger.debug("getRepository() repository root: " + repoSession.getRootDocument());
787         }
788         return repoSession;
789     }
790
791     private void releaseRepositorySession(RepositoryInstance repoSession) {
792         try {
793             NuxeoClient client = NuxeoConnector.getInstance().getClient();
794             // release session
795             client.releaseRepository(repoSession);
796         } catch (Exception e) {
797             logger.error("Could not close the repository session", e);
798             // no need to throw this service specific exception
799         }
800     }
801 }