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:
6 * http://www.collectionspace.org
7 * http://wiki.collectionspace.org
9 * Copyright 2009 University of California at Berkeley
11 * Licensed under the Educational Community License (ECL), Version 2.0.
12 * You may not use this file except in compliance with this License.
14 * You may obtain a copy of the ECL 2.0 License at
16 * https://source.collectionspace.org/collection-space/LICENSE.txt
18 package org.collectionspace.services.nuxeo.client.java;
20 import java.util.Hashtable;
21 import java.util.List;
23 import java.util.UUID;
24 import java.util.regex.Matcher;
25 import java.util.regex.Pattern;
26 import java.util.regex.PatternSyntaxException;
28 import javax.ws.rs.WebApplicationException;
29 import javax.ws.rs.core.MultivaluedMap;
31 import org.collectionspace.services.client.IQueryManager;
32 import org.collectionspace.services.client.PoxPayloadIn;
33 import org.collectionspace.services.client.PoxPayloadOut;
34 import org.collectionspace.services.client.workflow.WorkflowClient;
35 import org.collectionspace.services.common.context.ServiceContext;
36 import org.collectionspace.services.common.datetime.GregorianCalendarDateTimeUtils;
37 import org.collectionspace.services.common.query.QueryContext;
38 import org.collectionspace.services.common.repository.RepositoryClient;
39 import org.collectionspace.services.common.workflow.service.nuxeo.WorkflowDocumentModelHandler;
40 import org.collectionspace.services.common.profile.Profiler;
41 import org.collectionspace.services.nuxeo.util.NuxeoUtils;
43 import org.collectionspace.services.common.document.BadRequestException;
44 import org.collectionspace.services.common.document.DocumentException;
45 import org.collectionspace.services.common.document.DocumentFilter;
46 import org.collectionspace.services.common.document.DocumentHandler;
47 import org.collectionspace.services.common.document.DocumentNotFoundException;
48 import org.collectionspace.services.common.document.DocumentHandler.Action;
49 import org.collectionspace.services.common.document.DocumentWrapper;
50 import org.collectionspace.services.common.document.DocumentWrapperImpl;
52 import org.nuxeo.common.utils.IdUtils;
53 import org.nuxeo.ecm.core.api.ClientException;
54 import org.nuxeo.ecm.core.api.DocumentModel;
55 import org.nuxeo.ecm.core.api.DocumentModelList;
56 import org.nuxeo.ecm.core.api.impl.DocumentModelListImpl;
57 import org.nuxeo.ecm.core.api.DocumentRef;
58 import org.nuxeo.ecm.core.api.IdRef;
59 import org.nuxeo.ecm.core.api.PathRef;
60 import org.nuxeo.ecm.core.api.repository.RepositoryInstance;
61 //import org.nuxeo.ecm.core.client.NuxeoClient;
62 import org.nuxeo.ecm.core.schema.SchemaManager;
63 import org.nuxeo.runtime.api.Framework;
65 import org.slf4j.Logger;
66 import org.slf4j.LoggerFactory;
69 * RepositoryJavaClient is used to perform CRUD operations on documents in Nuxeo
70 * repository using Remote Java APIs. It uses @see DocumentHandler as IOHandler
73 * $LastChangedRevision: $ $LastChangedDate: $
75 public class RepositoryJavaClientImpl implements RepositoryClient<PoxPayloadIn, PoxPayloadOut> {
78 private final Logger logger = LoggerFactory.getLogger(RepositoryJavaClientImpl.class);
79 // private final Logger profilerLogger = LoggerFactory.getLogger("remperf");
80 // private String foo = Profiler.createLogger();
82 public static final String NUXEO_CORE_TYPE_DOMAIN = "Domain";
83 public static final String NUXEO_CORE_TYPE_WORKSPACEROOT = "WorkspaceRoot";
86 * Instantiates a new repository java client impl.
88 public RepositoryJavaClientImpl() {
93 public void assertWorkflowState(ServiceContext ctx,
94 DocumentModel docModel) throws DocumentNotFoundException, ClientException {
95 MultivaluedMap<String, String> queryParams = ctx.getQueryParams();
96 if (queryParams != null) {
98 // Look for the workflow "delete" query param and see if we need to assert that the
99 // docModel is in a non-deleted workflow state.
101 String currentState = docModel.getCurrentLifeCycleState();
102 String includeDeletedStr = queryParams.getFirst(WorkflowClient.WORKFLOW_QUERY_NONDELETED);
103 boolean includeDeleted = includeDeletedStr == null ? true : Boolean.parseBoolean(includeDeletedStr);
104 if (includeDeleted == false) {
106 // We don't wanted soft-deleted object, so throw an exception if this one is soft-deleted.
108 if (currentState.equalsIgnoreCase(WorkflowClient.WORKFLOWSTATE_DELETED)) {
109 String msg = "GET assertion that docModel not be in 'deleted' workflow state failed.";
111 throw new DocumentNotFoundException(msg);
118 * create document in the Nuxeo repository
120 * @param ctx service context under which this method is invoked
122 * should be used by the caller to provide and transform the
124 * @return id in repository of the newly created document
125 * @throws DocumentException
128 public String create(ServiceContext ctx,
129 DocumentHandler handler) throws BadRequestException,
132 String docType = NuxeoUtils.getTenantQualifiedDocType(ctx); //ctx.getDocumentType();
133 if (docType == null) {
134 throw new IllegalArgumentException(
135 "RepositoryJavaClient.create: docType is missing");
138 if (handler == null) {
139 throw new IllegalArgumentException(
140 "RepositoryJavaClient.create: handler is missing");
142 String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
143 if (nuxeoWspaceId == null) {
144 throw new DocumentNotFoundException(
145 "Unable to find workspace for service " + ctx.getServiceName()
146 + " check if the workspace exists in the Nuxeo repository");
149 RepositoryInstance repoSession = null;
151 handler.prepare(Action.CREATE);
152 repoSession = getRepositorySession();
153 DocumentRef nuxeoWspace = new IdRef(nuxeoWspaceId);
154 DocumentModel wspaceDoc = repoSession.getDocument(nuxeoWspace);
155 String wspacePath = wspaceDoc.getPathAsString();
156 //give our own ID so PathRef could be constructed later on
157 String id = IdUtils.generateId(UUID.randomUUID().toString());
158 // create document model
159 DocumentModel doc = repoSession.createDocumentModel(wspacePath, id, docType);
160 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
161 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
162 handler.handle(Action.CREATE, wrapDoc);
163 // create document with documentmodel
164 doc = repoSession.createDocument(doc);
166 // TODO for sub-docs need to call into the handler to let it deal with subitems. Pass in the id,
167 // and assume the handler has the state it needs (doc fragments).
168 handler.complete(Action.CREATE, wrapDoc);
170 } catch (BadRequestException bre) {
172 } catch (Exception e) {
173 logger.error("Caught exception ", e);
174 throw new DocumentException(e);
176 if (repoSession != null) {
177 releaseRepositorySession(repoSession);
184 * get document from the Nuxeo repository
185 * @param ctx service context under which this method is invoked
187 * of the document to retrieve
189 * should be used by the caller to provide and transform the
191 * @throws DocumentException
194 public void get(ServiceContext ctx, String id, DocumentHandler handler)
195 throws DocumentNotFoundException, DocumentException {
197 if (handler == null) {
198 throw new IllegalArgumentException(
199 "RepositoryJavaClient.get: handler is missing");
202 RepositoryInstance repoSession = null;
204 handler.prepare(Action.GET);
205 repoSession = getRepositorySession();
206 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
207 DocumentModel docModel = null;
209 docModel = repoSession.getDocument(docRef);
210 assertWorkflowState(ctx, docModel);
211 } catch (ClientException ce) {
212 String msg = "Could not find document with id=" + id;
213 logger.error(msg, ce);
214 throw new DocumentNotFoundException(msg, ce);
216 //set reposession to handle the document
217 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
218 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(docModel);
219 handler.handle(Action.GET, wrapDoc);
220 handler.complete(Action.GET, wrapDoc);
221 } catch (IllegalArgumentException iae) {
223 } catch (DocumentException de) {
225 } catch (Exception e) {
226 if (logger.isDebugEnabled()) {
227 logger.debug("Caught exception ", e);
229 throw new DocumentException(e);
231 if (repoSession != null) {
232 releaseRepositorySession(repoSession);
238 * get document from the Nuxeo repository, using the docFilter params.
239 * @param ctx service context under which this method is invoked
241 * should be used by the caller to provide and transform the
242 * document. Handler must have a docFilter set to return a single item.
243 * @throws DocumentException
246 public void get(ServiceContext ctx, DocumentHandler handler)
247 throws DocumentNotFoundException, DocumentException {
248 QueryContext queryContext = new QueryContext(ctx, handler);
249 RepositoryInstance repoSession = null;
252 handler.prepare(Action.GET);
253 repoSession = getRepositorySession();
255 DocumentModelList docList = null;
256 // force limit to 1, and ignore totalSize
257 String query = NuxeoUtils.buildNXQLQuery(ctx, queryContext);
258 docList = repoSession.query(query, null, 1, 0, false);
259 if (docList.size() != 1) {
260 throw new DocumentNotFoundException("No document found matching filter params.");
262 DocumentModel doc = docList.get(0);
264 if (logger.isDebugEnabled()) {
265 logger.debug("Executed NXQL query: " + query);
268 //set reposession to handle the document
269 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
270 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
271 handler.handle(Action.GET, wrapDoc);
272 handler.complete(Action.GET, wrapDoc);
273 } catch (IllegalArgumentException iae) {
275 } catch (DocumentException de) {
277 } catch (Exception e) {
278 if (logger.isDebugEnabled()) {
279 logger.debug("Caught exception ", e);
281 throw new DocumentException(e);
283 if (repoSession != null) {
284 releaseRepositorySession(repoSession);
289 public DocumentWrapper<DocumentModel> getDoc(
290 RepositoryInstance repoSession,
291 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
292 String csid) throws DocumentNotFoundException, DocumentException {
293 DocumentWrapper<DocumentModel> wrapDoc = null;
296 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, csid);
297 DocumentModel doc = null;
299 doc = repoSession.getDocument(docRef);
300 } catch (ClientException ce) {
301 String msg = "Could not find document with CSID=" + csid;
302 logger.error(msg, ce);
303 throw new DocumentNotFoundException(msg, ce);
305 wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
306 } catch (IllegalArgumentException iae) {
308 } catch (DocumentException de) {
316 * Get wrapped documentModel from the Nuxeo repository. The search is restricted to the workspace
317 * of the current context.
319 * @param ctx service context under which this method is invoked
321 * of the document to retrieve
322 * @throws DocumentException
325 public DocumentWrapper<DocumentModel> getDoc(
326 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
327 String csid) throws DocumentNotFoundException, DocumentException {
328 RepositoryInstance repoSession = null;
329 DocumentWrapper<DocumentModel> wrapDoc = null;
332 // Open a new repository session
333 repoSession = getRepositorySession();
334 wrapDoc = getDoc(repoSession, ctx, csid);
335 } catch (IllegalArgumentException iae) {
337 } catch (DocumentException de) {
339 } catch (Exception e) {
340 if (logger.isDebugEnabled()) {
341 logger.debug("Caught exception ", e);
343 throw new DocumentException(e);
345 if (repoSession != null) {
346 releaseRepositorySession(repoSession);
350 if (logger.isWarnEnabled() == true) {
351 logger.warn("Returned DocumentModel instance was created with a repository session that is now closed.");
356 public DocumentWrapper<DocumentModel> findDoc(
357 RepositoryInstance repoSession,
358 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
360 throws DocumentNotFoundException, DocumentException {
361 DocumentWrapper<DocumentModel> wrapDoc = null;
364 QueryContext queryContext = new QueryContext(ctx, whereClause);
365 DocumentModelList docList = null;
366 // force limit to 1, and ignore totalSize
367 String query = NuxeoUtils.buildNXQLQuery(ctx, queryContext);
368 docList = repoSession.query(query,
373 if (docList.size() != 1) {
374 if (logger.isDebugEnabled()) {
375 logger.debug("findDoc: Query found: " + docList.size() + " items.");
376 logger.debug(" Query: " + query);
378 throw new DocumentNotFoundException("No document found matching filter params.");
380 DocumentModel doc = docList.get(0);
381 wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
382 } catch (IllegalArgumentException iae) {
384 } catch (DocumentException de) {
386 } catch (Exception e) {
387 if (logger.isDebugEnabled()) {
388 logger.debug("Caught exception ", e);
390 throw new DocumentException(e);
397 * find wrapped documentModel from the Nuxeo repository
398 * @param ctx service context under which this method is invoked
399 * @param whereClause where NXQL where clause to get the document
400 * @throws DocumentException
403 public DocumentWrapper<DocumentModel> findDoc(
404 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
406 throws DocumentNotFoundException, DocumentException {
407 RepositoryInstance repoSession = null;
408 DocumentWrapper<DocumentModel> wrapDoc = null;
411 repoSession = getRepositorySession();
412 wrapDoc = findDoc(repoSession, ctx, whereClause);
413 } catch (Exception e) {
414 throw new DocumentException("Unable to create a Nuxeo repository session.", e);
416 if (repoSession != null) {
417 releaseRepositorySession(repoSession);
421 if (logger.isWarnEnabled() == true) {
422 logger.warn("Returned DocumentModel instance was created with a repository session that is now closed.");
429 * find doc and return CSID from the Nuxeo repository
430 * @param ctx service context under which this method is invoked
431 * @param whereClause where NXQL where clause to get the document
432 * @throws DocumentException
435 public String findDocCSID(RepositoryInstance repoSession,
436 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx, String whereClause)
437 throws DocumentNotFoundException, DocumentException {
439 boolean releaseSession = false;
441 if(repoSession== null) {
442 repoSession = this.getRepositorySession();
443 releaseSession = true;
445 DocumentWrapper<DocumentModel> wrapDoc = findDoc(repoSession, ctx, whereClause);
446 DocumentModel docModel = wrapDoc.getWrappedObject();
447 csid = NuxeoUtils.getCsid(docModel);//NuxeoUtils.extractId(docModel.getPathAsString());
448 } catch (DocumentNotFoundException dnfe) {
450 } catch (IllegalArgumentException iae) {
452 } catch (DocumentException de) {
454 } catch (Exception e) {
455 if (logger.isDebugEnabled()) {
456 logger.debug("Caught exception ", e);
458 throw new DocumentException(e);
460 if(releaseSession && (repoSession != null)) {
461 this.releaseRepositorySession(repoSession);
467 public DocumentWrapper<DocumentModelList> findDocs(
468 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
469 RepositoryInstance repoSession,
470 List<String> docTypes,
472 int pageSize, int pageNum, boolean computeTotal)
473 throws DocumentNotFoundException, DocumentException {
474 DocumentWrapper<DocumentModelList> wrapDoc = null;
477 if (docTypes == null || docTypes.size() < 1) {
478 throw new DocumentNotFoundException(
479 "findDocs must specify at least one DocumentType.");
481 DocumentModelList docList = null;
482 // force limit to 1, and ignore totalSize
483 QueryContext queryContext = new QueryContext(ctx, whereClause);
484 String query = NuxeoUtils.buildNXQLQuery(docTypes, queryContext);
485 if (logger.isDebugEnabled()) {
486 logger.debug("findDocs() NXQL: "+query);
488 docList = repoSession.query(query, null, pageSize, pageNum, computeTotal);
489 wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
490 } catch (IllegalArgumentException iae) {
492 } catch (Exception e) {
493 if (logger.isDebugEnabled()) {
494 logger.debug("Caught exception ", e);
496 throw new DocumentException(e);
503 * Find a list of documentModels from the Nuxeo repository
504 * @param docTypes a list of DocType names to match
505 * @param whereClause where the clause to qualify on
509 public DocumentWrapper<DocumentModelList> findDocs(
510 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
511 List<String> docTypes,
513 int pageSize, int pageNum, boolean computeTotal)
514 throws DocumentNotFoundException, DocumentException {
515 RepositoryInstance repoSession = null;
516 DocumentWrapper<DocumentModelList> wrapDoc = null;
519 repoSession = getRepositorySession();
520 wrapDoc = findDocs(ctx, repoSession, docTypes, whereClause,
521 pageSize, pageNum, computeTotal);
522 } catch (IllegalArgumentException iae) {
524 } catch (Exception e) {
525 if (logger.isDebugEnabled()) {
526 logger.debug("Caught exception ", e);
528 throw new DocumentException(e);
530 if (repoSession != null) {
531 releaseRepositorySession(repoSession);
535 if (logger.isWarnEnabled() == true) {
536 logger.warn("Returned DocumentModelList instance was created with a repository session that is now closed.");
543 * @see org.collectionspace.services.common.storage.StorageClient#get(org.collectionspace.services.common.context.ServiceContext, java.util.List, org.collectionspace.services.common.document.DocumentHandler)
546 public void get(ServiceContext ctx, List<String> csidList, DocumentHandler handler)
547 throws DocumentNotFoundException, DocumentException {
548 if (handler == null) {
549 throw new IllegalArgumentException(
550 "RepositoryJavaClient.getAll: handler is missing");
553 RepositoryInstance repoSession = null;
555 handler.prepare(Action.GET_ALL);
556 repoSession = getRepositorySession();
557 DocumentModelList docModelList = new DocumentModelListImpl();
558 //FIXME: Should be using NuxeoUtils.createPathRef for security reasons
559 for (String csid : csidList) {
560 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, csid);
561 DocumentModel docModel = repoSession.getDocument(docRef);
562 docModelList.add(docModel);
565 //set reposession to handle the document
566 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
567 DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docModelList);
568 handler.handle(Action.GET_ALL, wrapDoc);
569 handler.complete(Action.GET_ALL, wrapDoc);
570 } catch (DocumentException de) {
572 } catch (Exception e) {
573 if (logger.isDebugEnabled()) {
574 logger.debug("Caught exception ", e);
576 throw new DocumentException(e);
578 if (repoSession != null) {
579 releaseRepositorySession(repoSession);
585 * getAll get all documents for an entity entity service from the Nuxeo
588 * @param ctx service context under which this method is invoked
590 * should be used by the caller to provide and transform the
592 * @throws DocumentException
595 public void getAll(ServiceContext ctx, DocumentHandler handler)
596 throws DocumentNotFoundException, DocumentException {
597 if (handler == null) {
598 throw new IllegalArgumentException(
599 "RepositoryJavaClient.getAll: handler is missing");
601 String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
602 if (nuxeoWspaceId == null) {
603 throw new DocumentNotFoundException(
604 "Unable to find workspace for service "
605 + ctx.getServiceName()
606 + " check if the workspace exists in the Nuxeo repository");
609 RepositoryInstance repoSession = null;
611 handler.prepare(Action.GET_ALL);
612 repoSession = getRepositorySession();
613 DocumentRef wsDocRef = new IdRef(nuxeoWspaceId);
614 DocumentModelList docList = repoSession.getChildren(wsDocRef);
615 //set reposession to handle the document
616 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
617 DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
618 handler.handle(Action.GET_ALL, wrapDoc);
619 handler.complete(Action.GET_ALL, wrapDoc);
620 } catch (DocumentException de) {
622 } catch (Exception e) {
623 if (logger.isDebugEnabled()) {
624 logger.debug("Caught exception ", e);
626 throw new DocumentException(e);
628 if (repoSession != null) {
629 releaseRepositorySession(repoSession);
634 private boolean isClauseEmpty(String theString) {
635 boolean result = true;
636 if (theString != null && !theString.isEmpty()) {
642 public DocumentWrapper<DocumentModel> getDocFromCsid(
643 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
644 RepositoryInstance repoSession,
647 DocumentWrapper<DocumentModel> result = null;
649 result = new DocumentWrapperImpl(NuxeoUtils.getDocFromCsid(ctx, repoSession, csid));
655 * A method to find a CollectionSpace document (of any type) given just a service context and
656 * its CSID. A search across *all* service workspaces (within a given tenant context) is performed to find
659 * This query searches Nuxeo's Hierarchy table where our CSIDs are stored in the "name" column.
662 public DocumentWrapper<DocumentModel> getDocFromCsid(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
665 DocumentWrapper<DocumentModel> result = null;
666 RepositoryInstance repoSession = null;
668 repoSession = getRepositorySession();
669 result = getDocFromCsid(ctx, repoSession, csid);
671 if (repoSession != null) {
672 releaseRepositorySession(repoSession);
676 if (logger.isWarnEnabled() == true) {
677 logger.warn("Returned DocumentModel instance was created with a repository session that is now closed.");
684 * find doc and return CSID from the Nuxeo repository
685 * @param ctx service context under which this method is invoked
686 * @param whereClause where NXQL where clause to get the document
687 * @throws DocumentException
690 public String getDocURI(DocumentWrapper<DocumentModel> wrappedDoc) throws ClientException {
691 DocumentModel docModel = wrappedDoc.getWrappedObject();
692 String uri = (String)docModel.getProperty(DocumentModelHandler.COLLECTIONSPACE_CORE_SCHEMA,
693 DocumentModelHandler.COLLECTIONSPACE_CORE_URI);
699 * getFiltered get all documents for an entity service from the Document repository,
700 * given filter parameters specified by the handler.
701 * @param ctx service context under which this method is invoked
702 * @param handler should be used by the caller to provide and transform the document
703 * @throws DocumentNotFoundException if workspace not found
704 * @throws DocumentException
707 public void getFiltered(ServiceContext ctx, DocumentHandler handler)
708 throws DocumentNotFoundException, DocumentException {
710 DocumentFilter filter = handler.getDocumentFilter();
711 String oldOrderBy = filter.getOrderByClause();
712 if (isClauseEmpty(oldOrderBy) == true){
713 filter.setOrderByClause(DocumentFilter.ORDER_BY_LAST_UPDATED); //per http://issues.collectionspace.org/browse/CSPACE-705 (Doesn't this conflict with what happens with the QueryContext instance that we create below?)
715 QueryContext queryContext = new QueryContext(ctx, handler);
717 RepositoryInstance repoSession = null;
719 handler.prepare(Action.GET_ALL);
720 repoSession = getRepositorySession();
721 DocumentModelList docList = null;
722 String query = NuxeoUtils.buildNXQLQuery(ctx, queryContext);
724 if (logger.isDebugEnabled()) {
725 logger.debug("Executing NXQL query: " + query.toString());
728 // If we have limit and/or offset, then pass true to get totalSize
729 // in returned DocumentModelList.
730 Profiler profiler = new Profiler(this, 2);
731 profiler.log("Executing NXQL query: " + query.toString());
733 if ((queryContext.getDocFilter().getOffset() > 0) || (queryContext.getDocFilter().getPageSize() > 0)) {
734 docList = repoSession.query(query, null,
735 queryContext.getDocFilter().getPageSize(), queryContext.getDocFilter().getOffset(), true);
737 docList = repoSession.query(query);
741 //set repoSession to handle the document
742 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
743 DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
744 handler.handle(Action.GET_ALL, wrapDoc);
745 handler.complete(Action.GET_ALL, wrapDoc);
746 } catch (DocumentException de) {
748 } catch (Exception e) {
749 if (logger.isDebugEnabled()) {
750 logger.debug("Caught exception ", e);
752 throw new DocumentException(e);
754 if (repoSession != null) {
755 releaseRepositorySession(repoSession);
761 * update given document in the Nuxeo repository
763 * @param ctx service context under which this method is invoked
767 * should be used by the caller to provide and transform the
769 * @throws DocumentException
772 public void update(ServiceContext ctx, String id, DocumentHandler handler)
773 throws BadRequestException, DocumentNotFoundException,
775 if (handler == null) {
776 throw new IllegalArgumentException(
777 "RepositoryJavaClient.update: handler is missing");
780 RepositoryInstance repoSession = null;
782 handler.prepare(Action.UPDATE);
783 repoSession = getRepositorySession();
784 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
785 DocumentModel doc = null;
787 doc = repoSession.getDocument(docRef);
788 } catch (ClientException ce) {
789 String msg = "Could not find document to update with id=" + id;
790 logger.error(msg, ce);
791 throw new DocumentNotFoundException(msg, ce);
793 //set reposession to handle the document
794 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
795 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
796 handler.handle(Action.UPDATE, wrapDoc);
797 repoSession.saveDocument(doc);
799 handler.complete(Action.UPDATE, wrapDoc);
800 } catch (BadRequestException bre) {
802 } catch (DocumentException de) {
804 } catch (WebApplicationException wae){
806 } catch (Exception e) {
807 if (logger.isDebugEnabled()) {
808 logger.debug("Caught exception ", e);
810 throw new DocumentException(e);
812 if (repoSession != null) {
813 releaseRepositorySession(repoSession);
819 * Save a documentModel to the Nuxeo repository.
820 * @param ctx service context under which this method is invoked
821 * @param docModel the document to save
822 * @param fSaveSession if TRUE, will call CoreSession.save() to save accumulated changes.
823 * @throws DocumentException
825 public void saveDocWithoutHandlerProcessing(
826 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
827 RepositoryInstance repoSession,
828 DocumentModel docModel,
829 boolean fSaveSession)
830 throws ClientException, DocumentException {
833 repoSession.saveDocument(docModel);
837 } catch (ClientException ce) {
839 } catch (Exception e) {
840 if (logger.isDebugEnabled()) {
841 logger.debug("Caught exception ", e);
843 throw new DocumentException(e);
849 * Save a list of documentModels to the Nuxeo repository.
851 * @param ctx service context under which this method is invoked
852 * @param docModel the document to save
853 * @param fSaveSession if TRUE, will call CoreSession.save() to save accumulated changes.
854 * @throws DocumentException
856 public void saveDocListWithoutHandlerProcessing(
857 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
858 RepositoryInstance repoSession,
859 DocumentModelList docList,
860 boolean fSaveSession)
861 throws ClientException, DocumentException {
863 repoSession = getRepositorySession();
864 DocumentModel[] docModelArray = new DocumentModel[docList.size()];
865 repoSession.saveDocuments(docList.toArray(docModelArray));
869 } catch (ClientException ce) {
871 } catch (Exception e) {
872 logger.error("Caught exception ", e);
873 throw new DocumentException(e);
878 * delete a document from the Nuxeo repository
879 * @param ctx service context under which this method is invoked
882 * @throws DocumentException
885 public void delete(ServiceContext ctx, String id) throws DocumentNotFoundException,
888 if (logger.isDebugEnabled()) {
889 logger.debug("deleting document with id=" + id);
891 RepositoryInstance repoSession = null;
893 repoSession = getRepositorySession();
894 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
896 repoSession.removeDocument(docRef);
897 } catch (ClientException ce) {
898 String msg = "could not find document to delete with id=" + id;
899 logger.error(msg, ce);
900 throw new DocumentNotFoundException(msg, ce);
903 } catch (DocumentException de) {
905 } catch (Exception e) {
906 if (logger.isDebugEnabled()) {
907 logger.debug("Caught exception ", e);
909 throw new DocumentException(e);
911 if (repoSession != null) {
912 releaseRepositorySession(repoSession);
918 * @see org.collectionspace.services.common.storage.StorageClient#delete(org.collectionspace.services.common.context.ServiceContext, java.lang.String, org.collectionspace.services.common.document.DocumentHandler)
921 public void delete(ServiceContext ctx, String id, DocumentHandler handler)
922 throws DocumentNotFoundException, DocumentException {
923 throw new UnsupportedOperationException();
927 public Hashtable<String, String> retrieveWorkspaceIds(String domainName) throws Exception {
928 return NuxeoConnectorEmbedded.getInstance().retrieveWorkspaceIds(domainName);
932 public String createDomain(String domainName) throws Exception {
933 RepositoryInstance repoSession = null;
934 String domainId = null;
937 // First create the top-level domain directory
939 repoSession = getRepositorySession();
940 DocumentRef parentDocRef = new PathRef("/");
941 DocumentModel parentDoc = repoSession.getDocument(parentDocRef);
942 DocumentModel domainDoc = repoSession.createDocumentModel(parentDoc.getPathAsString(),
943 domainName, NUXEO_CORE_TYPE_DOMAIN);
944 domainDoc.setPropertyValue("dc:title", domainName);
945 domainDoc.setPropertyValue("dc:description", "A CollectionSpace domain "
947 domainDoc = repoSession.createDocument(domainDoc);
948 domainId = domainDoc.getId();
951 // Next, create a "Workspaces" root directory to contain the workspace folders for the individual service documents
953 DocumentModel workspacesRoot = repoSession.createDocumentModel(domainDoc.getPathAsString(),
954 NuxeoUtils.Workspaces, NUXEO_CORE_TYPE_WORKSPACEROOT);
955 workspacesRoot.setPropertyValue("dc:title", NuxeoUtils.Workspaces);
956 workspacesRoot.setPropertyValue("dc:description", "A CollectionSpace workspaces directory for "
957 + domainDoc.getPathAsString());
958 workspacesRoot = repoSession.createDocument(workspacesRoot);
959 String workspacesRootId = workspacesRoot.getId();
962 if (logger.isDebugEnabled()) {
963 logger.debug("Created tenant domain name=" + domainName
964 + " id=" + domainId + " " +
965 NuxeoUtils.Workspaces + " id=" + workspacesRootId);
966 logger.debug("Path to Domain: "+domainDoc.getPathAsString());
967 logger.debug("Path to Workspaces root: "+workspacesRoot.getPathAsString());
969 } catch (Exception e) {
970 if (logger.isDebugEnabled()) {
971 logger.debug("Could not create tenant domain name=" + domainName + " caught exception ", e);
975 if (repoSession != null) {
976 releaseRepositorySession(repoSession);
984 public String getDomainId(String domainName) throws Exception {
985 String domainId = null;
986 RepositoryInstance repoSession = null;
988 if (domainName != null && !domainName.isEmpty()) {
990 repoSession = getRepositorySession();
991 DocumentRef docRef = new PathRef(
993 DocumentModel domain = repoSession.getDocument(docRef);
994 domainId = domain.getId();
995 } catch (Exception e) {
996 if (logger.isTraceEnabled()) {
997 logger.trace("Caught exception ", e);
999 //there is no way to identify if document does not exist due to
1000 //lack of typed exception for getDocument method
1003 if (repoSession != null) {
1004 releaseRepositorySession(repoSession);
1013 * @see org.collectionspace.services.common.repository.RepositoryClient#createWorkspace(java.lang.String, java.lang.String)
1016 public String createWorkspace(String domainName, String workspaceName) throws Exception {
1017 RepositoryInstance repoSession = null;
1018 String workspaceId = null;
1020 repoSession = getRepositorySession();
1021 String parentDocRefPath = "/" + domainName + "/" + NuxeoUtils.Workspaces;
1022 DocumentRef parentDocRef = new PathRef(
1024 + "/" + NuxeoUtils.Workspaces);
1025 if (logger.isDebugEnabled()) {
1026 logger.debug("Fetching "+NuxeoUtils.Workspaces+", path=" + parentDocRefPath
1027 + " docRef:" + parentDocRef.toString());
1029 DocumentModel parentDoc = null;
1031 parentDoc = repoSession.getDocument(parentDocRef);
1032 } catch(ClientException ce) {
1033 logger.error("Failed to get "+NuxeoUtils.Workspaces+", path=" + parentDocRefPath
1034 + " docRef:" + parentDocRef.toString());
1035 // try again for debugging
1036 parentDoc = repoSession.getDocument(parentDocRef);
1039 DocumentModel doc = repoSession.createDocumentModel(parentDoc.getPathAsString(),
1040 workspaceName, "Workspace");
1041 doc.setPropertyValue("dc:title", workspaceName);
1042 doc.setPropertyValue("dc:description", "A CollectionSpace workspace for "
1044 doc = repoSession.createDocument(doc);
1045 workspaceId = doc.getId();
1047 if (logger.isDebugEnabled()) {
1048 logger.debug("created workspace name=" + workspaceName
1049 + " id=" + workspaceId);
1051 } catch (Exception e) {
1052 if (logger.isDebugEnabled()) {
1053 logger.debug("createWorkspace caught exception ", e);
1057 if (repoSession != null) {
1058 releaseRepositorySession(repoSession);
1065 * @see org.collectionspace.services.common.repository.RepositoryClient#getWorkspaceId(java.lang.String, java.lang.String)
1068 public String getWorkspaceId(String tenantDomain, String workspaceName) throws Exception {
1069 String workspaceId = null;
1071 RepositoryInstance repoSession = null;
1073 repoSession = getRepositorySession();
1074 DocumentRef docRef = new PathRef(
1076 + "/" + NuxeoUtils.Workspaces
1077 + "/" + workspaceName);
1078 DocumentModel workspace = repoSession.getDocument(docRef);
1079 workspaceId = workspace.getId();
1080 } catch (DocumentException de) {
1082 } catch (Exception e) {
1083 if (logger.isDebugEnabled()) {
1084 logger.debug("Caught exception ", e);
1086 throw new DocumentException(e);
1088 if (repoSession != null) {
1089 releaseRepositorySession(repoSession);
1098 * Gets the repository session. - Package access only.
1100 * @return the repository session
1101 * @throws Exception the exception
1103 public RepositoryInstance getRepositorySession() throws Exception {
1104 // FIXME: is it possible to reuse repository session?
1105 // Authentication failures happen while trying to reuse the session
1106 Profiler profiler = new Profiler("getRepositorySession():", 2);
1109 NuxeoClientEmbedded client = NuxeoConnectorEmbedded.getInstance().getClient();
1110 RepositoryInstance repoSession = client.openRepository();
1111 if (logger.isTraceEnabled()) {
1112 logger.trace("Testing call to getRepository() repository root: " + repoSession.getRootDocument());
1120 * Release repository session. - Package access only.
1122 * @param repoSession the repo session
1124 public void releaseRepositorySession(RepositoryInstance repoSession) {
1126 NuxeoClientEmbedded client = NuxeoConnectorEmbedded.getInstance().getClient();
1128 client.releaseRepository(repoSession);
1129 } catch (Exception e) {
1130 logger.error("Could not close the repository session", e);
1131 // no need to throw this service specific exception