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.ArrayList;
21 import java.util.Hashtable;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.UUID;
26 import javax.ws.rs.WebApplicationException;
27 import javax.ws.rs.core.MultivaluedMap;
29 import org.collectionspace.services.client.PoxPayloadIn;
30 import org.collectionspace.services.client.PoxPayloadOut;
31 import org.collectionspace.services.client.workflow.WorkflowClient;
32 import org.collectionspace.services.common.context.ServiceContext;
33 import org.collectionspace.services.common.query.QueryContext;
34 import org.collectionspace.services.common.repository.RepositoryClient;
35 import org.collectionspace.services.common.profile.Profiler;
36 import org.collectionspace.services.nuxeo.util.NuxeoUtils;
38 import org.collectionspace.services.common.document.BadRequestException;
39 import org.collectionspace.services.common.document.DocumentException;
40 import org.collectionspace.services.common.document.DocumentFilter;
41 import org.collectionspace.services.common.document.DocumentHandler;
42 import org.collectionspace.services.common.document.DocumentNotFoundException;
43 import org.collectionspace.services.common.document.DocumentHandler.Action;
44 import org.collectionspace.services.common.document.DocumentWrapper;
45 import org.collectionspace.services.common.document.DocumentWrapperImpl;
47 import org.nuxeo.common.utils.IdUtils;
48 import org.nuxeo.ecm.core.api.ClientException;
49 import org.nuxeo.ecm.core.api.DocumentModel;
50 import org.nuxeo.ecm.core.api.DocumentModelList;
51 import org.nuxeo.ecm.core.api.impl.DocumentModelListImpl;
52 import org.nuxeo.ecm.core.api.DocumentRef;
53 import org.nuxeo.ecm.core.api.IdRef;
54 import org.nuxeo.ecm.core.api.PathRef;
55 import org.nuxeo.ecm.core.api.repository.RepositoryInstance;
57 import org.slf4j.Logger;
58 import org.slf4j.LoggerFactory;
61 * RepositoryJavaClient is used to perform CRUD operations on documents in Nuxeo
62 * repository using Remote Java APIs. It uses @see DocumentHandler as IOHandler
65 * $LastChangedRevision: $ $LastChangedDate: $
67 public class RepositoryJavaClientImpl implements RepositoryClient<PoxPayloadIn, PoxPayloadOut> {
70 private final Logger logger = LoggerFactory.getLogger(RepositoryJavaClientImpl.class);
71 // private final Logger profilerLogger = LoggerFactory.getLogger("remperf");
72 // private String foo = Profiler.createLogger();
74 public static final String NUXEO_CORE_TYPE_DOMAIN = "Domain";
75 public static final String NUXEO_CORE_TYPE_WORKSPACEROOT = "WorkspaceRoot";
78 * Instantiates a new repository java client impl.
80 public RepositoryJavaClientImpl() {
85 public void assertWorkflowState(ServiceContext ctx,
86 DocumentModel docModel) throws DocumentNotFoundException, ClientException {
87 MultivaluedMap<String, String> queryParams = ctx.getQueryParams();
88 if (queryParams != null) {
90 // Look for the workflow "delete" query param and see if we need to assert that the
91 // docModel is in a non-deleted workflow state.
93 String currentState = docModel.getCurrentLifeCycleState();
94 String includeDeletedStr = queryParams.getFirst(WorkflowClient.WORKFLOW_QUERY_NONDELETED);
95 boolean includeDeleted = includeDeletedStr == null ? true : Boolean.parseBoolean(includeDeletedStr);
96 if (includeDeleted == false) {
98 // We don't wanted soft-deleted object, so throw an exception if this one is soft-deleted.
100 if (currentState.equalsIgnoreCase(WorkflowClient.WORKFLOWSTATE_DELETED)) {
101 String msg = "The GET assertion that docModel not be in 'deleted' workflow state failed.";
103 throw new DocumentNotFoundException(msg);
110 * create document in the Nuxeo repository
112 * @param ctx service context under which this method is invoked
114 * should be used by the caller to provide and transform the
116 * @return id in repository of the newly created document
117 * @throws DocumentException
120 public String create(ServiceContext ctx,
121 DocumentHandler handler) throws BadRequestException,
124 String docType = NuxeoUtils.getTenantQualifiedDocType(ctx); //ctx.getDocumentType();
125 if (docType == null) {
126 throw new IllegalArgumentException(
127 "RepositoryJavaClient.create: docType is missing");
130 if (handler == null) {
131 throw new IllegalArgumentException(
132 "RepositoryJavaClient.create: handler is missing");
134 String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
135 if (nuxeoWspaceId == null) {
136 throw new DocumentNotFoundException(
137 "Unable to find workspace for service " + ctx.getServiceName()
138 + " check if the workspace exists in the Nuxeo repository");
141 RepositoryInstance repoSession = null;
143 handler.prepare(Action.CREATE);
144 repoSession = getRepositorySession();
145 DocumentRef nuxeoWspace = new IdRef(nuxeoWspaceId);
146 DocumentModel wspaceDoc = repoSession.getDocument(nuxeoWspace);
147 String wspacePath = wspaceDoc.getPathAsString();
148 //give our own ID so PathRef could be constructed later on
149 String id = IdUtils.generateId(UUID.randomUUID().toString());
150 // create document model
151 DocumentModel doc = repoSession.createDocumentModel(wspacePath, id, docType);
152 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
153 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
154 handler.handle(Action.CREATE, wrapDoc);
155 // create document with documentmodel
156 doc = repoSession.createDocument(doc);
158 // TODO for sub-docs need to call into the handler to let it deal with subitems. Pass in the id,
159 // and assume the handler has the state it needs (doc fragments).
160 handler.complete(Action.CREATE, wrapDoc);
162 } catch (BadRequestException bre) {
164 } catch (Exception e) {
165 logger.error("Caught exception ", e);
166 throw new DocumentException(e);
168 if (repoSession != null) {
169 releaseRepositorySession(repoSession);
176 * get document from the Nuxeo repository
177 * @param ctx service context under which this method is invoked
179 * of the document to retrieve
181 * should be used by the caller to provide and transform the
183 * @throws DocumentException
186 public void get(ServiceContext ctx, String id, DocumentHandler handler)
187 throws DocumentNotFoundException, DocumentException {
189 if (handler == null) {
190 throw new IllegalArgumentException(
191 "RepositoryJavaClient.get: handler is missing");
194 RepositoryInstance repoSession = null;
196 handler.prepare(Action.GET);
197 repoSession = getRepositorySession();
198 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
199 DocumentModel docModel = null;
201 docModel = repoSession.getDocument(docRef);
202 assertWorkflowState(ctx, docModel);
203 } catch (ClientException ce) {
204 String msg = logException(ce, "Could not find document with CSID=" + id);
205 throw new DocumentNotFoundException(msg, ce);
208 // Set repository session to handle the document
210 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
211 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(docModel);
212 handler.handle(Action.GET, wrapDoc);
213 handler.complete(Action.GET, wrapDoc);
214 } catch (IllegalArgumentException iae) {
216 } catch (DocumentException de) {
218 } catch (Exception e) {
219 if (logger.isDebugEnabled()) {
220 logger.debug("Caught exception ", e);
222 throw new DocumentException(e);
224 if (repoSession != null) {
225 releaseRepositorySession(repoSession);
231 * get document from the Nuxeo repository, using the docFilter params.
232 * @param ctx service context under which this method is invoked
234 * should be used by the caller to provide and transform the
235 * document. Handler must have a docFilter set to return a single item.
236 * @throws DocumentException
239 public void get(ServiceContext ctx, DocumentHandler handler)
240 throws DocumentNotFoundException, DocumentException {
241 QueryContext queryContext = new QueryContext(ctx, handler);
242 RepositoryInstance repoSession = null;
245 handler.prepare(Action.GET);
246 repoSession = getRepositorySession();
248 DocumentModelList docList = null;
249 // force limit to 1, and ignore totalSize
250 String query = NuxeoUtils.buildNXQLQuery(ctx, queryContext);
251 docList = repoSession.query(query, null, 1, 0, false);
252 if (docList.size() != 1) {
253 throw new DocumentNotFoundException("No document found matching filter params: " + query);
255 DocumentModel doc = docList.get(0);
257 if (logger.isDebugEnabled()) {
258 logger.debug("Executed NXQL query: " + query);
261 //set reposession to handle the document
262 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
263 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
264 handler.handle(Action.GET, wrapDoc);
265 handler.complete(Action.GET, wrapDoc);
266 } catch (IllegalArgumentException iae) {
268 } catch (DocumentException de) {
270 } catch (Exception e) {
271 if (logger.isDebugEnabled()) {
272 logger.debug("Caught exception ", e);
274 throw new DocumentException(e);
276 if (repoSession != null) {
277 releaseRepositorySession(repoSession);
282 public DocumentWrapper<DocumentModel> getDoc(
283 RepositoryInstance repoSession,
284 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
285 String csid) throws DocumentNotFoundException, DocumentException {
286 DocumentWrapper<DocumentModel> wrapDoc = null;
289 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, csid);
290 DocumentModel doc = null;
292 doc = repoSession.getDocument(docRef);
293 } catch (ClientException ce) {
294 String msg = logException(ce, "Could not find document with CSID=" + csid);
295 throw new DocumentNotFoundException(msg, ce);
297 wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
298 } catch (IllegalArgumentException iae) {
300 } catch (DocumentException de) {
308 * Get wrapped documentModel from the Nuxeo repository. The search is restricted to the workspace
309 * of the current context.
311 * @param ctx service context under which this method is invoked
313 * of the document to retrieve
314 * @throws DocumentException
317 public DocumentWrapper<DocumentModel> getDoc(
318 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
319 String csid) throws DocumentNotFoundException, DocumentException {
320 RepositoryInstance repoSession = null;
321 DocumentWrapper<DocumentModel> wrapDoc = null;
324 // Open a new repository session
325 repoSession = getRepositorySession();
326 wrapDoc = getDoc(repoSession, ctx, csid);
327 } catch (IllegalArgumentException iae) {
329 } catch (DocumentException de) {
331 } catch (Exception e) {
332 if (logger.isDebugEnabled()) {
333 logger.debug("Caught exception ", e);
335 throw new DocumentException(e);
337 if (repoSession != null) {
338 releaseRepositorySession(repoSession);
342 if (logger.isWarnEnabled() == true) {
343 logger.warn("Returned DocumentModel instance was created with a repository session that is now closed.");
348 public DocumentWrapper<DocumentModel> findDoc(
349 RepositoryInstance repoSession,
350 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
352 throws DocumentNotFoundException, DocumentException {
353 DocumentWrapper<DocumentModel> wrapDoc = null;
356 QueryContext queryContext = new QueryContext(ctx, whereClause);
357 DocumentModelList docList = null;
358 // force limit to 1, and ignore totalSize
359 String query = NuxeoUtils.buildNXQLQuery(ctx, queryContext);
360 docList = repoSession.query(query,
365 if (docList.size() != 1) {
366 if (logger.isDebugEnabled()) {
367 logger.debug("findDoc: Query found: " + docList.size() + " items.");
368 logger.debug(" Query: " + query);
370 throw new DocumentNotFoundException("No document found matching filter params: " + query);
372 DocumentModel doc = docList.get(0);
373 wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
374 } catch (IllegalArgumentException iae) {
376 } catch (DocumentException de) {
378 } catch (Exception e) {
379 if (logger.isDebugEnabled()) {
380 logger.debug("Caught exception ", e);
382 throw new DocumentException(e);
389 * find wrapped documentModel from the Nuxeo repository
390 * @param ctx service context under which this method is invoked
391 * @param whereClause where NXQL where clause to get the document
392 * @throws DocumentException
395 public DocumentWrapper<DocumentModel> findDoc(
396 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
398 throws DocumentNotFoundException, DocumentException {
399 RepositoryInstance repoSession = null;
400 DocumentWrapper<DocumentModel> wrapDoc = null;
403 repoSession = getRepositorySession();
404 wrapDoc = findDoc(repoSession, ctx, whereClause);
405 } catch (Exception e) {
406 throw new DocumentException("Unable to create a Nuxeo repository session.", e);
408 if (repoSession != null) {
409 releaseRepositorySession(repoSession);
413 if (logger.isWarnEnabled() == true) {
414 logger.warn("Returned DocumentModel instance was created with a repository session that is now closed.");
421 * find doc and return CSID from the Nuxeo repository
422 * @param ctx service context under which this method is invoked
423 * @param whereClause where NXQL where clause to get the document
424 * @throws DocumentException
427 public String findDocCSID(RepositoryInstance repoSession,
428 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx, String whereClause)
429 throws DocumentNotFoundException, DocumentException {
431 boolean releaseSession = false;
433 if(repoSession== null) {
434 repoSession = this.getRepositorySession();
435 releaseSession = true;
437 DocumentWrapper<DocumentModel> wrapDoc = findDoc(repoSession, ctx, whereClause);
438 DocumentModel docModel = wrapDoc.getWrappedObject();
439 csid = NuxeoUtils.getCsid(docModel);//NuxeoUtils.extractId(docModel.getPathAsString());
440 } catch (DocumentNotFoundException dnfe) {
442 } catch (IllegalArgumentException iae) {
444 } catch (DocumentException de) {
446 } catch (Exception e) {
447 if (logger.isDebugEnabled()) {
448 logger.debug("Caught exception ", e);
450 throw new DocumentException(e);
452 if(releaseSession && (repoSession != null)) {
453 this.releaseRepositorySession(repoSession);
459 public DocumentWrapper<DocumentModelList> findDocs(
460 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
461 RepositoryInstance repoSession,
462 List<String> docTypes,
464 int pageSize, int pageNum, boolean computeTotal)
465 throws DocumentNotFoundException, DocumentException {
466 DocumentWrapper<DocumentModelList> wrapDoc = null;
469 if (docTypes == null || docTypes.size() < 1) {
470 throw new DocumentNotFoundException(
471 "The findDocs() method must specify at least one DocumentType.");
473 DocumentModelList docList = null;
474 // force limit to 1, and ignore totalSize
475 QueryContext queryContext = new QueryContext(ctx, whereClause);
476 String query = NuxeoUtils.buildNXQLQuery(docTypes, queryContext);
477 if (logger.isDebugEnabled()) {
478 logger.debug("findDocs() NXQL: "+query);
480 docList = repoSession.query(query, null, pageSize, pageNum, computeTotal);
481 wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
482 } catch (IllegalArgumentException iae) {
484 } catch (Exception e) {
485 if (logger.isDebugEnabled()) {
486 logger.debug("Caught exception ", e);
488 throw new DocumentException(e);
495 * Find a list of documentModels from the Nuxeo repository
496 * @param docTypes a list of DocType names to match
497 * @param whereClause where the clause to qualify on
501 public DocumentWrapper<DocumentModelList> findDocs(
502 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
503 List<String> docTypes,
505 int pageSize, int pageNum, boolean computeTotal)
506 throws DocumentNotFoundException, DocumentException {
507 RepositoryInstance repoSession = null;
508 DocumentWrapper<DocumentModelList> wrapDoc = null;
511 repoSession = getRepositorySession();
512 wrapDoc = findDocs(ctx, repoSession, docTypes, whereClause,
513 pageSize, pageNum, computeTotal);
514 } catch (IllegalArgumentException iae) {
516 } catch (Exception e) {
517 if (logger.isDebugEnabled()) {
518 logger.debug("Caught exception ", e);
520 throw new DocumentException(e);
522 if (repoSession != null) {
523 releaseRepositorySession(repoSession);
527 if (logger.isWarnEnabled() == true) {
528 logger.warn("Returned DocumentModelList instance was created with a repository session that is now closed.");
535 * @see org.collectionspace.services.common.storage.StorageClient#get(org.collectionspace.services.common.context.ServiceContext, java.util.List, org.collectionspace.services.common.document.DocumentHandler)
538 public void get(ServiceContext ctx, List<String> csidList, DocumentHandler handler)
539 throws DocumentNotFoundException, DocumentException {
540 if (handler == null) {
541 throw new IllegalArgumentException(
542 "RepositoryJavaClient.getAll: handler is missing");
545 RepositoryInstance repoSession = null;
547 handler.prepare(Action.GET_ALL);
548 repoSession = getRepositorySession();
549 DocumentModelList docModelList = new DocumentModelListImpl();
550 //FIXME: Should be using NuxeoUtils.createPathRef for security reasons
551 for (String csid : csidList) {
552 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, csid);
553 DocumentModel docModel = repoSession.getDocument(docRef);
554 docModelList.add(docModel);
557 //set reposession to handle the document
558 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
559 DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docModelList);
560 handler.handle(Action.GET_ALL, wrapDoc);
561 handler.complete(Action.GET_ALL, wrapDoc);
562 } catch (DocumentException de) {
564 } catch (Exception e) {
565 if (logger.isDebugEnabled()) {
566 logger.debug("Caught exception ", e);
568 throw new DocumentException(e);
570 if (repoSession != null) {
571 releaseRepositorySession(repoSession);
577 * getAll get all documents for an entity entity service from the Nuxeo
580 * @param ctx service context under which this method is invoked
582 * should be used by the caller to provide and transform the
584 * @throws DocumentException
587 public void getAll(ServiceContext ctx, DocumentHandler handler)
588 throws DocumentNotFoundException, DocumentException {
589 if (handler == null) {
590 throw new IllegalArgumentException(
591 "RepositoryJavaClient.getAll: handler is missing");
593 String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
594 if (nuxeoWspaceId == null) {
595 throw new DocumentNotFoundException(
596 "Unable to find workspace for service "
597 + ctx.getServiceName()
598 + " check if the workspace exists in the Nuxeo repository.");
601 RepositoryInstance repoSession = null;
603 handler.prepare(Action.GET_ALL);
604 repoSession = getRepositorySession();
605 DocumentRef wsDocRef = new IdRef(nuxeoWspaceId);
606 DocumentModelList docList = repoSession.getChildren(wsDocRef);
607 //set reposession to handle the document
608 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
609 DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
610 handler.handle(Action.GET_ALL, wrapDoc);
611 handler.complete(Action.GET_ALL, wrapDoc);
612 } catch (DocumentException de) {
614 } catch (Exception e) {
615 if (logger.isDebugEnabled()) {
616 logger.debug("Caught exception ", e);
618 throw new DocumentException(e);
620 if (repoSession != null) {
621 releaseRepositorySession(repoSession);
626 private boolean isClauseEmpty(String theString) {
627 boolean result = true;
628 if (theString != null && !theString.isEmpty()) {
634 public DocumentWrapper<DocumentModel> getDocFromCsid(
635 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
636 RepositoryInstance repoSession,
639 DocumentWrapper<DocumentModel> result = null;
641 result = new DocumentWrapperImpl(NuxeoUtils.getDocFromCsid(ctx, repoSession, csid));
647 * A method to find a CollectionSpace document (of any type) given just a service context and
648 * its CSID. A search across *all* service workspaces (within a given tenant context) is performed to find
651 * This query searches Nuxeo's Hierarchy table where our CSIDs are stored in the "name" column.
654 public DocumentWrapper<DocumentModel> getDocFromCsid(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
657 DocumentWrapper<DocumentModel> result = null;
658 RepositoryInstance repoSession = null;
660 repoSession = getRepositorySession();
661 result = getDocFromCsid(ctx, repoSession, csid);
663 if (repoSession != null) {
664 releaseRepositorySession(repoSession);
668 if (logger.isWarnEnabled() == true) {
669 logger.warn("Returned DocumentModel instance was created with a repository session that is now closed.");
676 * find doc and return CSID from the Nuxeo repository
677 * @param ctx service context under which this method is invoked
678 * @param whereClause where NXQL where clause to get the document
679 * @throws DocumentException
682 public String getDocURI(DocumentWrapper<DocumentModel> wrappedDoc) throws ClientException {
683 DocumentModel docModel = wrappedDoc.getWrappedObject();
684 String uri = (String)docModel.getProperty(DocumentModelHandler.COLLECTIONSPACE_CORE_SCHEMA,
685 DocumentModelHandler.COLLECTIONSPACE_CORE_URI);
691 * getFiltered get all documents for an entity service from the Document repository,
692 * given filter parameters specified by the handler.
693 * @param ctx service context under which this method is invoked
694 * @param handler should be used by the caller to provide and transform the document
695 * @throws DocumentNotFoundException if workspace not found
696 * @throws DocumentException
699 public void getFiltered(ServiceContext ctx, DocumentHandler handler)
700 throws DocumentNotFoundException, DocumentException {
702 DocumentFilter filter = handler.getDocumentFilter();
703 String oldOrderBy = filter.getOrderByClause();
704 if (isClauseEmpty(oldOrderBy) == true){
705 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?)
707 QueryContext queryContext = new QueryContext(ctx, handler);
709 RepositoryInstance repoSession = null;
711 handler.prepare(Action.GET_ALL);
712 repoSession = getRepositorySession();
713 DocumentModelList docList = null;
714 String query = NuxeoUtils.buildNXQLQuery(ctx, queryContext);
716 if (logger.isDebugEnabled()) {
717 logger.debug("Executing NXQL query: " + query.toString());
720 // If we have limit and/or offset, then pass true to get totalSize
721 // in returned DocumentModelList.
722 Profiler profiler = new Profiler(this, 2);
723 profiler.log("Executing NXQL query: " + query.toString());
725 if ((queryContext.getDocFilter().getOffset() > 0) || (queryContext.getDocFilter().getPageSize() > 0)) {
726 docList = repoSession.query(query, null,
727 queryContext.getDocFilter().getPageSize(), queryContext.getDocFilter().getOffset(), true);
729 docList = repoSession.query(query);
733 //set repoSession to handle the document
734 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
735 DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
736 handler.handle(Action.GET_ALL, wrapDoc);
737 handler.complete(Action.GET_ALL, wrapDoc);
738 } catch (DocumentException de) {
740 } catch (Exception e) {
741 if (logger.isDebugEnabled()) {
742 logger.debug("Caught exception ", e);
744 throw new DocumentException(e);
746 if (repoSession != null) {
747 releaseRepositorySession(repoSession);
752 private String logException(Exception e, String msg) {
753 String result = null;
755 String exceptionMessage = e.getMessage();
756 exceptionMessage = exceptionMessage != null ? exceptionMessage : "<No details provided>";
757 result = msg = msg + ". Caught exception:" + exceptionMessage;
759 if (logger.isTraceEnabled() == true) {
760 logger.error(msg, e);
769 * update given document in the Nuxeo repository
771 * @param ctx service context under which this method is invoked
775 * should be used by the caller to provide and transform the
777 * @throws DocumentException
780 public void update(ServiceContext ctx, String csid, DocumentHandler handler)
781 throws BadRequestException, DocumentNotFoundException,
783 if (handler == null) {
784 throw new IllegalArgumentException(
785 "RepositoryJavaClient.update: document handler is missing.");
788 RepositoryInstance repoSession = null;
790 handler.prepare(Action.UPDATE);
791 repoSession = getRepositorySession();
792 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, csid);
793 DocumentModel doc = null;
795 doc = repoSession.getDocument(docRef);
796 } catch (ClientException ce) {
797 String msg = logException(ce, "Could not find document to update with CSID=" + csid);
798 throw new DocumentNotFoundException(msg, ce);
801 // Set reposession to handle the document
803 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
804 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
805 handler.handle(Action.UPDATE, wrapDoc);
806 repoSession.saveDocument(doc);
808 handler.complete(Action.UPDATE, wrapDoc);
809 } catch (BadRequestException bre) {
811 } catch (DocumentException de) {
813 } catch (WebApplicationException wae){
815 } catch (Exception e) {
816 if (logger.isDebugEnabled()) {
817 logger.debug("Caught exception ", e);
819 throw new DocumentException(e);
821 if (repoSession != null) {
822 releaseRepositorySession(repoSession);
828 * Save a documentModel to the Nuxeo repository.
829 * @param ctx service context under which this method is invoked
830 * @param docModel the document to save
831 * @param fSaveSession if TRUE, will call CoreSession.save() to save accumulated changes.
832 * @throws DocumentException
834 public void saveDocWithoutHandlerProcessing(
835 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
836 RepositoryInstance repoSession,
837 DocumentModel docModel,
838 boolean fSaveSession)
839 throws ClientException, DocumentException {
842 repoSession.saveDocument(docModel);
846 } catch (ClientException ce) {
848 } catch (Exception e) {
849 if (logger.isDebugEnabled()) {
850 logger.debug("Caught exception ", e);
852 throw new DocumentException(e);
858 * Save a list of documentModels to the Nuxeo repository.
860 * @param ctx service context under which this method is invoked
861 * @param docModel the document to save
862 * @param fSaveSession if TRUE, will call CoreSession.save() to save accumulated changes.
863 * @throws DocumentException
865 public void saveDocListWithoutHandlerProcessing(
866 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
867 RepositoryInstance repoSession,
868 DocumentModelList docList,
869 boolean fSaveSession)
870 throws ClientException, DocumentException {
872 repoSession = getRepositorySession();
873 DocumentModel[] docModelArray = new DocumentModel[docList.size()];
874 repoSession.saveDocuments(docList.toArray(docModelArray));
878 } catch (ClientException ce) {
880 } catch (Exception e) {
881 logger.error("Caught exception ", e);
882 throw new DocumentException(e);
887 * delete a document from the Nuxeo repository
888 * @param ctx service context under which this method is invoked
891 * @throws DocumentException
894 public void delete(ServiceContext ctx, String id) throws DocumentNotFoundException,
897 if (logger.isDebugEnabled()) {
898 logger.debug("Deleting document with CSID=" + id);
900 RepositoryInstance repoSession = null;
902 repoSession = getRepositorySession();
903 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
905 repoSession.removeDocument(docRef);
906 } catch (ClientException ce) {
907 String msg = logException(ce, "Could not find document to delete with CSID=" + id);
908 throw new DocumentNotFoundException(msg, ce);
911 } catch (DocumentException de) {
913 } catch (Exception e) {
914 if (logger.isDebugEnabled()) {
915 logger.debug("Caught exception ", e);
917 throw new DocumentException(e);
919 if (repoSession != null) {
920 releaseRepositorySession(repoSession);
926 * @see org.collectionspace.services.common.storage.StorageClient#delete(org.collectionspace.services.common.context.ServiceContext, java.lang.String, org.collectionspace.services.common.document.DocumentHandler)
929 public void delete(ServiceContext ctx, String id, DocumentHandler handler)
930 throws DocumentNotFoundException, DocumentException {
931 throw new UnsupportedOperationException();
935 public Hashtable<String, String> retrieveWorkspaceIds(String domainName) throws Exception {
936 return NuxeoConnectorEmbedded.getInstance().retrieveWorkspaceIds(domainName);
940 public String createDomain(String domainName) throws Exception {
941 RepositoryInstance repoSession = null;
942 String domainId = null;
945 // First create the top-level domain directory
947 repoSession = getRepositorySession();
948 DocumentRef parentDocRef = new PathRef("/");
949 DocumentModel parentDoc = repoSession.getDocument(parentDocRef);
950 DocumentModel domainDoc = repoSession.createDocumentModel(parentDoc.getPathAsString(),
951 domainName, NUXEO_CORE_TYPE_DOMAIN);
952 domainDoc.setPropertyValue("dc:title", domainName);
953 domainDoc.setPropertyValue("dc:description", "A CollectionSpace domain "
955 domainDoc = repoSession.createDocument(domainDoc);
956 domainId = domainDoc.getId();
959 // Next, create a "Workspaces" root directory to contain the workspace folders for the individual service documents
961 DocumentModel workspacesRoot = repoSession.createDocumentModel(domainDoc.getPathAsString(),
962 NuxeoUtils.Workspaces, NUXEO_CORE_TYPE_WORKSPACEROOT);
963 workspacesRoot.setPropertyValue("dc:title", NuxeoUtils.Workspaces);
964 workspacesRoot.setPropertyValue("dc:description", "A CollectionSpace workspaces directory for "
965 + domainDoc.getPathAsString());
966 workspacesRoot = repoSession.createDocument(workspacesRoot);
967 String workspacesRootId = workspacesRoot.getId();
970 if (logger.isDebugEnabled()) {
971 logger.debug("Created tenant domain name=" + domainName
972 + " id=" + domainId + " " +
973 NuxeoUtils.Workspaces + " id=" + workspacesRootId);
974 logger.debug("Path to Domain: "+domainDoc.getPathAsString());
975 logger.debug("Path to Workspaces root: "+workspacesRoot.getPathAsString());
977 } catch (Exception e) {
978 if (logger.isDebugEnabled()) {
979 logger.debug("Could not create tenant domain name=" + domainName + " caught exception ", e);
983 if (repoSession != null) {
984 releaseRepositorySession(repoSession);
992 public String getDomainId(String domainName) throws Exception {
993 String domainId = null;
994 RepositoryInstance repoSession = null;
996 if (domainName != null && !domainName.isEmpty()) {
998 repoSession = getRepositorySession();
999 DocumentRef docRef = new PathRef(
1001 DocumentModel domain = repoSession.getDocument(docRef);
1002 domainId = domain.getId();
1003 } catch (Exception e) {
1004 if (logger.isTraceEnabled()) {
1005 logger.trace("Caught exception ", e);
1007 //there is no way to identify if document does not exist due to
1008 //lack of typed exception for getDocument method
1011 if (repoSession != null) {
1012 releaseRepositorySession(repoSession);
1021 * Returns the workspaces root directory for a given domain.
1023 private DocumentModel getWorkspacesRoot(RepositoryInstance repoSession,
1024 String domainName) throws Exception {
1025 DocumentModel result = null;
1027 String domainPath = "/" + domainName;
1028 DocumentRef parentDocRef = new PathRef(domainPath);
1029 DocumentModelList domainChildrenList = repoSession.getChildren(
1031 Iterator<DocumentModel> witer = domainChildrenList.iterator();
1032 while (witer.hasNext()) {
1033 DocumentModel childNode = witer.next();
1034 if (NuxeoUtils.Workspaces.equalsIgnoreCase(childNode.getName())) {
1036 logger.trace("Found workspaces directory at: " + result.getPathAsString());
1041 if (result == null) {
1042 throw new ClientException("Could not find workspace root directory in: "
1050 * @see org.collectionspace.services.common.repository.RepositoryClient#createWorkspace(java.lang.String, java.lang.String)
1053 public String createWorkspace(String domainName, String workspaceName) throws Exception {
1054 RepositoryInstance repoSession = null;
1055 String workspaceId = null;
1057 repoSession = getRepositorySession();
1058 DocumentModel parentDoc = getWorkspacesRoot(repoSession, domainName);
1059 DocumentModel doc = repoSession.createDocumentModel(parentDoc.getPathAsString(),
1060 workspaceName, NuxeoUtils.WORKSPACE_DOCUMENT_TYPE);
1061 doc.setPropertyValue("dc:title", workspaceName);
1062 doc.setPropertyValue("dc:description", "A CollectionSpace workspace for "
1064 doc = repoSession.createDocument(doc);
1065 workspaceId = doc.getId();
1067 if (logger.isDebugEnabled()) {
1068 logger.debug("Created workspace name=" + workspaceName
1069 + " id=" + workspaceId);
1071 } catch (Exception e) {
1072 if (logger.isDebugEnabled()) {
1073 logger.debug("createWorkspace caught exception ", e);
1077 if (repoSession != null) {
1078 releaseRepositorySession(repoSession);
1085 * @see org.collectionspace.services.common.repository.RepositoryClient#getWorkspaceId(java.lang.String, java.lang.String)
1088 public String getWorkspaceId(String tenantDomain, String workspaceName) throws Exception {
1089 String workspaceId = null;
1091 RepositoryInstance repoSession = null;
1093 repoSession = getRepositorySession();
1094 DocumentRef docRef = new PathRef(
1096 + "/" + NuxeoUtils.Workspaces
1097 + "/" + workspaceName);
1098 DocumentModel workspace = repoSession.getDocument(docRef);
1099 workspaceId = workspace.getId();
1100 } catch (DocumentException de) {
1102 } catch (Exception e) {
1103 if (logger.isDebugEnabled()) {
1104 logger.debug("Caught exception ", e);
1106 throw new DocumentException(e);
1108 if (repoSession != null) {
1109 releaseRepositorySession(repoSession);
1118 * Gets the repository session. - Package access only.
1120 * @return the repository session
1121 * @throws Exception the exception
1123 public RepositoryInstance getRepositorySession() throws Exception {
1124 // FIXME: is it possible to reuse repository session?
1125 // Authentication failures happen while trying to reuse the session
1126 Profiler profiler = new Profiler("getRepositorySession():", 2);
1129 NuxeoClientEmbedded client = NuxeoConnectorEmbedded.getInstance().getClient();
1130 RepositoryInstance repoSession = client.openRepository();
1131 if (logger.isTraceEnabled()) {
1132 logger.trace("Testing call to getRepository() repository root: " + repoSession.getRootDocument());
1140 * Release repository session. - Package access only.
1142 * @param repoSession the repo session
1144 public void releaseRepositorySession(RepositoryInstance repoSession) {
1146 NuxeoClientEmbedded client = NuxeoConnectorEmbedded.getInstance().getClient();
1148 client.releaseRepository(repoSession);
1149 } catch (Exception e) {
1150 logger.error("Could not close the repository session", e);
1151 // no need to throw this service specific exception