2 * This document is a part of the source code and related artifacts
3 * for CollectionSpace, an open source collections management system
4 * for museums and related institutions:
6 * http://www.collectionspace.org
7 * http://wiki.collectionspace.org
9 * Copyright 2009 University of California at Berkeley
11 * Licensed under the Educational Community License (ECL), Version 2.0.
12 * You may not use this file except in compliance with this License.
14 * You may obtain a copy of the ECL 2.0 License at
16 * https://source.collectionspace.org/collection-space/LICENSE.txt
18 package org.collectionspace.services.nuxeo.client.java;
20 import java.util.Hashtable;
21 import java.util.List;
23 import java.util.UUID;
24 import java.util.regex.Matcher;
25 import java.util.regex.Pattern;
26 import java.util.regex.PatternSyntaxException;
28 import javax.ws.rs.WebApplicationException;
29 import javax.ws.rs.core.MultivaluedMap;
31 import org.collectionspace.services.client.IQueryManager;
32 import org.collectionspace.services.client.PoxPayloadIn;
33 import org.collectionspace.services.client.PoxPayloadOut;
34 import org.collectionspace.services.client.workflow.WorkflowClient;
35 import org.collectionspace.services.common.context.ServiceContext;
36 import org.collectionspace.services.common.datetime.GregorianCalendarDateTimeUtils;
37 import org.collectionspace.services.common.query.QueryContext;
38 import org.collectionspace.services.common.repository.RepositoryClient;
39 import org.collectionspace.services.common.workflow.service.nuxeo.WorkflowDocumentModelHandler;
40 import org.collectionspace.services.common.profile.Profiler;
41 import org.collectionspace.services.nuxeo.util.NuxeoUtils;
43 import org.collectionspace.services.common.document.BadRequestException;
44 import org.collectionspace.services.common.document.DocumentException;
45 import org.collectionspace.services.common.document.DocumentFilter;
46 import org.collectionspace.services.common.document.DocumentHandler;
47 import org.collectionspace.services.common.document.DocumentNotFoundException;
48 import org.collectionspace.services.common.document.DocumentHandler.Action;
49 import org.collectionspace.services.common.document.DocumentWrapper;
50 import org.collectionspace.services.common.document.DocumentWrapperImpl;
52 import org.nuxeo.common.utils.IdUtils;
53 import org.nuxeo.ecm.core.api.ClientException;
54 import org.nuxeo.ecm.core.api.DocumentModel;
55 import org.nuxeo.ecm.core.api.DocumentModelList;
56 import org.nuxeo.ecm.core.api.impl.DocumentModelListImpl;
57 import org.nuxeo.ecm.core.api.DocumentRef;
58 import org.nuxeo.ecm.core.api.IdRef;
59 import org.nuxeo.ecm.core.api.PathRef;
60 import org.nuxeo.ecm.core.api.repository.RepositoryInstance;
61 //import org.nuxeo.ecm.core.client.NuxeoClient;
62 import org.nuxeo.ecm.core.schema.SchemaManager;
63 import org.nuxeo.runtime.api.Framework;
65 import org.slf4j.Logger;
66 import org.slf4j.LoggerFactory;
69 * RepositoryJavaClient is used to perform CRUD operations on documents in Nuxeo
70 * repository using Remote Java APIs. It uses @see DocumentHandler as IOHandler
73 * $LastChangedRevision: $ $LastChangedDate: $
75 public class RepositoryJavaClientImpl implements RepositoryClient<PoxPayloadIn, PoxPayloadOut> {
78 private final Logger logger = LoggerFactory.getLogger(RepositoryJavaClientImpl.class);
79 // private final Logger profilerLogger = LoggerFactory.getLogger("remperf");
80 // private String foo = Profiler.createLogger();
82 public static final String NUXEO_CORE_TYPE_DOMAIN = "Domain";
83 public static final String NUXEO_CORE_TYPE_WORKSPACEROOT = "WorkspaceRoot";
86 * Instantiates a new repository java client impl.
88 public RepositoryJavaClientImpl() {
93 public void assertWorkflowState(ServiceContext ctx,
94 DocumentModel docModel) throws DocumentNotFoundException, ClientException {
95 MultivaluedMap<String, String> queryParams = ctx.getQueryParams();
96 if (queryParams != null) {
98 // Look for the workflow "delete" query param and see if we need to assert that the
99 // docModel is in a non-deleted workflow state.
101 String currentState = docModel.getCurrentLifeCycleState();
102 String includeDeletedStr = queryParams.getFirst(WorkflowClient.WORKFLOW_QUERY_NONDELETED);
103 boolean includeDeleted = includeDeletedStr == null ? true : Boolean.parseBoolean(includeDeletedStr);
104 if (includeDeleted == false) {
106 // We don't wanted soft-deleted object, so throw an exception if this one is soft-deleted.
108 if (currentState.equalsIgnoreCase(WorkflowClient.WORKFLOWSTATE_DELETED)) {
109 String msg = "GET assertion that docModel not be in 'deleted' workflow state failed.";
111 throw new DocumentNotFoundException(msg);
118 * create document in the Nuxeo repository
120 * @param ctx service context under which this method is invoked
122 * should be used by the caller to provide and transform the
124 * @return id in repository of the newly created document
125 * @throws DocumentException
128 public String create(ServiceContext ctx,
129 DocumentHandler handler) throws BadRequestException,
132 String docType = NuxeoUtils.getTenantQualifiedDocType(ctx); //ctx.getDocumentType();
133 if (docType == null) {
134 throw new IllegalArgumentException(
135 "RepositoryJavaClient.create: docType is missing");
138 if (handler == null) {
139 throw new IllegalArgumentException(
140 "RepositoryJavaClient.create: handler is missing");
142 String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
143 if (nuxeoWspaceId == null) {
144 throw new DocumentNotFoundException(
145 "Unable to find workspace for service " + ctx.getServiceName()
146 + " check if the workspace exists in the Nuxeo repository");
148 RepositoryInstance repoSession = null;
150 handler.prepare(Action.CREATE);
151 repoSession = getRepositorySession();
152 DocumentRef nuxeoWspace = new IdRef(nuxeoWspaceId);
153 DocumentModel wspaceDoc = repoSession.getDocument(nuxeoWspace);
154 String wspacePath = wspaceDoc.getPathAsString();
155 //give our own ID so PathRef could be constructed later on
156 String id = IdUtils.generateId(UUID.randomUUID().toString());
157 // create document model
158 DocumentModel doc = repoSession.createDocumentModel(wspacePath, id, docType);
159 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
160 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
161 handler.handle(Action.CREATE, wrapDoc);
162 // create document with documentmodel
163 doc = repoSession.createDocument(doc);
165 // TODO for sub-docs need to call into the handler to let it deal with subitems. Pass in the id,
166 // and assume the handler has the state it needs (doc fragments).
167 handler.complete(Action.CREATE, wrapDoc);
169 } catch (BadRequestException bre) {
171 } catch (Exception e) {
172 if (logger.isDebugEnabled()) {
173 logger.debug("Caught exception ", e);
175 throw new DocumentException(e);
177 if (repoSession != null) {
178 releaseRepositorySession(repoSession);
185 * get document from the Nuxeo repository
186 * @param ctx service context under which this method is invoked
188 * of the document to retrieve
190 * should be used by the caller to provide and transform the
192 * @throws DocumentException
195 public void get(ServiceContext ctx, String id, DocumentHandler handler)
196 throws DocumentNotFoundException, DocumentException {
198 if (handler == null) {
199 throw new IllegalArgumentException(
200 "RepositoryJavaClient.get: handler is missing");
202 RepositoryInstance repoSession = null;
205 handler.prepare(Action.GET);
206 repoSession = getRepositorySession();
207 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
208 DocumentModel docModel = null;
210 docModel = repoSession.getDocument(docRef);
211 assertWorkflowState(ctx, docModel);
212 } catch (ClientException ce) {
213 String msg = "Could not find document with id=" + id;
214 logger.error(msg, ce);
215 throw new DocumentNotFoundException(msg, ce);
217 //set reposession to handle the document
218 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
219 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(docModel);
220 handler.handle(Action.GET, wrapDoc);
221 handler.complete(Action.GET, wrapDoc);
222 } catch (IllegalArgumentException iae) {
224 } catch (DocumentException de) {
226 } catch (Exception e) {
227 if (logger.isDebugEnabled()) {
228 logger.debug("Caught exception ", e);
230 throw new DocumentException(e);
232 if (repoSession != null) {
233 releaseRepositorySession(repoSession);
239 * get document from the Nuxeo repository, using the docFilter params.
240 * @param ctx service context under which this method is invoked
242 * should be used by the caller to provide and transform the
243 * document. Handler must have a docFilter set to return a single item.
244 * @throws DocumentException
247 public void get(ServiceContext ctx, DocumentHandler handler)
248 throws DocumentNotFoundException, DocumentException {
249 QueryContext queryContext = new QueryContext(ctx, handler);
250 RepositoryInstance repoSession = null;
253 handler.prepare(Action.GET);
254 repoSession = getRepositorySession();
256 DocumentModelList docList = null;
257 // force limit to 1, and ignore totalSize
258 String query = NuxeoUtils.buildNXQLQuery(ctx, queryContext);
259 docList = repoSession.query(query, null, 1, 0, false);
260 if (docList.size() != 1) {
261 throw new DocumentNotFoundException("No document found matching filter params.");
263 DocumentModel doc = docList.get(0);
265 if (logger.isDebugEnabled()) {
266 logger.debug("Executed NXQL query: " + query);
269 //set reposession to handle the document
270 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
271 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
272 handler.handle(Action.GET, wrapDoc);
273 handler.complete(Action.GET, wrapDoc);
274 } catch (IllegalArgumentException iae) {
276 } catch (DocumentException de) {
278 } catch (Exception e) {
279 if (logger.isDebugEnabled()) {
280 logger.debug("Caught exception ", e);
282 throw new DocumentException(e);
284 if (repoSession != null) {
285 releaseRepositorySession(repoSession);
291 * Get wrapped documentModel from the Nuxeo repository. The search is restricted to the workspace
292 * of the current context.
294 * @param ctx service context under which this method is invoked
296 * of the document to retrieve
297 * @throws DocumentException
300 public DocumentWrapper<DocumentModel> getDoc(
301 ServiceContext ctx, String csid)
302 throws DocumentNotFoundException, DocumentException {
303 RepositoryInstance repoSession = null;
304 DocumentWrapper<DocumentModel> wrapDoc = null;
307 repoSession = getRepositorySession();
308 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, csid);
309 DocumentModel doc = null;
311 doc = repoSession.getDocument(docRef);
312 } catch (ClientException ce) {
313 String msg = "could not find document with id=" + csid;
314 logger.error(msg, ce);
315 throw new DocumentNotFoundException(msg, ce);
317 wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
318 } catch (IllegalArgumentException iae) {
320 } catch (DocumentException de) {
322 } catch (Exception e) {
323 if (logger.isDebugEnabled()) {
324 logger.debug("Caught exception ", e);
326 throw new DocumentException(e);
328 if (repoSession != null) {
329 releaseRepositorySession(repoSession);
336 * find wrapped documentModel from the Nuxeo repository
337 * @param ctx service context under which this method is invoked
338 * @param whereClause where NXQL where clause to get the document
339 * @throws DocumentException
342 public DocumentWrapper<DocumentModel> findDoc(
343 ServiceContext ctx, String whereClause)
344 throws DocumentNotFoundException, DocumentException {
345 RepositoryInstance repoSession = null;
346 DocumentWrapper<DocumentModel> wrapDoc = null;
349 QueryContext queryContext = new QueryContext(ctx, whereClause);
350 repoSession = getRepositorySession();
351 DocumentModelList docList = null;
352 // force limit to 1, and ignore totalSize
353 String query = NuxeoUtils.buildNXQLQuery(ctx, queryContext);
354 docList = repoSession.query(query,
359 if (docList.size() != 1) {
360 if (logger.isDebugEnabled()) {
361 logger.debug("findDoc: Query found: " + docList.size() + " items.");
362 logger.debug(" Query: " + query);
364 throw new DocumentNotFoundException("No document found matching filter params.");
366 DocumentModel doc = docList.get(0);
367 wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
368 } catch (IllegalArgumentException iae) {
370 } catch (DocumentException de) {
372 } catch (Exception e) {
373 if (logger.isDebugEnabled()) {
374 logger.debug("Caught exception ", e);
376 throw new DocumentException(e);
378 if (repoSession != null) {
379 releaseRepositorySession(repoSession);
386 * find doc and return CSID from the Nuxeo repository
387 * @param ctx service context under which this method is invoked
388 * @param whereClause where NXQL where clause to get the document
389 * @throws DocumentException
392 public String findDocCSID(
393 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx, String whereClause)
394 throws DocumentNotFoundException, DocumentException {
397 DocumentWrapper<DocumentModel> wrapDoc = findDoc(ctx, whereClause);
398 DocumentModel docModel = wrapDoc.getWrappedObject();
399 csid = NuxeoUtils.getCsid(docModel);//NuxeoUtils.extractId(docModel.getPathAsString());
400 } catch (DocumentNotFoundException dnfe) {
402 } catch (IllegalArgumentException iae) {
404 } catch (DocumentException de) {
406 } catch (Exception e) {
407 if (logger.isDebugEnabled()) {
408 logger.debug("Caught exception ", e);
410 throw new DocumentException(e);
416 * Find a list of documentModels from the Nuxeo repository
417 * @param docTypes a list of DocType names to match
418 * @param whereClause where the clause to qualify on
422 public DocumentWrapper<DocumentModelList> findDocs(
423 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
424 List<String> docTypes,
426 int pageSize, int pageNum, boolean computeTotal)
427 throws DocumentNotFoundException, DocumentException {
428 RepositoryInstance repoSession = null;
429 DocumentWrapper<DocumentModelList> wrapDoc = null;
432 if (docTypes == null || docTypes.size() < 1) {
433 throw new DocumentNotFoundException(
434 "findDocs must specify at least one DocumentType.");
436 repoSession = getRepositorySession();
437 DocumentModelList docList = null;
438 // force limit to 1, and ignore totalSize
439 QueryContext queryContext = new QueryContext(ctx, whereClause);
440 String query = NuxeoUtils.buildNXQLQuery(docTypes, queryContext);
441 docList = repoSession.query(query, null, pageSize, pageNum, computeTotal);
442 wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
443 } catch (IllegalArgumentException iae) {
445 } catch (Exception e) {
446 if (logger.isDebugEnabled()) {
447 logger.debug("Caught exception ", e);
449 throw new DocumentException(e);
451 if (repoSession != null) {
452 releaseRepositorySession(repoSession);
459 * @see org.collectionspace.services.common.storage.StorageClient#get(org.collectionspace.services.common.context.ServiceContext, java.util.List, org.collectionspace.services.common.document.DocumentHandler)
462 public void get(ServiceContext ctx, List<String> csidList, DocumentHandler handler)
463 throws DocumentNotFoundException, DocumentException {
464 if (handler == null) {
465 throw new IllegalArgumentException(
466 "RepositoryJavaClient.getAll: handler is missing");
469 RepositoryInstance repoSession = null;
472 handler.prepare(Action.GET_ALL);
473 repoSession = getRepositorySession();
474 DocumentModelList docModelList = new DocumentModelListImpl();
475 //FIXME: Should be using NuxeoUtils.createPathRef for security reasons
476 for (String csid : csidList) {
477 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, csid);
478 DocumentModel docModel = repoSession.getDocument(docRef);
479 docModelList.add(docModel);
482 //set reposession to handle the document
483 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
484 DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docModelList);
485 handler.handle(Action.GET_ALL, wrapDoc);
486 handler.complete(Action.GET_ALL, wrapDoc);
487 } catch (DocumentException de) {
489 } catch (Exception e) {
490 if (logger.isDebugEnabled()) {
491 logger.debug("Caught exception ", e);
493 throw new DocumentException(e);
495 if (repoSession != null) {
496 releaseRepositorySession(repoSession);
502 * getAll get all documents for an entity entity service from the Nuxeo
505 * @param ctx service context under which this method is invoked
507 * should be used by the caller to provide and transform the
509 * @throws DocumentException
512 public void getAll(ServiceContext ctx, DocumentHandler handler)
513 throws DocumentNotFoundException, DocumentException {
514 if (handler == null) {
515 throw new IllegalArgumentException(
516 "RepositoryJavaClient.getAll: handler is missing");
518 String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
519 if (nuxeoWspaceId == null) {
520 throw new DocumentNotFoundException(
521 "Unable to find workspace for service "
522 + ctx.getServiceName()
523 + " check if the workspace exists in the Nuxeo repository");
525 RepositoryInstance repoSession = null;
528 handler.prepare(Action.GET_ALL);
529 repoSession = getRepositorySession();
530 DocumentRef wsDocRef = new IdRef(nuxeoWspaceId);
531 DocumentModelList docList = repoSession.getChildren(wsDocRef);
532 //set reposession to handle the document
533 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
534 DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
535 handler.handle(Action.GET_ALL, wrapDoc);
536 handler.complete(Action.GET_ALL, wrapDoc);
537 } catch (DocumentException de) {
539 } catch (Exception e) {
540 if (logger.isDebugEnabled()) {
541 logger.debug("Caught exception ", e);
543 throw new DocumentException(e);
545 if (repoSession != null) {
546 releaseRepositorySession(repoSession);
551 private boolean isClauseEmpty(String theString) {
552 boolean result = true;
553 if (theString != null && !theString.isEmpty()) {
560 * A method to find a CollectionSpace document (of any type) given just a service context and
561 * its CSID. A search across *all* service workspaces (within a given tenant context) is performed to find
564 * This query searches Nuxeo's Hierarchy table where our CSIDs are stored in the "name" column.
567 public DocumentWrapper<DocumentModel> getDocFromCsid(ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
570 DocumentWrapper<DocumentModel> result = null;
571 RepositoryInstance repoSession = getRepositorySession();
573 result = new DocumentWrapperImpl(NuxeoUtils.getDocFromCsid(repoSession, ctx, csid));
575 if (repoSession != null) {
576 releaseRepositorySession(repoSession);
583 * find doc and return CSID from the Nuxeo repository
584 * @param ctx service context under which this method is invoked
585 * @param whereClause where NXQL where clause to get the document
586 * @throws DocumentException
589 public String getDocURI(DocumentWrapper<DocumentModel> wrappedDoc) throws ClientException {
590 DocumentModel docModel = wrappedDoc.getWrappedObject();
591 String uri = (String)docModel.getProperty(DocumentModelHandler.COLLECTIONSPACE_CORE_SCHEMA,
592 DocumentModelHandler.COLLECTIONSPACE_CORE_URI);
598 * getFiltered get all documents for an entity service from the Document repository,
599 * given filter parameters specified by the handler.
600 * @param ctx service context under which this method is invoked
601 * @param handler should be used by the caller to provide and transform the document
602 * @throws DocumentNotFoundException if workspace not found
603 * @throws DocumentException
606 public void getFiltered(ServiceContext ctx, DocumentHandler handler)
607 throws DocumentNotFoundException, DocumentException {
609 DocumentFilter filter = handler.getDocumentFilter();
610 String oldOrderBy = filter.getOrderByClause();
611 if (isClauseEmpty(oldOrderBy) == true){
612 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?)
614 QueryContext queryContext = new QueryContext(ctx, handler);
615 RepositoryInstance repoSession = null;
617 handler.prepare(Action.GET_ALL);
618 repoSession = getRepositorySession();
619 DocumentModelList docList = null;
620 String query = NuxeoUtils.buildNXQLQuery(ctx, queryContext);
622 if (logger.isDebugEnabled()) {
623 logger.debug("Executing NXQL query: " + query.toString());
626 // If we have limit and/or offset, then pass true to get totalSize
627 // in returned DocumentModelList.
628 Profiler profiler = new Profiler(this, 2);
629 profiler.log("Executing NXQL query: " + query.toString());
631 if ((queryContext.getDocFilter().getOffset() > 0) || (queryContext.getDocFilter().getPageSize() > 0)) {
632 docList = repoSession.query(query, null,
633 queryContext.getDocFilter().getPageSize(), queryContext.getDocFilter().getOffset(), true);
635 docList = repoSession.query(query);
639 //set repoSession to handle the document
640 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
641 DocumentWrapper<DocumentModelList> wrapDoc = new DocumentWrapperImpl<DocumentModelList>(docList);
642 handler.handle(Action.GET_ALL, wrapDoc);
643 handler.complete(Action.GET_ALL, wrapDoc);
644 } catch (DocumentException de) {
646 } catch (Exception e) {
647 if (logger.isDebugEnabled()) {
648 logger.debug("Caught exception ", e);
650 throw new DocumentException(e);
652 if (repoSession != null) {
653 releaseRepositorySession(repoSession);
659 * update given document in the Nuxeo repository
661 * @param ctx service context under which this method is invoked
665 * should be used by the caller to provide and transform the
667 * @throws DocumentException
670 public void update(ServiceContext ctx, String id, DocumentHandler handler)
671 throws BadRequestException, DocumentNotFoundException,
673 if (handler == null) {
674 throw new IllegalArgumentException(
675 "RepositoryJavaClient.update: handler is missing");
677 RepositoryInstance repoSession = null;
679 handler.prepare(Action.UPDATE);
680 repoSession = getRepositorySession();
681 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
682 DocumentModel doc = null;
684 doc = repoSession.getDocument(docRef);
685 } catch (ClientException ce) {
686 String msg = "Could not find document to update with id=" + id;
687 logger.error(msg, ce);
688 throw new DocumentNotFoundException(msg, ce);
690 //set reposession to handle the document
691 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
692 DocumentWrapper<DocumentModel> wrapDoc = new DocumentWrapperImpl<DocumentModel>(doc);
693 handler.handle(Action.UPDATE, wrapDoc);
694 repoSession.saveDocument(doc);
696 handler.complete(Action.UPDATE, wrapDoc);
697 } catch (BadRequestException bre) {
699 } catch (DocumentException de) {
701 } catch (WebApplicationException wae){
703 } catch (Exception e) {
704 if (logger.isDebugEnabled()) {
705 logger.debug("Caught exception ", e);
707 throw new DocumentException(e);
709 if (repoSession != null) {
710 releaseRepositorySession(repoSession);
716 * Save a documentModel to the Nuxeo repository, using the current session,
717 * bypassing the normal document handler processing (validation, etc.)
718 * NOTE: This should be called only in specific circumstances, e.g., to
719 * update known cached values like refNames. DO NOT USE this for any normal
720 * document processing.
721 * NOTE: Does not release session, as it should be called in a wider session context.
722 * Caller is responsible for releasing the session.
724 * @param ctx service context under which this method is invoked
725 * @param docModel the document to save
726 * @param fSaveSession if TRUE, will call CoreSession.save() to save accumulated changes.
727 * @throws DocumentException
729 public void saveDocWithoutHandlerProcessing(
730 ServiceContext ctx, DocumentModel docModel, boolean fSaveSession)
731 throws ClientException, DocumentException {
732 RepositoryInstance repoSession = null;
733 DocumentWrapper<DocumentModel> wrapDoc = null;
736 repoSession = getRepositorySession();
737 repoSession.saveDocument(docModel);
740 } catch (ClientException ce) {
742 } catch (Exception e) {
743 if (logger.isDebugEnabled()) {
744 logger.debug("Caught exception ", e);
746 throw new DocumentException(e);
752 * Save a list of documentModels to the Nuxeo repository, using the current session,
753 * bypassing the normal document handler processing (validation, etc.)
754 * NOTE: This should be called only in specific circumstances, e.g., to
755 * update known cached values like refNames. DO NOT USE this for any normal
756 * document processing.
757 * NOTE: Does not release session, as it should be called in a wider session context.
758 * Caller is responsible for releasing the session.
760 * @param ctx service context under which this method is invoked
761 * @param docModel the document to save
762 * @param fSaveSession if TRUE, will call CoreSession.save() to save accumulated changes.
763 * @throws DocumentException
765 public void saveDocListWithoutHandlerProcessing(
766 ServiceContext ctx, DocumentModelList docList, boolean fSaveSession)
767 throws ClientException, DocumentException {
768 RepositoryInstance repoSession = null;
769 DocumentWrapper<DocumentModel> wrapDoc = null;
772 repoSession = getRepositorySession();
773 DocumentModel[] docModelArray = new DocumentModel[docList.size()];
774 repoSession.saveDocuments(docList.toArray(docModelArray));
777 } catch (ClientException ce) {
779 } catch (Exception e) {
780 if (logger.isDebugEnabled()) {
781 logger.debug("Caught exception ", e);
783 throw new DocumentException(e);
790 * delete a document from the Nuxeo repository
791 * @param ctx service context under which this method is invoked
794 * @throws DocumentException
797 public void delete(ServiceContext ctx, String id) throws DocumentNotFoundException,
800 if (logger.isDebugEnabled()) {
801 logger.debug("deleting document with id=" + id);
803 RepositoryInstance repoSession = null;
805 repoSession = getRepositorySession();
806 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
808 repoSession.removeDocument(docRef);
809 } catch (ClientException ce) {
810 String msg = "could not find document to delete with id=" + id;
811 logger.error(msg, ce);
812 throw new DocumentNotFoundException(msg, ce);
815 } catch (DocumentException de) {
817 } catch (Exception e) {
818 if (logger.isDebugEnabled()) {
819 logger.debug("Caught exception ", e);
821 throw new DocumentException(e);
823 if (repoSession != null) {
824 releaseRepositorySession(repoSession);
830 * @see org.collectionspace.services.common.storage.StorageClient#delete(org.collectionspace.services.common.context.ServiceContext, java.lang.String, org.collectionspace.services.common.document.DocumentHandler)
833 public void delete(ServiceContext ctx, String id, DocumentHandler handler)
834 throws DocumentNotFoundException, DocumentException {
835 throw new UnsupportedOperationException();
839 public Hashtable<String, String> retrieveWorkspaceIds(String domainName) throws Exception {
840 return NuxeoConnectorEmbedded.getInstance().retrieveWorkspaceIds(domainName);
844 public String createDomain(String domainName) throws Exception {
845 RepositoryInstance repoSession = null;
846 String domainId = null;
849 // First create the top-level domain directory
851 repoSession = getRepositorySession();
852 DocumentRef parentDocRef = new PathRef("/");
853 DocumentModel parentDoc = repoSession.getDocument(parentDocRef);
854 DocumentModel domainDoc = repoSession.createDocumentModel(parentDoc.getPathAsString(),
855 domainName, NUXEO_CORE_TYPE_DOMAIN);
856 domainDoc.setPropertyValue("dc:title", domainName);
857 domainDoc.setPropertyValue("dc:description", "A CollectionSpace domain "
859 domainDoc = repoSession.createDocument(domainDoc);
860 domainId = domainDoc.getId();
863 // Next, create a "Workspaces" root directory to contain the workspace folders for the individual service documents
865 DocumentModel workspacesRoot = repoSession.createDocumentModel(domainDoc.getPathAsString(),
866 NuxeoUtils.Workspaces, NUXEO_CORE_TYPE_WORKSPACEROOT);
867 workspacesRoot.setPropertyValue("dc:title", NuxeoUtils.Workspaces);
868 workspacesRoot.setPropertyValue("dc:description", "A CollectionSpace workspaces directory for "
869 + domainDoc.getPathAsString());
870 workspacesRoot = repoSession.createDocument(workspacesRoot);
871 String workspacesRootId = workspacesRoot.getId();
873 if (logger.isDebugEnabled()) {
874 logger.debug("Created tenant domain name=" + domainName
875 + " id=" + domainId + " " +
876 NuxeoUtils.Workspaces + " id=" + workspacesRootId);
878 } catch (Exception e) {
879 if (logger.isDebugEnabled()) {
880 logger.debug("createTenantSpace caught exception ", e);
884 if (repoSession != null) {
885 releaseRepositorySession(repoSession);
892 public String getDomainId(String domainName) throws Exception {
893 String domainId = null;
894 RepositoryInstance repoSession = null;
896 if (domainName != null && !domainName.isEmpty()) {
898 repoSession = getRepositorySession();
899 DocumentRef docRef = new PathRef(
901 DocumentModel domain = repoSession.getDocument(docRef);
902 domainId = domain.getId();
903 } catch (Exception e) {
904 if (logger.isTraceEnabled()) {
905 logger.trace("Caught exception ", e);
907 //there is no way to identify if document does not exist due to
908 //lack of typed exception for getDocument method
911 if (repoSession != null) {
912 releaseRepositorySession(repoSession);
921 * @see org.collectionspace.services.common.repository.RepositoryClient#createWorkspace(java.lang.String, java.lang.String)
924 public String createWorkspace(String domainName, String workspaceName) throws Exception {
925 RepositoryInstance repoSession = null;
926 String workspaceId = null;
928 repoSession = getRepositorySession();
929 DocumentRef parentDocRef = new PathRef(
931 + "/" + NuxeoUtils.Workspaces);
932 DocumentModel parentDoc = repoSession.getDocument(parentDocRef);
933 DocumentModel doc = repoSession.createDocumentModel(parentDoc.getPathAsString(),
934 workspaceName, "Workspace");
935 doc.setPropertyValue("dc:title", workspaceName);
936 doc.setPropertyValue("dc:description", "A CollectionSpace workspace for "
938 doc = repoSession.createDocument(doc);
939 workspaceId = doc.getId();
941 if (logger.isDebugEnabled()) {
942 logger.debug("created workspace name=" + workspaceName
943 + " id=" + workspaceId);
945 } catch (Exception e) {
946 if (logger.isDebugEnabled()) {
947 logger.debug("createWorkspace caught exception ", e);
951 if (repoSession != null) {
952 releaseRepositorySession(repoSession);
959 * @see org.collectionspace.services.common.repository.RepositoryClient#getWorkspaceId(java.lang.String, java.lang.String)
962 public String getWorkspaceId(String tenantDomain, String workspaceName) throws Exception {
963 String workspaceId = null;
964 RepositoryInstance repoSession = null;
966 repoSession = getRepositorySession();
967 DocumentRef docRef = new PathRef(
969 + "/" + NuxeoUtils.Workspaces
970 + "/" + workspaceName);
971 DocumentModel workspace = repoSession.getDocument(docRef);
972 workspaceId = workspace.getId();
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);
990 * Gets the repository session.
992 * @return the repository session
993 * @throws Exception the exception
995 private RepositoryInstance getRepositorySession() throws Exception {
996 // FIXME: is it possible to reuse repository session?
997 // Authentication failures happen while trying to reuse the session
998 Profiler profiler = new Profiler("getRepositorySession():", 2);
1000 NuxeoClientEmbedded client = NuxeoConnectorEmbedded.getInstance().getClient();
1001 RepositoryInstance repoSession = client.openRepository();
1002 if (logger.isDebugEnabled()) {
1003 logger.debug("getRepository() repository root: " + repoSession.getRootDocument());
1010 * Release repository session.
1012 * @param repoSession the repo session
1014 private void releaseRepositorySession(RepositoryInstance repoSession) {
1016 NuxeoClientEmbedded client = NuxeoConnectorEmbedded.getInstance().getClient();
1018 client.releaseRepository(repoSession);
1019 } catch (Exception e) {
1020 logger.error("Could not close the repository session", e);
1021 // no need to throw this service specific exception