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.io.Serializable;
21 import java.util.Hashtable;
22 import java.util.Iterator;
23 import java.util.List;
25 import java.util.UUID;
27 import javax.ws.rs.WebApplicationException;
28 import javax.ws.rs.core.MultivaluedMap;
30 import org.collectionspace.services.client.PoxPayloadIn;
31 import org.collectionspace.services.client.PoxPayloadOut;
32 import org.collectionspace.services.client.workflow.WorkflowClient;
33 import org.collectionspace.services.common.context.ServiceContext;
34 import org.collectionspace.services.common.query.QueryContext;
35 import org.collectionspace.services.common.repository.RepositoryClient;
36 import org.collectionspace.services.common.profile.Profiler;
37 import org.collectionspace.services.lifecycle.TransitionDef;
38 import org.collectionspace.services.nuxeo.util.NuxeoUtils;
40 import org.collectionspace.services.common.document.BadRequestException;
41 import org.collectionspace.services.common.document.DocumentException;
42 import org.collectionspace.services.common.document.DocumentFilter;
43 import org.collectionspace.services.common.document.DocumentHandler;
44 import org.collectionspace.services.common.document.DocumentNotFoundException;
45 import org.collectionspace.services.common.document.DocumentHandler.Action;
46 import org.collectionspace.services.common.document.DocumentWrapper;
47 import org.collectionspace.services.common.document.DocumentWrapperImpl;
49 import org.nuxeo.common.utils.IdUtils;
50 import org.nuxeo.ecm.core.api.ClientException;
51 import org.nuxeo.ecm.core.api.DocumentModel;
52 import org.nuxeo.ecm.core.api.DocumentModelList;
53 import org.nuxeo.ecm.core.api.IterableQueryResult;
54 import org.nuxeo.ecm.core.api.impl.DocumentModelListImpl;
55 import org.nuxeo.ecm.core.api.DocumentRef;
56 import org.nuxeo.ecm.core.api.IdRef;
57 import org.nuxeo.ecm.core.api.PathRef;
58 import org.nuxeo.ecm.core.api.repository.RepositoryInstance;
61 // CSPACE-5036 - How to make CMISQL queries from Nuxeo
63 import org.apache.chemistry.opencmis.commons.server.CallContext;
64 import org.apache.chemistry.opencmis.server.impl.CallContextImpl;
65 import org.nuxeo.ecm.core.opencmis.impl.server.NuxeoCmisService;
66 import org.nuxeo.ecm.core.opencmis.impl.server.NuxeoRepository;
68 import org.slf4j.Logger;
69 import org.slf4j.LoggerFactory;
72 * RepositoryJavaClient is used to perform CRUD operations on documents in Nuxeo
73 * repository using Remote Java APIs. It uses @see DocumentHandler as IOHandler
76 * $LastChangedRevision: $ $LastChangedDate: $
78 public class RepositoryJavaClientImpl implements RepositoryClient<PoxPayloadIn, PoxPayloadOut> {
81 private final Logger logger = LoggerFactory.getLogger(RepositoryJavaClientImpl.class);
82 // private final Logger profilerLogger = LoggerFactory.getLogger("remperf");
83 // private String foo = Profiler.createLogger();
85 public static final String NUXEO_CORE_TYPE_DOMAIN = "Domain";
86 public static final String NUXEO_CORE_TYPE_WORKSPACEROOT = "WorkspaceRoot";
89 * Instantiates a new repository java client impl.
91 public RepositoryJavaClientImpl() {
96 public void assertWorkflowState(ServiceContext ctx,
97 DocumentModel docModel) throws DocumentNotFoundException, ClientException {
98 MultivaluedMap<String, String> queryParams = ctx.getQueryParams();
99 if (queryParams != null) {
101 // Look for the workflow "delete" query param and see if we need to assert that the
102 // docModel is in a non-deleted workflow state.
104 String currentState = docModel.getCurrentLifeCycleState();
105 String includeDeletedStr = queryParams.getFirst(WorkflowClient.WORKFLOW_QUERY_NONDELETED);
106 boolean includeDeleted = includeDeletedStr == null ? true : Boolean.parseBoolean(includeDeletedStr);
107 if (includeDeleted == false) {
109 // We don't wanted soft-deleted object, so throw an exception if this one is soft-deleted.
111 if (currentState.equalsIgnoreCase(WorkflowClient.WORKFLOWSTATE_DELETED)) {
112 String msg = "The GET assertion that docModel not be in 'deleted' workflow state failed.";
114 throw new DocumentNotFoundException(msg);
121 * create document in the Nuxeo repository
123 * @param ctx service context under which this method is invoked
125 * should be used by the caller to provide and transform the
127 * @return id in repository of the newly created document
128 * @throws DocumentException
131 public String create(ServiceContext ctx,
132 DocumentHandler handler) throws BadRequestException,
135 String docType = NuxeoUtils.getTenantQualifiedDocType(ctx); //ctx.getDocumentType();
136 if (docType == null) {
137 throw new IllegalArgumentException(
138 "RepositoryJavaClient.create: docType is missing");
141 if (handler == null) {
142 throw new IllegalArgumentException(
143 "RepositoryJavaClient.create: handler is missing");
145 String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
146 if (nuxeoWspaceId == null) {
147 throw new DocumentNotFoundException(
148 "Unable to find workspace for service " + ctx.getServiceName()
149 + " check if the workspace exists in the Nuxeo repository");
152 RepositoryInstance repoSession = null;
154 handler.prepare(Action.CREATE);
155 repoSession = getRepositorySession();
156 DocumentRef nuxeoWspace = new IdRef(nuxeoWspaceId);
157 DocumentModel wspaceDoc = repoSession.getDocument(nuxeoWspace);
158 String wspacePath = wspaceDoc.getPathAsString();
159 //give our own ID so PathRef could be constructed later on
160 String id = IdUtils.generateId(UUID.randomUUID().toString());
161 // create document model
162 DocumentModel doc = repoSession.createDocumentModel(wspacePath, id, docType);
163 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
164 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
165 handler.handle(Action.CREATE, wrapDoc);
166 // create document with documentmodel
167 doc = repoSession.createDocument(doc);
169 // TODO for sub-docs need to call into the handler to let it deal with subitems. Pass in the id,
170 // and assume the handler has the state it needs (doc fragments).
171 handler.complete(Action.CREATE, wrapDoc);
173 } catch (BadRequestException bre) {
175 } catch (Exception e) {
176 logger.error("Caught exception ", e);
177 throw new DocumentException(e);
179 if (repoSession != null) {
180 releaseRepositorySession(repoSession);
187 * get document from the Nuxeo repository
188 * @param ctx service context under which this method is invoked
190 * of the document to retrieve
192 * should be used by the caller to provide and transform the
194 * @throws DocumentException
197 public void get(ServiceContext ctx, String id, DocumentHandler handler)
198 throws DocumentNotFoundException, DocumentException {
200 if (handler == null) {
201 throw new IllegalArgumentException(
202 "RepositoryJavaClient.get: handler is missing");
205 RepositoryInstance repoSession = null;
207 handler.prepare(Action.GET);
208 repoSession = getRepositorySession();
209 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
210 DocumentModel docModel = null;
212 docModel = repoSession.getDocument(docRef);
213 assertWorkflowState(ctx, docModel);
214 } catch (ClientException ce) {
215 String msg = logException(ce, "Could not find document with CSID=" + id);
216 throw new DocumentNotFoundException(msg, ce);
219 // Set repository session to handle the document
221 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
222 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(docModel);
223 handler.handle(Action.GET, wrapDoc);
224 handler.complete(Action.GET, wrapDoc);
225 } catch (IllegalArgumentException iae) {
227 } catch (DocumentException de) {
229 } catch (Exception e) {
230 if (logger.isDebugEnabled()) {
231 logger.debug("Caught exception ", e);
233 throw new DocumentException(e);
235 if (repoSession != null) {
236 releaseRepositorySession(repoSession);
242 * get document from the Nuxeo repository, using the docFilter params.
243 * @param ctx service context under which this method is invoked
245 * should be used by the caller to provide and transform the
246 * document. Handler must have a docFilter set to return a single item.
247 * @throws DocumentException
250 public void get(ServiceContext ctx, DocumentHandler handler)
251 throws DocumentNotFoundException, DocumentException {
252 QueryContext queryContext = new QueryContext(ctx, handler);
253 RepositoryInstance repoSession = null;
256 handler.prepare(Action.GET);
257 repoSession = getRepositorySession();
259 DocumentModelList docList = null;
260 // force limit to 1, and ignore totalSize
261 String query = NuxeoUtils.buildNXQLQuery(ctx, queryContext);
262 docList = repoSession.query(query, null, 1, 0, false);
263 if (docList.size() != 1) {
264 throw new DocumentNotFoundException("No document found matching filter params: " + query);
266 DocumentModel doc = docList.get(0);
268 if (logger.isDebugEnabled()) {
269 logger.debug("Executed NXQL query: " + query);
272 //set reposession to handle the document
273 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
274 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
275 handler.handle(Action.GET, wrapDoc);
276 handler.complete(Action.GET, wrapDoc);
277 } catch (IllegalArgumentException iae) {
279 } catch (DocumentException de) {
281 } catch (Exception e) {
282 if (logger.isDebugEnabled()) {
283 logger.debug("Caught exception ", e);
285 throw new DocumentException(e);
287 if (repoSession != null) {
288 releaseRepositorySession(repoSession);
293 public DocumentWrapper<DocumentModel> getDoc(
294 RepositoryInstance repoSession,
295 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
296 String csid) throws DocumentNotFoundException, DocumentException {
297 DocumentWrapper<DocumentModel> wrapDoc = null;
300 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, csid);
301 DocumentModel doc = null;
303 doc = repoSession.getDocument(docRef);
304 } catch (ClientException ce) {
305 String msg = logException(ce, "Could not find document with CSID=" + csid);
306 throw new DocumentNotFoundException(msg, ce);
308 wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
309 } catch (IllegalArgumentException iae) {
311 } catch (DocumentException de) {
319 * Get wrapped documentModel from the Nuxeo repository. The search is restricted to the workspace
320 * of the current context.
322 * @param ctx service context under which this method is invoked
324 * of the document to retrieve
325 * @throws DocumentException
328 public DocumentWrapper<DocumentModel> getDoc(
329 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
330 String csid) throws DocumentNotFoundException, DocumentException {
331 RepositoryInstance repoSession = null;
332 DocumentWrapper<DocumentModel> wrapDoc = null;
335 // Open a new repository session
336 repoSession = getRepositorySession();
337 wrapDoc = getDoc(repoSession, ctx, csid);
338 } catch (IllegalArgumentException iae) {
340 } catch (DocumentException de) {
342 } catch (Exception e) {
343 if (logger.isDebugEnabled()) {
344 logger.debug("Caught exception ", e);
346 throw new DocumentException(e);
348 if (repoSession != null) {
349 releaseRepositorySession(repoSession);
353 if (logger.isWarnEnabled() == true) {
354 logger.warn("Returned DocumentModel instance was created with a repository session that is now closed.");
359 public DocumentWrapper<DocumentModel> findDoc(
360 RepositoryInstance repoSession,
361 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
363 throws DocumentNotFoundException, DocumentException {
364 DocumentWrapper<DocumentModel> wrapDoc = null;
367 QueryContext queryContext = new QueryContext(ctx, whereClause);
368 DocumentModelList docList = null;
369 // force limit to 1, and ignore totalSize
370 String query = NuxeoUtils.buildNXQLQuery(ctx, queryContext);
371 docList = repoSession.query(query,
376 if (docList.size() != 1) {
377 if (logger.isDebugEnabled()) {
378 logger.debug("findDoc: Query found: " + docList.size() + " items.");
379 logger.debug(" Query: " + query);
381 throw new DocumentNotFoundException("No document found matching filter params: " + query);
383 DocumentModel doc = docList.get(0);
384 wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
385 } catch (IllegalArgumentException iae) {
387 } catch (DocumentException de) {
389 } catch (Exception e) {
390 if (logger.isDebugEnabled()) {
391 logger.debug("Caught exception ", e);
393 throw new DocumentException(e);
400 * find wrapped documentModel from the Nuxeo repository
401 * @param ctx service context under which this method is invoked
402 * @param whereClause where NXQL where clause to get the document
403 * @throws DocumentException
406 public DocumentWrapper<DocumentModel> findDoc(
407 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
409 throws DocumentNotFoundException, DocumentException {
410 RepositoryInstance repoSession = null;
411 DocumentWrapper<DocumentModel> wrapDoc = null;
414 repoSession = getRepositorySession();
415 wrapDoc = findDoc(repoSession, ctx, whereClause);
416 } catch (Exception e) {
417 throw new DocumentException("Unable to create a Nuxeo repository session.", e);
419 if (repoSession != null) {
420 releaseRepositorySession(repoSession);
424 if (logger.isWarnEnabled() == true) {
425 logger.warn("Returned DocumentModel instance was created with a repository session that is now closed.");
432 * find doc and return CSID from the Nuxeo repository
433 * @param ctx service context under which this method is invoked
434 * @param whereClause where NXQL where clause to get the document
435 * @throws DocumentException
438 public String findDocCSID(RepositoryInstance repoSession,
439 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx, String whereClause)
440 throws DocumentNotFoundException, DocumentException {
442 boolean releaseSession = false;
444 if(repoSession== null) {
445 repoSession = this.getRepositorySession();
446 releaseSession = true;
448 DocumentWrapper<DocumentModel> wrapDoc = findDoc(repoSession, ctx, whereClause);
449 DocumentModel docModel = wrapDoc.getWrappedObject();
450 csid = NuxeoUtils.getCsid(docModel);//NuxeoUtils.extractId(docModel.getPathAsString());
451 } catch (DocumentNotFoundException dnfe) {
453 } catch (IllegalArgumentException iae) {
455 } catch (DocumentException de) {
457 } catch (Exception e) {
458 if (logger.isDebugEnabled()) {
459 logger.debug("Caught exception ", e);
461 throw new DocumentException(e);
463 if(releaseSession && (repoSession != null)) {
464 this.releaseRepositorySession(repoSession);
470 public DocumentWrapper<DocumentModelList> findDocs(
471 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
472 RepositoryInstance repoSession,
473 List<String> docTypes,
475 int pageSize, int pageNum, boolean computeTotal)
476 throws DocumentNotFoundException, DocumentException {
477 DocumentWrapper<DocumentModelList> wrapDoc = null;
480 if (docTypes == null || docTypes.size() < 1) {
481 throw new DocumentNotFoundException(
482 "The findDocs() method must specify at least one DocumentType.");
484 DocumentModelList docList = null;
485 QueryContext queryContext = new QueryContext(ctx, whereClause);
486 String query = NuxeoUtils.buildNXQLQuery(docTypes, queryContext);
487 if (logger.isDebugEnabled()) {
488 logger.debug("findDocs() NXQL: "+query);
490 docList = repoSession.query(query, null, pageSize, pageNum, computeTotal);
491 wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
492 } catch (IllegalArgumentException iae) {
494 } catch (Exception e) {
495 if (logger.isDebugEnabled()) {
496 logger.debug("Caught exception ", e);
498 throw new DocumentException(e);
505 * Find a list of documentModels from the Nuxeo repository
506 * @param docTypes a list of DocType names to match
507 * @param whereClause where the clause to qualify on
511 public DocumentWrapper<DocumentModelList> findDocs(
512 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
513 List<String> docTypes,
515 int pageSize, int pageNum, boolean computeTotal)
516 throws DocumentNotFoundException, DocumentException {
517 RepositoryInstance repoSession = null;
518 DocumentWrapper<DocumentModelList> wrapDoc = null;
521 repoSession = getRepositorySession();
522 wrapDoc = findDocs(ctx, repoSession, docTypes, whereClause,
523 pageSize, pageNum, computeTotal);
524 } catch (IllegalArgumentException iae) {
526 } catch (Exception e) {
527 if (logger.isDebugEnabled()) {
528 logger.debug("Caught exception ", e);
530 throw new DocumentException(e);
532 if (repoSession != null) {
533 releaseRepositorySession(repoSession);
537 if (logger.isWarnEnabled() == true) {
538 logger.warn("Returned DocumentModelList instance was created with a repository session that is now closed.");
545 * @see org.collectionspace.services.common.storage.StorageClient#get(org.collectionspace.services.common.context.ServiceContext, java.util.List, org.collectionspace.services.common.document.DocumentHandler)
548 public void get(ServiceContext ctx, List<String> csidList, DocumentHandler handler)
549 throws DocumentNotFoundException, DocumentException {
550 if (handler == null) {
551 throw new IllegalArgumentException(
552 "RepositoryJavaClient.getAll: handler is missing");
555 RepositoryInstance repoSession = null;
557 handler.prepare(Action.GET_ALL);
558 repoSession = getRepositorySession();
559 DocumentModelList docModelList = new DocumentModelListImpl();
560 //FIXME: Should be using NuxeoUtils.createPathRef for security reasons
561 for (String csid : csidList) {
562 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, csid);
563 DocumentModel docModel = repoSession.getDocument(docRef);
564 docModelList.add(docModel);
567 //set reposession to handle the document
568 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
569 DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docModelList);
570 handler.handle(Action.GET_ALL, wrapDoc);
571 handler.complete(Action.GET_ALL, wrapDoc);
572 } catch (DocumentException de) {
574 } catch (Exception e) {
575 if (logger.isDebugEnabled()) {
576 logger.debug("Caught exception ", e);
578 throw new DocumentException(e);
580 if (repoSession != null) {
581 releaseRepositorySession(repoSession);
587 * getAll get all documents for an entity entity service from the Nuxeo
590 * @param ctx service context under which this method is invoked
592 * should be used by the caller to provide and transform the
594 * @throws DocumentException
597 public void getAll(ServiceContext ctx, DocumentHandler handler)
598 throws DocumentNotFoundException, DocumentException {
599 if (handler == null) {
600 throw new IllegalArgumentException(
601 "RepositoryJavaClient.getAll: handler is missing");
603 String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
604 if (nuxeoWspaceId == null) {
605 throw new DocumentNotFoundException(
606 "Unable to find workspace for service "
607 + ctx.getServiceName()
608 + " check if the workspace exists in the Nuxeo repository.");
611 RepositoryInstance repoSession = null;
613 handler.prepare(Action.GET_ALL);
614 repoSession = getRepositorySession();
615 DocumentRef wsDocRef = new IdRef(nuxeoWspaceId);
616 DocumentModelList docList = repoSession.getChildren(wsDocRef);
617 //set reposession to handle the document
618 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
619 DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
620 handler.handle(Action.GET_ALL, wrapDoc);
621 handler.complete(Action.GET_ALL, wrapDoc);
622 } catch (DocumentException de) {
624 } catch (Exception e) {
625 if (logger.isDebugEnabled()) {
626 logger.debug("Caught exception ", e);
628 throw new DocumentException(e);
630 if (repoSession != null) {
631 releaseRepositorySession(repoSession);
636 private boolean isClauseEmpty(String theString) {
637 boolean result = true;
638 if (theString != null && !theString.isEmpty()) {
644 public DocumentWrapper<DocumentModel> getDocFromCsid(
645 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
646 RepositoryInstance repoSession,
649 DocumentWrapper<DocumentModel> result = null;
651 result = new DocumentWrapperImpl(NuxeoUtils.getDocFromCsid(ctx, repoSession, csid));
657 * A method to find a CollectionSpace document (of any type) given just a service context and
658 * its CSID. A search across *all* service workspaces (within a given tenant context) is performed to find
661 * This query searches Nuxeo's Hierarchy table where our CSIDs are stored in the "name" column.
664 public DocumentWrapper<DocumentModel> getDocFromCsid(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
667 DocumentWrapper<DocumentModel> result = null;
668 RepositoryInstance repoSession = null;
670 repoSession = getRepositorySession();
671 result = getDocFromCsid(ctx, repoSession, csid);
673 if (repoSession != null) {
674 releaseRepositorySession(repoSession);
678 if (logger.isWarnEnabled() == true) {
679 logger.warn("Returned DocumentModel instance was created with a repository session that is now closed.");
686 * find doc and return CSID from the Nuxeo repository
687 * @param ctx service context under which this method is invoked
688 * @param whereClause where NXQL where clause to get the document
689 * @throws DocumentException
692 public String getDocURI(DocumentWrapper<DocumentModel> wrappedDoc) throws ClientException {
693 DocumentModel docModel = wrappedDoc.getWrappedObject();
694 String uri = (String)docModel.getProperty(DocumentModelHandler.COLLECTIONSPACE_CORE_SCHEMA,
695 DocumentModelHandler.COLLECTIONSPACE_CORE_URI);
700 * See CSPACE-5036 - How to make CMISQL queries from Nuxeo
702 private void makeCMISQLQuery(RepositoryInstance repoSession) {
703 // the NuxeoRepository should be constructed only once, then cached
704 // (its construction is expensive)
706 NuxeoRepository repo = new NuxeoRepository(repoSession.getRepositoryName(),
707 repoSession.getRootDocument().getId());
708 logger.debug("Repository ID:" + repo.getId() + " Root folder:" + repo.getRootFolderId());
710 CallContextImpl callContext = new CallContextImpl(CallContext.BINDING_LOCAL,
711 repo.getId(), false);
712 callContext.put(CallContext.USERNAME, repoSession.getPrincipal().getName());
713 NuxeoCmisService cmisService = new NuxeoCmisService(repo, callContext, repoSession);
716 // String query = "SELECT cmis:objectId, dc:title FROM cmis:document WHERE dc:title = 'REMBlobs'"; // try eaee111c-a8d8-48c7-95cb
717 String query = "SELECT cmis:objectId, cmis:name, dc:title, nuxeo:lifecycleState FROM Dimension WHERE dc:title = 'REMBlobs'"; // try eaee111c-a8d8-48c7-95cb
718 // String query = "SELECT * from Dimension D JOIN Relation R ON D.cmis:name = R.relations_common:objectcsid";
719 // String query = "SELECT * FROM cmis:document WHERE dc:title = 'REMBlobs'"; // try eaee111c-a8d8-48c7-95cb
720 IterableQueryResult result = repoSession.queryAndFetch(query, "CMISQL", cmisService);
721 for (Map<String, Serializable> row : result) {
722 logger.debug("dc:title is: " + (String)row.get("dc:title")
723 + " Hierarchy Table ID is:" + row.get("cmis:objectId")
724 + " cmis:name is: " + row.get("cmis:name")
725 + " nuxeo:lifecycleState is: " + row.get("nuxeo:lifecycleState")
728 } catch (ClientException e) {
729 // TODO Auto-generated catch block
735 * getFiltered get all documents for an entity service from the Document repository,
736 * given filter parameters specified by the handler.
737 * @param ctx service context under which this method is invoked
738 * @param handler should be used by the caller to provide and transform the document
739 * @throws DocumentNotFoundException if workspace not found
740 * @throws DocumentException
743 public void getFiltered(ServiceContext ctx, DocumentHandler handler)
744 throws DocumentNotFoundException, DocumentException {
746 DocumentFilter filter = handler.getDocumentFilter();
747 String oldOrderBy = filter.getOrderByClause();
748 if (isClauseEmpty(oldOrderBy) == true){
749 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?)
751 QueryContext queryContext = new QueryContext(ctx, handler);
753 RepositoryInstance repoSession = null;
755 handler.prepare(Action.GET_ALL);
756 repoSession = getRepositorySession();
758 // CSPACE-5036 - How to make CMISQL queries from Nuxeo
760 makeCMISQLQuery(repoSession);
762 DocumentModelList docList = null;
763 String query = NuxeoUtils.buildNXQLQuery(ctx, queryContext);
765 if (logger.isDebugEnabled()) {
766 logger.debug("Executing NXQL query: " + query.toString());
769 // If we have limit and/or offset, then pass true to get totalSize
770 // in returned DocumentModelList.
771 Profiler profiler = new Profiler(this, 2);
772 profiler.log("Executing NXQL query: " + query.toString());
774 if ((queryContext.getDocFilter().getOffset() > 0) || (queryContext.getDocFilter().getPageSize() > 0)) {
775 docList = repoSession.query(query, null,
776 queryContext.getDocFilter().getPageSize(), queryContext.getDocFilter().getOffset(), true);
778 docList = repoSession.query(query);
782 //set repoSession to handle the document
783 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
784 DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
785 handler.handle(Action.GET_ALL, wrapDoc);
786 handler.complete(Action.GET_ALL, wrapDoc);
787 } catch (DocumentException de) {
789 } catch (Exception e) {
790 if (logger.isDebugEnabled()) {
791 logger.debug("Caught exception ", e);
793 throw new DocumentException(e);
795 if (repoSession != null) {
796 releaseRepositorySession(repoSession);
801 private String logException(Exception e, String msg) {
802 String result = null;
804 String exceptionMessage = e.getMessage();
805 exceptionMessage = exceptionMessage != null ? exceptionMessage : "<No details provided>";
806 result = msg = msg + ". Caught exception:" + exceptionMessage;
808 if (logger.isTraceEnabled() == true) {
809 logger.error(msg, e);
818 * update given document in the Nuxeo repository
820 * @param ctx service context under which this method is invoked
824 * should be used by the caller to provide and transform the
826 * @throws DocumentException
829 public void update(ServiceContext ctx, String csid, DocumentHandler handler)
830 throws BadRequestException, DocumentNotFoundException,
832 if (handler == null) {
833 throw new IllegalArgumentException(
834 "RepositoryJavaClient.update: document handler is missing.");
837 RepositoryInstance repoSession = null;
839 handler.prepare(Action.UPDATE);
840 repoSession = getRepositorySession();
841 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, csid);
842 DocumentModel doc = null;
844 doc = repoSession.getDocument(docRef);
845 } catch (ClientException ce) {
846 String msg = logException(ce, "Could not find document to update with CSID=" + csid);
847 throw new DocumentNotFoundException(msg, ce);
850 // Set reposession to handle the document
852 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
853 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
854 handler.handle(Action.UPDATE, wrapDoc);
855 repoSession.saveDocument(doc);
857 handler.complete(Action.UPDATE, wrapDoc);
858 } catch (BadRequestException bre) {
860 } catch (DocumentException de) {
862 } catch (WebApplicationException wae){
864 } catch (Exception e) {
865 if (logger.isDebugEnabled()) {
866 logger.debug("Caught exception ", e);
868 throw new DocumentException(e);
870 if (repoSession != null) {
871 releaseRepositorySession(repoSession);
877 * Save a documentModel to the Nuxeo repository.
878 * @param ctx service context under which this method is invoked
879 * @param docModel the document to save
880 * @param fSaveSession if TRUE, will call CoreSession.save() to save accumulated changes.
881 * @throws DocumentException
883 public void saveDocWithoutHandlerProcessing(
884 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
885 RepositoryInstance repoSession,
886 DocumentModel docModel,
887 boolean fSaveSession)
888 throws ClientException, DocumentException {
891 repoSession.saveDocument(docModel);
895 } catch (ClientException ce) {
897 } catch (Exception e) {
898 if (logger.isDebugEnabled()) {
899 logger.debug("Caught exception ", e);
901 throw new DocumentException(e);
907 * Save a list of documentModels to the Nuxeo repository.
909 * @param ctx service context under which this method is invoked
910 * @param docModel the document to save
911 * @param fSaveSession if TRUE, will call CoreSession.save() to save accumulated changes.
912 * @throws DocumentException
914 public void saveDocListWithoutHandlerProcessing(
915 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
916 RepositoryInstance repoSession,
917 DocumentModelList docList,
918 boolean fSaveSession)
919 throws ClientException, DocumentException {
921 repoSession = getRepositorySession();
922 DocumentModel[] docModelArray = new DocumentModel[docList.size()];
923 repoSession.saveDocuments(docList.toArray(docModelArray));
927 } catch (ClientException ce) {
929 } catch (Exception e) {
930 logger.error("Caught exception ", e);
931 throw new DocumentException(e);
936 * delete a document from the Nuxeo repository
937 * @param ctx service context under which this method is invoked
940 * @throws DocumentException
943 public void delete(ServiceContext ctx, String id, DocumentHandler handler) throws DocumentNotFoundException,
946 throw new IllegalArgumentException(
947 "delete(ctx, ix, handler): ctx is missing");
949 if (handler == null) {
950 throw new IllegalArgumentException(
951 "delete(ctx, ix, handler): handler is missing");
953 if (logger.isDebugEnabled()) {
954 logger.debug("Deleting document with CSID=" + id);
956 RepositoryInstance repoSession = null;
958 handler.prepare(Action.DELETE);
959 repoSession = getRepositorySession();
960 DocumentWrapper<DocumentModel> wrapDoc = null;
962 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
963 wrapDoc = new DocumentWrapperImpl<DocumentModel>(repoSession.getDocument(docRef));
964 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
965 handler.handle(Action.DELETE, wrapDoc);
966 repoSession.removeDocument(docRef);
967 } catch (ClientException ce) {
968 String msg = logException(ce, "Could not find document to delete with CSID=" + id);
969 throw new DocumentNotFoundException(msg, ce);
972 handler.complete(Action.DELETE, wrapDoc);
973 } catch (DocumentException de) {
975 } catch (Exception e) {
976 if (logger.isDebugEnabled()) {
977 logger.debug("Caught exception ", e);
979 throw new DocumentException(e);
981 if (repoSession != null) {
982 releaseRepositorySession(repoSession);
988 * @see org.collectionspace.services.common.storage.StorageClient#delete(org.collectionspace.services.common.context.ServiceContext, java.lang.String, org.collectionspace.services.common.document.DocumentHandler)
992 public void delete(@SuppressWarnings("rawtypes") ServiceContext ctx, String id)
993 throws DocumentNotFoundException, DocumentException {
994 throw new UnsupportedOperationException();
995 // Use the other delete instead
999 public Hashtable<String, String> retrieveWorkspaceIds(String domainName) throws Exception {
1000 return NuxeoConnectorEmbedded.getInstance().retrieveWorkspaceIds(domainName);
1004 public String createDomain(String domainName) throws Exception {
1005 RepositoryInstance repoSession = null;
1006 String domainId = null;
1009 // First create the top-level domain directory
1011 repoSession = getRepositorySession();
1012 DocumentRef parentDocRef = new PathRef("/");
1013 DocumentModel parentDoc = repoSession.getDocument(parentDocRef);
1014 DocumentModel domainDoc = repoSession.createDocumentModel(parentDoc.getPathAsString(),
1015 domainName, NUXEO_CORE_TYPE_DOMAIN);
1016 domainDoc.setPropertyValue("dc:title", domainName);
1017 domainDoc.setPropertyValue("dc:description", "A CollectionSpace domain "
1019 domainDoc = repoSession.createDocument(domainDoc);
1020 domainId = domainDoc.getId();
1023 // Next, create a "Workspaces" root directory to contain the workspace folders for the individual service documents
1025 DocumentModel workspacesRoot = repoSession.createDocumentModel(domainDoc.getPathAsString(),
1026 NuxeoUtils.Workspaces, NUXEO_CORE_TYPE_WORKSPACEROOT);
1027 workspacesRoot.setPropertyValue("dc:title", NuxeoUtils.Workspaces);
1028 workspacesRoot.setPropertyValue("dc:description", "A CollectionSpace workspaces directory for "
1029 + domainDoc.getPathAsString());
1030 workspacesRoot = repoSession.createDocument(workspacesRoot);
1031 String workspacesRootId = workspacesRoot.getId();
1034 if (logger.isDebugEnabled()) {
1035 logger.debug("Created tenant domain name=" + domainName
1036 + " id=" + domainId + " " +
1037 NuxeoUtils.Workspaces + " id=" + workspacesRootId);
1038 logger.debug("Path to Domain: "+domainDoc.getPathAsString());
1039 logger.debug("Path to Workspaces root: "+workspacesRoot.getPathAsString());
1041 } catch (Exception e) {
1042 if (logger.isDebugEnabled()) {
1043 logger.debug("Could not create tenant domain name=" + domainName + " caught exception ", e);
1047 if (repoSession != null) {
1048 releaseRepositorySession(repoSession);
1056 public String getDomainId(String domainName) throws Exception {
1057 String domainId = null;
1058 RepositoryInstance repoSession = null;
1060 if (domainName != null && !domainName.isEmpty()) {
1062 repoSession = getRepositorySession();
1063 DocumentRef docRef = new PathRef(
1065 DocumentModel domain = repoSession.getDocument(docRef);
1066 domainId = domain.getId();
1067 } catch (Exception e) {
1068 if (logger.isTraceEnabled()) {
1069 logger.trace("Caught exception ", e);
1071 //there is no way to identify if document does not exist due to
1072 //lack of typed exception for getDocument method
1075 if (repoSession != null) {
1076 releaseRepositorySession(repoSession);
1085 * Returns the workspaces root directory for a given domain.
1087 private DocumentModel getWorkspacesRoot(RepositoryInstance repoSession,
1088 String domainName) throws Exception {
1089 DocumentModel result = null;
1091 String domainPath = "/" + domainName;
1092 DocumentRef parentDocRef = new PathRef(domainPath);
1093 DocumentModelList domainChildrenList = repoSession.getChildren(
1095 Iterator<DocumentModel> witer = domainChildrenList.iterator();
1096 while (witer.hasNext()) {
1097 DocumentModel childNode = witer.next();
1098 if (NuxeoUtils.Workspaces.equalsIgnoreCase(childNode.getName())) {
1100 logger.trace("Found workspaces directory at: " + result.getPathAsString());
1105 if (result == null) {
1106 throw new ClientException("Could not find workspace root directory in: "
1114 * @see org.collectionspace.services.common.repository.RepositoryClient#createWorkspace(java.lang.String, java.lang.String)
1117 public String createWorkspace(String domainName, String workspaceName) throws Exception {
1118 RepositoryInstance repoSession = null;
1119 String workspaceId = null;
1121 repoSession = getRepositorySession();
1122 DocumentModel parentDoc = getWorkspacesRoot(repoSession, domainName);
1123 DocumentModel doc = repoSession.createDocumentModel(parentDoc.getPathAsString(),
1124 workspaceName, NuxeoUtils.WORKSPACE_DOCUMENT_TYPE);
1125 doc.setPropertyValue("dc:title", workspaceName);
1126 doc.setPropertyValue("dc:description", "A CollectionSpace workspace for "
1128 doc = repoSession.createDocument(doc);
1129 workspaceId = doc.getId();
1131 if (logger.isDebugEnabled()) {
1132 logger.debug("Created workspace name=" + workspaceName
1133 + " id=" + workspaceId);
1135 } catch (Exception e) {
1136 if (logger.isDebugEnabled()) {
1137 logger.debug("createWorkspace caught exception ", e);
1141 if (repoSession != null) {
1142 releaseRepositorySession(repoSession);
1149 * @see org.collectionspace.services.common.repository.RepositoryClient#getWorkspaceId(java.lang.String, java.lang.String)
1152 public String getWorkspaceId(String tenantDomain, String workspaceName) throws Exception {
1153 String workspaceId = null;
1155 RepositoryInstance repoSession = null;
1157 repoSession = getRepositorySession();
1158 DocumentRef docRef = new PathRef(
1160 + "/" + NuxeoUtils.Workspaces
1161 + "/" + workspaceName);
1162 DocumentModel workspace = repoSession.getDocument(docRef);
1163 workspaceId = workspace.getId();
1164 } catch (DocumentException de) {
1166 } catch (Exception e) {
1167 if (logger.isDebugEnabled()) {
1168 logger.debug("Caught exception ", e);
1170 throw new DocumentException(e);
1172 if (repoSession != null) {
1173 releaseRepositorySession(repoSession);
1182 * Gets the repository session. - Package access only.
1184 * @return the repository session
1185 * @throws Exception the exception
1187 public RepositoryInstance getRepositorySession() throws Exception {
1188 // FIXME: is it possible to reuse repository session?
1189 // Authentication failures happen while trying to reuse the session
1190 Profiler profiler = new Profiler("getRepositorySession():", 2);
1193 NuxeoClientEmbedded client = NuxeoConnectorEmbedded.getInstance().getClient();
1194 RepositoryInstance repoSession = client.openRepository();
1195 if (logger.isTraceEnabled()) {
1196 logger.trace("Testing call to getRepository() repository root: " + repoSession.getRootDocument());
1204 * Release repository session. - Package access only.
1206 * @param repoSession the repo session
1208 public void releaseRepositorySession(RepositoryInstance repoSession) {
1210 NuxeoClientEmbedded client = NuxeoConnectorEmbedded.getInstance().getClient();
1212 client.releaseRepository(repoSession);
1213 } catch (Exception e) {
1214 logger.error("Could not close the repository session", e);
1215 // no need to throw this service specific exception
1220 public void doWorkflowTransition(ServiceContext ctx, String id,
1221 DocumentHandler handler, TransitionDef transitionDef)
1222 throws BadRequestException, DocumentNotFoundException,
1224 // This is a placeholder for when we change the StorageClient interface to treat workflow transitions as 1st class operations like 'get', 'create', 'update, 'delete', etc