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.Iterator;
22 import java.util.List;
23 import java.util.UUID;
25 import javax.ws.rs.WebApplicationException;
26 import javax.ws.rs.core.MultivaluedMap;
28 import org.collectionspace.services.client.PoxPayloadIn;
29 import org.collectionspace.services.client.PoxPayloadOut;
30 import org.collectionspace.services.client.workflow.WorkflowClient;
31 import org.collectionspace.services.common.context.ServiceContext;
32 import org.collectionspace.services.common.query.QueryContext;
33 import org.collectionspace.services.common.repository.RepositoryClient;
34 import org.collectionspace.services.common.profile.Profiler;
35 import org.collectionspace.services.nuxeo.util.NuxeoUtils;
37 import org.collectionspace.services.common.document.BadRequestException;
38 import org.collectionspace.services.common.document.DocumentException;
39 import org.collectionspace.services.common.document.DocumentFilter;
40 import org.collectionspace.services.common.document.DocumentHandler;
41 import org.collectionspace.services.common.document.DocumentNotFoundException;
42 import org.collectionspace.services.common.document.DocumentHandler.Action;
43 import org.collectionspace.services.common.document.DocumentWrapper;
44 import org.collectionspace.services.common.document.DocumentWrapperImpl;
46 import org.nuxeo.common.utils.IdUtils;
47 import org.nuxeo.ecm.core.api.ClientException;
48 import org.nuxeo.ecm.core.api.DocumentModel;
49 import org.nuxeo.ecm.core.api.DocumentModelList;
50 import org.nuxeo.ecm.core.api.impl.DocumentModelListImpl;
51 import org.nuxeo.ecm.core.api.DocumentRef;
52 import org.nuxeo.ecm.core.api.IdRef;
53 import org.nuxeo.ecm.core.api.PathRef;
54 import org.nuxeo.ecm.core.api.repository.RepositoryInstance;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
60 * RepositoryJavaClient is used to perform CRUD operations on documents in Nuxeo
61 * repository using Remote Java APIs. It uses @see DocumentHandler as IOHandler
64 * $LastChangedRevision: $ $LastChangedDate: $
66 public class RepositoryJavaClientImpl implements RepositoryClient<PoxPayloadIn, PoxPayloadOut> {
69 private final Logger logger = LoggerFactory.getLogger(RepositoryJavaClientImpl.class);
70 // private final Logger profilerLogger = LoggerFactory.getLogger("remperf");
71 // private String foo = Profiler.createLogger();
73 public static final String NUXEO_CORE_TYPE_DOMAIN = "Domain";
74 public static final String NUXEO_CORE_TYPE_WORKSPACEROOT = "WorkspaceRoot";
77 * Instantiates a new repository java client impl.
79 public RepositoryJavaClientImpl() {
84 public void assertWorkflowState(ServiceContext ctx,
85 DocumentModel docModel) throws DocumentNotFoundException, ClientException {
86 MultivaluedMap<String, String> queryParams = ctx.getQueryParams();
87 if (queryParams != null) {
89 // Look for the workflow "delete" query param and see if we need to assert that the
90 // docModel is in a non-deleted workflow state.
92 String currentState = docModel.getCurrentLifeCycleState();
93 String includeDeletedStr = queryParams.getFirst(WorkflowClient.WORKFLOW_QUERY_NONDELETED);
94 boolean includeDeleted = includeDeletedStr == null ? true : Boolean.parseBoolean(includeDeletedStr);
95 if (includeDeleted == false) {
97 // We don't wanted soft-deleted object, so throw an exception if this one is soft-deleted.
99 if (currentState.equalsIgnoreCase(WorkflowClient.WORKFLOWSTATE_DELETED)) {
100 String msg = "The GET assertion that docModel not be in 'deleted' workflow state failed.";
102 throw new DocumentNotFoundException(msg);
109 * create document in the Nuxeo repository
111 * @param ctx service context under which this method is invoked
113 * should be used by the caller to provide and transform the
115 * @return id in repository of the newly created document
116 * @throws DocumentException
119 public String create(ServiceContext ctx,
120 DocumentHandler handler) throws BadRequestException,
123 String docType = NuxeoUtils.getTenantQualifiedDocType(ctx); //ctx.getDocumentType();
124 if (docType == null) {
125 throw new IllegalArgumentException(
126 "RepositoryJavaClient.create: docType is missing");
129 if (handler == null) {
130 throw new IllegalArgumentException(
131 "RepositoryJavaClient.create: handler is missing");
133 String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
134 if (nuxeoWspaceId == null) {
135 throw new DocumentNotFoundException(
136 "Unable to find workspace for service " + ctx.getServiceName()
137 + " check if the workspace exists in the Nuxeo repository");
140 RepositoryInstance repoSession = null;
142 handler.prepare(Action.CREATE);
143 repoSession = getRepositorySession();
144 DocumentRef nuxeoWspace = new IdRef(nuxeoWspaceId);
145 DocumentModel wspaceDoc = repoSession.getDocument(nuxeoWspace);
146 String wspacePath = wspaceDoc.getPathAsString();
147 //give our own ID so PathRef could be constructed later on
148 String id = IdUtils.generateId(UUID.randomUUID().toString());
149 // create document model
150 DocumentModel doc = repoSession.createDocumentModel(wspacePath, id, docType);
151 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
152 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
153 handler.handle(Action.CREATE, wrapDoc);
154 // create document with documentmodel
155 doc = repoSession.createDocument(doc);
157 // TODO for sub-docs need to call into the handler to let it deal with subitems. Pass in the id,
158 // and assume the handler has the state it needs (doc fragments).
159 handler.complete(Action.CREATE, wrapDoc);
161 } catch (BadRequestException bre) {
163 } catch (Exception e) {
164 logger.error("Caught exception ", e);
165 throw new DocumentException(e);
167 if (repoSession != null) {
168 releaseRepositorySession(repoSession);
175 * get document from the Nuxeo repository
176 * @param ctx service context under which this method is invoked
178 * of the document to retrieve
180 * should be used by the caller to provide and transform the
182 * @throws DocumentException
185 public void get(ServiceContext ctx, String id, DocumentHandler handler)
186 throws DocumentNotFoundException, DocumentException {
188 if (handler == null) {
189 throw new IllegalArgumentException(
190 "RepositoryJavaClient.get: handler is missing");
193 RepositoryInstance repoSession = null;
195 handler.prepare(Action.GET);
196 repoSession = getRepositorySession();
197 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
198 DocumentModel docModel = null;
200 docModel = repoSession.getDocument(docRef);
201 assertWorkflowState(ctx, docModel);
202 } catch (ClientException ce) {
203 String msg = logException(ce, "Could not find document with CSID=" + id);
204 throw new DocumentNotFoundException(msg, ce);
207 // Set repository session to handle the document
209 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
210 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(docModel);
211 handler.handle(Action.GET, wrapDoc);
212 handler.complete(Action.GET, wrapDoc);
213 } catch (IllegalArgumentException iae) {
215 } catch (DocumentException de) {
217 } catch (Exception e) {
218 if (logger.isDebugEnabled()) {
219 logger.debug("Caught exception ", e);
221 throw new DocumentException(e);
223 if (repoSession != null) {
224 releaseRepositorySession(repoSession);
230 * get document from the Nuxeo repository, using the docFilter params.
231 * @param ctx service context under which this method is invoked
233 * should be used by the caller to provide and transform the
234 * document. Handler must have a docFilter set to return a single item.
235 * @throws DocumentException
238 public void get(ServiceContext ctx, DocumentHandler handler)
239 throws DocumentNotFoundException, DocumentException {
240 QueryContext queryContext = new QueryContext(ctx, handler);
241 RepositoryInstance repoSession = null;
244 handler.prepare(Action.GET);
245 repoSession = getRepositorySession();
247 DocumentModelList docList = null;
248 // force limit to 1, and ignore totalSize
249 String query = NuxeoUtils.buildNXQLQuery(ctx, queryContext);
250 docList = repoSession.query(query, null, 1, 0, false);
251 if (docList.size() != 1) {
252 throw new DocumentNotFoundException("No document found matching filter params: " + query);
254 DocumentModel doc = docList.get(0);
256 if (logger.isDebugEnabled()) {
257 logger.debug("Executed NXQL query: " + query);
260 //set reposession to handle the document
261 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
262 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
263 handler.handle(Action.GET, wrapDoc);
264 handler.complete(Action.GET, wrapDoc);
265 } catch (IllegalArgumentException iae) {
267 } catch (DocumentException de) {
269 } catch (Exception e) {
270 if (logger.isDebugEnabled()) {
271 logger.debug("Caught exception ", e);
273 throw new DocumentException(e);
275 if (repoSession != null) {
276 releaseRepositorySession(repoSession);
281 public DocumentWrapper<DocumentModel> getDoc(
282 RepositoryInstance repoSession,
283 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
284 String csid) throws DocumentNotFoundException, DocumentException {
285 DocumentWrapper<DocumentModel> wrapDoc = null;
288 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, csid);
289 DocumentModel doc = null;
291 doc = repoSession.getDocument(docRef);
292 } catch (ClientException ce) {
293 String msg = logException(ce, "Could not find document with CSID=" + csid);
294 throw new DocumentNotFoundException(msg, ce);
296 wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
297 } catch (IllegalArgumentException iae) {
299 } catch (DocumentException de) {
307 * Get wrapped documentModel from the Nuxeo repository. The search is restricted to the workspace
308 * of the current context.
310 * @param ctx service context under which this method is invoked
312 * of the document to retrieve
313 * @throws DocumentException
316 public DocumentWrapper<DocumentModel> getDoc(
317 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
318 String csid) throws DocumentNotFoundException, DocumentException {
319 RepositoryInstance repoSession = null;
320 DocumentWrapper<DocumentModel> wrapDoc = null;
323 // Open a new repository session
324 repoSession = getRepositorySession();
325 wrapDoc = getDoc(repoSession, ctx, csid);
326 } catch (IllegalArgumentException iae) {
328 } catch (DocumentException de) {
330 } catch (Exception e) {
331 if (logger.isDebugEnabled()) {
332 logger.debug("Caught exception ", e);
334 throw new DocumentException(e);
336 if (repoSession != null) {
337 releaseRepositorySession(repoSession);
341 if (logger.isWarnEnabled() == true) {
342 logger.warn("Returned DocumentModel instance was created with a repository session that is now closed.");
347 public DocumentWrapper<DocumentModel> findDoc(
348 RepositoryInstance repoSession,
349 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
351 throws DocumentNotFoundException, DocumentException {
352 DocumentWrapper<DocumentModel> wrapDoc = null;
355 QueryContext queryContext = new QueryContext(ctx, whereClause);
356 DocumentModelList docList = null;
357 // force limit to 1, and ignore totalSize
358 String query = NuxeoUtils.buildNXQLQuery(ctx, queryContext);
359 docList = repoSession.query(query,
364 if (docList.size() != 1) {
365 if (logger.isDebugEnabled()) {
366 logger.debug("findDoc: Query found: " + docList.size() + " items.");
367 logger.debug(" Query: " + query);
369 throw new DocumentNotFoundException("No document found matching filter params: " + query);
371 DocumentModel doc = docList.get(0);
372 wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
373 } catch (IllegalArgumentException iae) {
375 } catch (DocumentException de) {
377 } catch (Exception e) {
378 if (logger.isDebugEnabled()) {
379 logger.debug("Caught exception ", e);
381 throw new DocumentException(e);
388 * find wrapped documentModel from the Nuxeo repository
389 * @param ctx service context under which this method is invoked
390 * @param whereClause where NXQL where clause to get the document
391 * @throws DocumentException
394 public DocumentWrapper<DocumentModel> findDoc(
395 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
397 throws DocumentNotFoundException, DocumentException {
398 RepositoryInstance repoSession = null;
399 DocumentWrapper<DocumentModel> wrapDoc = null;
402 repoSession = getRepositorySession();
403 wrapDoc = findDoc(repoSession, ctx, whereClause);
404 } catch (Exception e) {
405 throw new DocumentException("Unable to create a Nuxeo repository session.", e);
407 if (repoSession != null) {
408 releaseRepositorySession(repoSession);
412 if (logger.isWarnEnabled() == true) {
413 logger.warn("Returned DocumentModel instance was created with a repository session that is now closed.");
420 * find doc and return CSID from the Nuxeo repository
421 * @param ctx service context under which this method is invoked
422 * @param whereClause where NXQL where clause to get the document
423 * @throws DocumentException
426 public String findDocCSID(RepositoryInstance repoSession,
427 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx, String whereClause)
428 throws DocumentNotFoundException, DocumentException {
430 boolean releaseSession = false;
432 if(repoSession== null) {
433 repoSession = this.getRepositorySession();
434 releaseSession = true;
436 DocumentWrapper<DocumentModel> wrapDoc = findDoc(repoSession, ctx, whereClause);
437 DocumentModel docModel = wrapDoc.getWrappedObject();
438 csid = NuxeoUtils.getCsid(docModel);//NuxeoUtils.extractId(docModel.getPathAsString());
439 } catch (DocumentNotFoundException dnfe) {
441 } catch (IllegalArgumentException iae) {
443 } catch (DocumentException de) {
445 } catch (Exception e) {
446 if (logger.isDebugEnabled()) {
447 logger.debug("Caught exception ", e);
449 throw new DocumentException(e);
451 if(releaseSession && (repoSession != null)) {
452 this.releaseRepositorySession(repoSession);
458 public DocumentWrapper<DocumentModelList> findDocs(
459 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
460 RepositoryInstance repoSession,
461 List<String> docTypes,
463 int pageSize, int pageNum, boolean computeTotal)
464 throws DocumentNotFoundException, DocumentException {
465 DocumentWrapper<DocumentModelList> wrapDoc = null;
468 if (docTypes == null || docTypes.size() < 1) {
469 throw new DocumentNotFoundException(
470 "The findDocs() method must specify at least one DocumentType.");
472 DocumentModelList docList = null;
473 QueryContext queryContext = new QueryContext(ctx, whereClause);
474 String query = NuxeoUtils.buildNXQLQuery(docTypes, queryContext);
475 if (logger.isDebugEnabled()) {
476 logger.debug("findDocs() NXQL: "+query);
478 docList = repoSession.query(query, null, pageSize, pageNum, computeTotal);
479 wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
480 } catch (IllegalArgumentException iae) {
482 } catch (Exception e) {
483 if (logger.isDebugEnabled()) {
484 logger.debug("Caught exception ", e);
486 throw new DocumentException(e);
493 * Find a list of documentModels from the Nuxeo repository
494 * @param docTypes a list of DocType names to match
495 * @param whereClause where the clause to qualify on
499 public DocumentWrapper<DocumentModelList> findDocs(
500 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
501 List<String> docTypes,
503 int pageSize, int pageNum, boolean computeTotal)
504 throws DocumentNotFoundException, DocumentException {
505 RepositoryInstance repoSession = null;
506 DocumentWrapper<DocumentModelList> wrapDoc = null;
509 repoSession = getRepositorySession();
510 wrapDoc = findDocs(ctx, repoSession, docTypes, whereClause,
511 pageSize, pageNum, computeTotal);
512 } catch (IllegalArgumentException iae) {
514 } catch (Exception e) {
515 if (logger.isDebugEnabled()) {
516 logger.debug("Caught exception ", e);
518 throw new DocumentException(e);
520 if (repoSession != null) {
521 releaseRepositorySession(repoSession);
525 if (logger.isWarnEnabled() == true) {
526 logger.warn("Returned DocumentModelList instance was created with a repository session that is now closed.");
533 * @see org.collectionspace.services.common.storage.StorageClient#get(org.collectionspace.services.common.context.ServiceContext, java.util.List, org.collectionspace.services.common.document.DocumentHandler)
536 public void get(ServiceContext ctx, List<String> csidList, DocumentHandler handler)
537 throws DocumentNotFoundException, DocumentException {
538 if (handler == null) {
539 throw new IllegalArgumentException(
540 "RepositoryJavaClient.getAll: handler is missing");
543 RepositoryInstance repoSession = null;
545 handler.prepare(Action.GET_ALL);
546 repoSession = getRepositorySession();
547 DocumentModelList docModelList = new DocumentModelListImpl();
548 //FIXME: Should be using NuxeoUtils.createPathRef for security reasons
549 for (String csid : csidList) {
550 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, csid);
551 DocumentModel docModel = repoSession.getDocument(docRef);
552 docModelList.add(docModel);
555 //set reposession to handle the document
556 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
557 DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docModelList);
558 handler.handle(Action.GET_ALL, wrapDoc);
559 handler.complete(Action.GET_ALL, wrapDoc);
560 } catch (DocumentException de) {
562 } catch (Exception e) {
563 if (logger.isDebugEnabled()) {
564 logger.debug("Caught exception ", e);
566 throw new DocumentException(e);
568 if (repoSession != null) {
569 releaseRepositorySession(repoSession);
575 * getAll get all documents for an entity entity service from the Nuxeo
578 * @param ctx service context under which this method is invoked
580 * should be used by the caller to provide and transform the
582 * @throws DocumentException
585 public void getAll(ServiceContext ctx, DocumentHandler handler)
586 throws DocumentNotFoundException, DocumentException {
587 if (handler == null) {
588 throw new IllegalArgumentException(
589 "RepositoryJavaClient.getAll: handler is missing");
591 String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
592 if (nuxeoWspaceId == null) {
593 throw new DocumentNotFoundException(
594 "Unable to find workspace for service "
595 + ctx.getServiceName()
596 + " check if the workspace exists in the Nuxeo repository.");
599 RepositoryInstance repoSession = null;
601 handler.prepare(Action.GET_ALL);
602 repoSession = getRepositorySession();
603 DocumentRef wsDocRef = new IdRef(nuxeoWspaceId);
604 DocumentModelList docList = repoSession.getChildren(wsDocRef);
605 //set reposession to handle the document
606 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
607 DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
608 handler.handle(Action.GET_ALL, wrapDoc);
609 handler.complete(Action.GET_ALL, wrapDoc);
610 } catch (DocumentException de) {
612 } catch (Exception e) {
613 if (logger.isDebugEnabled()) {
614 logger.debug("Caught exception ", e);
616 throw new DocumentException(e);
618 if (repoSession != null) {
619 releaseRepositorySession(repoSession);
624 private boolean isClauseEmpty(String theString) {
625 boolean result = true;
626 if (theString != null && !theString.isEmpty()) {
632 public DocumentWrapper<DocumentModel> getDocFromCsid(
633 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
634 RepositoryInstance repoSession,
637 DocumentWrapper<DocumentModel> result = null;
639 result = new DocumentWrapperImpl(NuxeoUtils.getDocFromCsid(ctx, repoSession, csid));
645 * A method to find a CollectionSpace document (of any type) given just a service context and
646 * its CSID. A search across *all* service workspaces (within a given tenant context) is performed to find
649 * This query searches Nuxeo's Hierarchy table where our CSIDs are stored in the "name" column.
652 public DocumentWrapper<DocumentModel> getDocFromCsid(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
655 DocumentWrapper<DocumentModel> result = null;
656 RepositoryInstance repoSession = null;
658 repoSession = getRepositorySession();
659 result = getDocFromCsid(ctx, repoSession, csid);
661 if (repoSession != null) {
662 releaseRepositorySession(repoSession);
666 if (logger.isWarnEnabled() == true) {
667 logger.warn("Returned DocumentModel instance was created with a repository session that is now closed.");
674 * find doc and return CSID from the Nuxeo repository
675 * @param ctx service context under which this method is invoked
676 * @param whereClause where NXQL where clause to get the document
677 * @throws DocumentException
680 public String getDocURI(DocumentWrapper<DocumentModel> wrappedDoc) throws ClientException {
681 DocumentModel docModel = wrappedDoc.getWrappedObject();
682 String uri = (String)docModel.getProperty(DocumentModelHandler.COLLECTIONSPACE_CORE_SCHEMA,
683 DocumentModelHandler.COLLECTIONSPACE_CORE_URI);
689 * getFiltered get all documents for an entity service from the Document repository,
690 * given filter parameters specified by the handler.
691 * @param ctx service context under which this method is invoked
692 * @param handler should be used by the caller to provide and transform the document
693 * @throws DocumentNotFoundException if workspace not found
694 * @throws DocumentException
697 public void getFiltered(ServiceContext ctx, DocumentHandler handler)
698 throws DocumentNotFoundException, DocumentException {
700 DocumentFilter filter = handler.getDocumentFilter();
701 String oldOrderBy = filter.getOrderByClause();
702 if (isClauseEmpty(oldOrderBy) == true){
703 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?)
705 QueryContext queryContext = new QueryContext(ctx, handler);
707 RepositoryInstance repoSession = null;
709 handler.prepare(Action.GET_ALL);
710 repoSession = getRepositorySession();
711 DocumentModelList docList = null;
712 String query = NuxeoUtils.buildNXQLQuery(ctx, queryContext);
714 if (logger.isDebugEnabled()) {
715 logger.debug("Executing NXQL query: " + query.toString());
718 // If we have limit and/or offset, then pass true to get totalSize
719 // in returned DocumentModelList.
720 Profiler profiler = new Profiler(this, 2);
721 profiler.log("Executing NXQL query: " + query.toString());
723 if ((queryContext.getDocFilter().getOffset() > 0) || (queryContext.getDocFilter().getPageSize() > 0)) {
724 docList = repoSession.query(query, null,
725 queryContext.getDocFilter().getPageSize(), queryContext.getDocFilter().getOffset(), true);
727 docList = repoSession.query(query);
731 //set repoSession to handle the document
732 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
733 DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
734 handler.handle(Action.GET_ALL, wrapDoc);
735 handler.complete(Action.GET_ALL, wrapDoc);
736 } catch (DocumentException de) {
738 } catch (Exception e) {
739 if (logger.isDebugEnabled()) {
740 logger.debug("Caught exception ", e);
742 throw new DocumentException(e);
744 if (repoSession != null) {
745 releaseRepositorySession(repoSession);
750 private String logException(Exception e, String msg) {
751 String result = null;
753 String exceptionMessage = e.getMessage();
754 exceptionMessage = exceptionMessage != null ? exceptionMessage : "<No details provided>";
755 result = msg = msg + ". Caught exception:" + exceptionMessage;
757 if (logger.isTraceEnabled() == true) {
758 logger.error(msg, e);
767 * update given document in the Nuxeo repository
769 * @param ctx service context under which this method is invoked
773 * should be used by the caller to provide and transform the
775 * @throws DocumentException
778 public void update(ServiceContext ctx, String csid, DocumentHandler handler)
779 throws BadRequestException, DocumentNotFoundException,
781 if (handler == null) {
782 throw new IllegalArgumentException(
783 "RepositoryJavaClient.update: document handler is missing.");
786 RepositoryInstance repoSession = null;
788 handler.prepare(Action.UPDATE);
789 repoSession = getRepositorySession();
790 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, csid);
791 DocumentModel doc = null;
793 doc = repoSession.getDocument(docRef);
794 } catch (ClientException ce) {
795 String msg = logException(ce, "Could not find document to update with CSID=" + csid);
796 throw new DocumentNotFoundException(msg, ce);
799 // Set reposession to handle the document
801 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
802 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
803 handler.handle(Action.UPDATE, wrapDoc);
804 repoSession.saveDocument(doc);
806 handler.complete(Action.UPDATE, wrapDoc);
807 } catch (BadRequestException bre) {
809 } catch (DocumentException de) {
811 } catch (WebApplicationException wae){
813 } catch (Exception e) {
814 if (logger.isDebugEnabled()) {
815 logger.debug("Caught exception ", e);
817 throw new DocumentException(e);
819 if (repoSession != null) {
820 releaseRepositorySession(repoSession);
826 * Save a documentModel to the Nuxeo repository.
827 * @param ctx service context under which this method is invoked
828 * @param docModel the document to save
829 * @param fSaveSession if TRUE, will call CoreSession.save() to save accumulated changes.
830 * @throws DocumentException
832 public void saveDocWithoutHandlerProcessing(
833 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
834 RepositoryInstance repoSession,
835 DocumentModel docModel,
836 boolean fSaveSession)
837 throws ClientException, DocumentException {
840 repoSession.saveDocument(docModel);
844 } catch (ClientException ce) {
846 } catch (Exception e) {
847 if (logger.isDebugEnabled()) {
848 logger.debug("Caught exception ", e);
850 throw new DocumentException(e);
856 * Save a list of documentModels to the Nuxeo repository.
858 * @param ctx service context under which this method is invoked
859 * @param docModel the document to save
860 * @param fSaveSession if TRUE, will call CoreSession.save() to save accumulated changes.
861 * @throws DocumentException
863 public void saveDocListWithoutHandlerProcessing(
864 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
865 RepositoryInstance repoSession,
866 DocumentModelList docList,
867 boolean fSaveSession)
868 throws ClientException, DocumentException {
870 repoSession = getRepositorySession();
871 DocumentModel[] docModelArray = new DocumentModel[docList.size()];
872 repoSession.saveDocuments(docList.toArray(docModelArray));
876 } catch (ClientException ce) {
878 } catch (Exception e) {
879 logger.error("Caught exception ", e);
880 throw new DocumentException(e);
885 * delete a document from the Nuxeo repository
886 * @param ctx service context under which this method is invoked
889 * @throws DocumentException
892 public void delete(ServiceContext ctx, String id) throws DocumentNotFoundException,
895 if (logger.isDebugEnabled()) {
896 logger.debug("Deleting document with CSID=" + id);
898 RepositoryInstance repoSession = null;
900 repoSession = getRepositorySession();
901 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
903 repoSession.removeDocument(docRef);
904 } catch (ClientException ce) {
905 String msg = logException(ce, "Could not find document to delete with CSID=" + id);
906 throw new DocumentNotFoundException(msg, ce);
909 } catch (DocumentException de) {
911 } catch (Exception e) {
912 if (logger.isDebugEnabled()) {
913 logger.debug("Caught exception ", e);
915 throw new DocumentException(e);
917 if (repoSession != null) {
918 releaseRepositorySession(repoSession);
924 * @see org.collectionspace.services.common.storage.StorageClient#delete(org.collectionspace.services.common.context.ServiceContext, java.lang.String, org.collectionspace.services.common.document.DocumentHandler)
927 public void delete(ServiceContext ctx, String id, DocumentHandler handler)
928 throws DocumentNotFoundException, DocumentException {
929 throw new UnsupportedOperationException();
933 public Hashtable<String, String> retrieveWorkspaceIds(String domainName) throws Exception {
934 return NuxeoConnectorEmbedded.getInstance().retrieveWorkspaceIds(domainName);
938 public String createDomain(String domainName) throws Exception {
939 RepositoryInstance repoSession = null;
940 String domainId = null;
943 // First create the top-level domain directory
945 repoSession = getRepositorySession();
946 DocumentRef parentDocRef = new PathRef("/");
947 DocumentModel parentDoc = repoSession.getDocument(parentDocRef);
948 DocumentModel domainDoc = repoSession.createDocumentModel(parentDoc.getPathAsString(),
949 domainName, NUXEO_CORE_TYPE_DOMAIN);
950 domainDoc.setPropertyValue("dc:title", domainName);
951 domainDoc.setPropertyValue("dc:description", "A CollectionSpace domain "
953 domainDoc = repoSession.createDocument(domainDoc);
954 domainId = domainDoc.getId();
957 // Next, create a "Workspaces" root directory to contain the workspace folders for the individual service documents
959 DocumentModel workspacesRoot = repoSession.createDocumentModel(domainDoc.getPathAsString(),
960 NuxeoUtils.Workspaces, NUXEO_CORE_TYPE_WORKSPACEROOT);
961 workspacesRoot.setPropertyValue("dc:title", NuxeoUtils.Workspaces);
962 workspacesRoot.setPropertyValue("dc:description", "A CollectionSpace workspaces directory for "
963 + domainDoc.getPathAsString());
964 workspacesRoot = repoSession.createDocument(workspacesRoot);
965 String workspacesRootId = workspacesRoot.getId();
968 if (logger.isDebugEnabled()) {
969 logger.debug("Created tenant domain name=" + domainName
970 + " id=" + domainId + " " +
971 NuxeoUtils.Workspaces + " id=" + workspacesRootId);
972 logger.debug("Path to Domain: "+domainDoc.getPathAsString());
973 logger.debug("Path to Workspaces root: "+workspacesRoot.getPathAsString());
975 } catch (Exception e) {
976 if (logger.isDebugEnabled()) {
977 logger.debug("Could not create tenant domain name=" + domainName + " caught exception ", e);
981 if (repoSession != null) {
982 releaseRepositorySession(repoSession);
990 public String getDomainId(String domainName) throws Exception {
991 String domainId = null;
992 RepositoryInstance repoSession = null;
994 if (domainName != null && !domainName.isEmpty()) {
996 repoSession = getRepositorySession();
997 DocumentRef docRef = new PathRef(
999 DocumentModel domain = repoSession.getDocument(docRef);
1000 domainId = domain.getId();
1001 } catch (Exception e) {
1002 if (logger.isTraceEnabled()) {
1003 logger.trace("Caught exception ", e);
1005 //there is no way to identify if document does not exist due to
1006 //lack of typed exception for getDocument method
1009 if (repoSession != null) {
1010 releaseRepositorySession(repoSession);
1019 * Returns the workspaces root directory for a given domain.
1021 private DocumentModel getWorkspacesRoot(RepositoryInstance repoSession,
1022 String domainName) throws Exception {
1023 DocumentModel result = null;
1025 String domainPath = "/" + domainName;
1026 DocumentRef parentDocRef = new PathRef(domainPath);
1027 DocumentModelList domainChildrenList = repoSession.getChildren(
1029 Iterator<DocumentModel> witer = domainChildrenList.iterator();
1030 while (witer.hasNext()) {
1031 DocumentModel childNode = witer.next();
1032 if (NuxeoUtils.Workspaces.equalsIgnoreCase(childNode.getName())) {
1034 logger.trace("Found workspaces directory at: " + result.getPathAsString());
1039 if (result == null) {
1040 throw new ClientException("Could not find workspace root directory in: "
1048 * @see org.collectionspace.services.common.repository.RepositoryClient#createWorkspace(java.lang.String, java.lang.String)
1051 public String createWorkspace(String domainName, String workspaceName) throws Exception {
1052 RepositoryInstance repoSession = null;
1053 String workspaceId = null;
1055 repoSession = getRepositorySession();
1056 DocumentModel parentDoc = getWorkspacesRoot(repoSession, domainName);
1057 DocumentModel doc = repoSession.createDocumentModel(parentDoc.getPathAsString(),
1058 workspaceName, NuxeoUtils.WORKSPACE_DOCUMENT_TYPE);
1059 doc.setPropertyValue("dc:title", workspaceName);
1060 doc.setPropertyValue("dc:description", "A CollectionSpace workspace for "
1062 doc = repoSession.createDocument(doc);
1063 workspaceId = doc.getId();
1065 if (logger.isDebugEnabled()) {
1066 logger.debug("Created workspace name=" + workspaceName
1067 + " id=" + workspaceId);
1069 } catch (Exception e) {
1070 if (logger.isDebugEnabled()) {
1071 logger.debug("createWorkspace caught exception ", e);
1075 if (repoSession != null) {
1076 releaseRepositorySession(repoSession);
1083 * @see org.collectionspace.services.common.repository.RepositoryClient#getWorkspaceId(java.lang.String, java.lang.String)
1086 public String getWorkspaceId(String tenantDomain, String workspaceName) throws Exception {
1087 String workspaceId = null;
1089 RepositoryInstance repoSession = null;
1091 repoSession = getRepositorySession();
1092 DocumentRef docRef = new PathRef(
1094 + "/" + NuxeoUtils.Workspaces
1095 + "/" + workspaceName);
1096 DocumentModel workspace = repoSession.getDocument(docRef);
1097 workspaceId = workspace.getId();
1098 } catch (DocumentException de) {
1100 } catch (Exception e) {
1101 if (logger.isDebugEnabled()) {
1102 logger.debug("Caught exception ", e);
1104 throw new DocumentException(e);
1106 if (repoSession != null) {
1107 releaseRepositorySession(repoSession);
1116 * Gets the repository session. - Package access only.
1118 * @return the repository session
1119 * @throws Exception the exception
1121 public RepositoryInstance getRepositorySession() throws Exception {
1122 // FIXME: is it possible to reuse repository session?
1123 // Authentication failures happen while trying to reuse the session
1124 Profiler profiler = new Profiler("getRepositorySession():", 2);
1127 NuxeoClientEmbedded client = NuxeoConnectorEmbedded.getInstance().getClient();
1128 RepositoryInstance repoSession = client.openRepository();
1129 if (logger.isTraceEnabled()) {
1130 logger.trace("Testing call to getRepository() repository root: " + repoSession.getRootDocument());
1138 * Release repository session. - Package access only.
1140 * @param repoSession the repo session
1142 public void releaseRepositorySession(RepositoryInstance repoSession) {
1144 NuxeoClientEmbedded client = NuxeoConnectorEmbedded.getInstance().getClient();
1146 client.releaseRepository(repoSession);
1147 } catch (Exception e) {
1148 logger.error("Could not close the repository session", e);
1149 // no need to throw this service specific exception