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;
21 import java.util.UUID;
23 import org.collectionspace.services.common.context.ServiceContext;
24 import org.collectionspace.services.common.repository.BadRequestException;
25 import org.collectionspace.services.common.repository.DocumentException;
26 import org.collectionspace.services.common.repository.DocumentFilter;
27 import org.collectionspace.services.common.repository.DocumentHandler;
28 import org.collectionspace.services.common.repository.DocumentNotFoundException;
29 import org.collectionspace.services.common.repository.RepositoryClient;
30 import org.collectionspace.services.common.repository.DocumentHandler.Action;
31 import org.collectionspace.services.nuxeo.util.NuxeoUtils;
32 import org.nuxeo.common.utils.IdUtils;
33 import org.nuxeo.ecm.core.api.ClientException;
34 import org.nuxeo.ecm.core.api.DocumentModel;
35 import org.nuxeo.ecm.core.api.DocumentModelList;
36 import org.nuxeo.ecm.core.api.DocumentRef;
37 import org.nuxeo.ecm.core.api.IdRef;
38 import org.nuxeo.ecm.core.api.PathRef;
39 import org.nuxeo.ecm.core.api.repository.RepositoryInstance;
40 import org.nuxeo.ecm.core.client.NuxeoClient;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
45 * RepositoryJavaClient is used to perform CRUD operations on documents in Nuxeo
46 * repository using Remote Java APIs. It uses @see DocumentHandler as IOHandler
49 * $LastChangedRevision: $ $LastChangedDate: $
51 public class RepositoryJavaClient implements RepositoryClient {
53 private final Logger logger = LoggerFactory.getLogger(RepositoryJavaClient.class);
55 public RepositoryJavaClient() {
59 * create document in the Nuxeo repository
61 * @param ctx service context under which this method is invoked
63 * of the document created
65 * should be used by the caller to provide and transform the
67 * @return id in repository of the newly created document
68 * @throws DocumentException
71 public String create(ServiceContext ctx,
72 DocumentHandler handler) throws BadRequestException,
75 if (handler.getDocumentType() == null) {
76 throw new IllegalArgumentException(
77 "RemoteRepositoryClient.create: docType is missing");
79 if (handler == null) {
80 throw new IllegalArgumentException(
81 "RemoteRepositoryClient.create: handler is missing");
83 String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
84 if (nuxeoWspaceId == null) {
85 throw new DocumentNotFoundException(
86 "Unable to find workspace for service " + ctx.getServiceName() +
87 " check if the workspace exists in the Nuxeo repository");
89 RepositoryInstance repoSession = null;
91 handler.prepare(Action.CREATE);
92 repoSession = getRepositorySession();
93 DocumentRef nuxeoWspace = new IdRef(nuxeoWspaceId);
94 DocumentModel wspaceDoc = repoSession.getDocument(nuxeoWspace);
95 String wspacePath = wspaceDoc.getPathAsString();
96 //give our own ID so PathRef could be constructed later on
97 String id = IdUtils.generateId(UUID.randomUUID().toString());
98 // create document model
99 DocumentModel doc = repoSession.createDocumentModel(wspacePath, id,
100 handler.getDocumentType());
101 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
102 DocumentModelWrapper wrapDoc = new DocumentModelWrapper(doc);
103 handler.handle(Action.CREATE, wrapDoc);
104 // create document with documentmodel
105 doc = repoSession.createDocument(doc);
107 handler.complete(Action.CREATE, wrapDoc);
109 } catch (Exception e) {
110 if (logger.isDebugEnabled()) {
111 logger.debug("Caught exception ", e);
113 throw new DocumentException(e);
115 if (repoSession != null) {
116 releaseRepositorySession(repoSession);
123 * get document from the Nuxeo repository
124 * @param ctx service context under which this method is invoked
126 * of the document to retrieve
128 * should be used by the caller to provide and transform the
130 * @throws DocumentException
133 public void get(ServiceContext ctx, String id, DocumentHandler handler)
134 throws DocumentNotFoundException, DocumentException {
136 if (handler == null) {
137 throw new IllegalArgumentException(
138 "RemoteRepositoryClient.get: handler is missing");
140 RepositoryInstance repoSession = null;
143 handler.prepare(Action.GET);
144 repoSession = getRepositorySession();
145 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
146 DocumentModel doc = null;
148 doc = repoSession.getDocument(docRef);
149 } catch (ClientException ce) {
150 String msg = "could not find document with id=" + id;
151 logger.error(msg, ce);
152 throw new DocumentNotFoundException(msg, ce);
154 //set reposession to handle the document
155 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
156 DocumentModelWrapper wrapDoc = new DocumentModelWrapper(doc);
157 handler.handle(Action.GET, wrapDoc);
158 handler.complete(Action.GET, wrapDoc);
159 } catch (IllegalArgumentException iae) {
161 } catch (DocumentException de) {
163 } catch (Exception e) {
164 if (logger.isDebugEnabled()) {
165 logger.debug("Caught exception ", e);
167 throw new DocumentException(e);
169 if (repoSession != null) {
170 releaseRepositorySession(repoSession);
176 * getAll get all documents for an entity entity service from the Nuxeo
179 * @param ctx service context under which this method is invoked
181 * should be used by the caller to provide and transform the
183 * @throws DocumentException
186 public void getAll(ServiceContext ctx, DocumentHandler handler)
187 throws DocumentNotFoundException, DocumentException {
188 if (handler == null) {
189 throw new IllegalArgumentException(
190 "RemoteRepositoryClient.getAll: handler is missing");
192 String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
193 if (nuxeoWspaceId == null) {
194 throw new DocumentNotFoundException(
195 "Unable to find workspace for service " +
196 ctx.getServiceName() +
197 " check if the workspace exists in the Nuxeo repository");
199 RepositoryInstance repoSession = null;
202 handler.prepare(Action.GET_ALL);
203 repoSession = getRepositorySession();
204 DocumentRef wsDocRef = new IdRef(nuxeoWspaceId);
205 DocumentModelList docList = repoSession.getChildren(wsDocRef);
206 //set reposession to handle the document
207 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
208 DocumentModelListWrapper wrapDoc = new DocumentModelListWrapper(
210 handler.handle(Action.GET_ALL, wrapDoc);
211 handler.complete(Action.GET_ALL, wrapDoc);
212 } catch (DocumentException de) {
214 } catch (Exception e) {
215 if (logger.isDebugEnabled()) {
216 logger.debug("Caught exception ", e);
218 throw new DocumentException(e);
220 if (repoSession != null) {
221 releaseRepositorySession(repoSession);
227 * getFiltered get all documents for an entity service from the Document repository,
228 * given filter parameters specified by the handler.
229 * @param ctx service context under which this method is invoked
230 * @param handler should be used by the caller to provide and transform the document
231 * @throws DocumentNotFoundException if workspace not found
232 * @throws DocumentException
234 public void getFiltered(ServiceContext ctx, DocumentHandler handler)
235 throws DocumentNotFoundException, DocumentException {
236 if (handler == null) {
237 throw new IllegalArgumentException(
238 "RemoteRepositoryClient.getFiltered: handler is missing");
240 DocumentFilter docFilter = handler.getDocumentFilter();
241 if (docFilter == null) {
242 throw new IllegalArgumentException(
243 "RemoteRepositoryClient.getFiltered: handler has no Filter specified");
245 String docType = ctx.getDocumentType();
246 if (docType == null) {
247 throw new DocumentNotFoundException(
248 "Unable to find DocumentType for service " + ctx.getServiceName());
250 String domain = ctx.getRepositoryDomainName();
251 if (domain == null) {
252 throw new DocumentNotFoundException(
253 "Unable to find Domain for service " + ctx.getServiceName());
255 RepositoryInstance repoSession = null;
257 handler.prepare(Action.GET_ALL);
258 repoSession = getRepositorySession();
259 StringBuilder query = new StringBuilder("SELECT * FROM ");
260 query.append(docType);
261 String where = docFilter.getWhereClause();
262 // TODO This is a slow method for tenant-filter
263 // We should make this a property that is indexed.
264 query.append(" WHERE ecm:path STARTSWITH '/"+domain+"'");
265 if((null!=where)&&(where.length()>0))
266 query.append(" AND "+where);
267 DocumentModelList docList = null;
268 if((docFilter.getOffset()>0)||(docFilter.getPageSize()>0)) {
269 docList = repoSession.query(query.toString(), null,
270 docFilter.getPageSize(), docFilter.getOffset(), false);
272 docList = repoSession.query(query.toString());
274 //set repoSession to handle the document
275 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
276 DocumentModelListWrapper wrapDoc = new DocumentModelListWrapper(
278 handler.handle(Action.GET_ALL, wrapDoc);
279 handler.complete(Action.GET_ALL, wrapDoc);
280 } catch (DocumentException de) {
282 } catch (Exception e) {
283 if (logger.isDebugEnabled()) {
284 logger.debug("Caught exception ", e);
286 throw new DocumentException(e);
288 if (repoSession != null) {
289 releaseRepositorySession(repoSession);
297 * update given document in the Nuxeo repository
299 * @param ctx service context under which this method is invoked
303 * should be used by the caller to provide and transform the
305 * @throws DocumentException
308 public void update(ServiceContext ctx, String id, DocumentHandler handler)
309 throws BadRequestException, DocumentNotFoundException,
312 throw new BadRequestException(
313 "RemoteRepositoryClient.update: id is missing");
315 if (handler == null) {
316 throw new IllegalArgumentException(
317 "RemoteRepositoryClient.update: handler is missing");
319 RepositoryInstance repoSession = null;
321 handler.prepare(Action.UPDATE);
322 repoSession = getRepositorySession();
323 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
324 DocumentModel doc = null;
326 doc = repoSession.getDocument(docRef);
327 } catch (ClientException ce) {
328 String msg = "Could not find document to update with id=" + id;
329 logger.error(msg, ce);
330 throw new DocumentNotFoundException(msg, ce);
332 //set reposession to handle the document
333 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
334 DocumentModelWrapper wrapDoc = new DocumentModelWrapper(doc);
335 handler.handle(Action.UPDATE, wrapDoc);
336 repoSession.saveDocument(doc);
338 handler.complete(Action.UPDATE, wrapDoc);
339 } catch (DocumentException de) {
341 } catch (Exception e) {
342 if (logger.isDebugEnabled()) {
343 logger.debug("Caught exception ", e);
345 throw new DocumentException(e);
347 if (repoSession != null) {
348 releaseRepositorySession(repoSession);
354 * delete a document from the Nuxeo repository
355 * @param ctx service context under which this method is invoked
358 * @throws DocumentException
361 public void delete(ServiceContext ctx, String id) throws DocumentNotFoundException,
364 if (logger.isDebugEnabled()) {
365 logger.debug("deleting document with id=" + id);
367 RepositoryInstance repoSession = null;
369 repoSession = getRepositorySession();
370 DocumentRef docRef = NuxeoUtils.createPathRef(ctx, id);
372 repoSession.removeDocument(docRef);
373 } catch (ClientException ce) {
374 String msg = "could not find document to delete with id=" + id;
375 logger.error(msg, ce);
376 throw new DocumentNotFoundException(msg, ce);
379 } catch (DocumentException de) {
381 } catch (Exception e) {
382 if (logger.isDebugEnabled()) {
383 logger.debug("Caught exception ", e);
385 throw new DocumentException(e);
387 if (repoSession != null) {
388 releaseRepositorySession(repoSession);
394 public String createWorkspace(String tenantDomain, String workspaceName) throws Exception {
395 RepositoryInstance repoSession = null;
396 String workspaceId = null;
398 repoSession= getRepositorySession();
399 DocumentRef docRef = new PathRef(
402 DocumentModel parent = repoSession.getDocument(docRef);
403 DocumentModel doc = repoSession.createDocumentModel(parent.getPathAsString(),
404 workspaceName, "Workspace");
405 doc.setPropertyValue("dc:title", workspaceName);
406 doc.setPropertyValue("dc:description", "A CollectionSpace workspace for " +
408 doc = repoSession.createDocument(doc);
409 workspaceId = doc.getId();
411 if(logger.isDebugEnabled()){
412 logger.debug("created workspace name=" + workspaceName +
413 " id=" + workspaceId);
416 if(logger.isDebugEnabled()){
417 logger.debug("createWorkspace caught exception ", e);
421 if(repoSession != null){
422 releaseRepositorySession(repoSession);
429 public String getWorkspaceId(String tenantDomain, String workspaceName) throws Exception {
430 String workspaceId = null;
431 RepositoryInstance repoSession = null;
433 repoSession = getRepositorySession();
434 DocumentRef docRef = new PathRef(
437 "/" + workspaceName);
438 DocumentModel workspace = repoSession.getDocument(docRef);
439 workspaceId = workspace.getId();
440 }catch(DocumentException de){
443 if(logger.isDebugEnabled()){
444 logger.debug("Caught exception ", e);
446 throw new DocumentException(e);
448 if(repoSession != null){
449 releaseRepositorySession(repoSession);
455 private RepositoryInstance getRepositorySession() throws Exception {
456 // FIXME: is it possible to reuse repository session?
457 // Authentication failures happen while trying to reuse the session
458 NuxeoClient client = NuxeoConnector.getInstance().getClient();
459 RepositoryInstance repoSession = client.openRepository();
460 if (logger.isDebugEnabled()) {
461 logger.debug("getRepository() repository root: " + repoSession.getRootDocument());
466 private void releaseRepositorySession(RepositoryInstance repoSession) {
468 NuxeoClient client = NuxeoConnector.getInstance().getClient();
470 client.releaseRepository(repoSession);
471 } catch (Exception e) {
472 logger.error("Could not close the repository session", e);
473 // no need to throw this service specific exception