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 org.collectionspace.services.common.repository.RepositoryClient;
22 import org.collectionspace.services.common.context.ServiceContext;
23 import org.collectionspace.services.common.repository.BadRequestException;
24 import org.collectionspace.services.common.repository.DocumentNotFoundException;
25 import org.collectionspace.services.common.repository.DocumentHandler;
26 import org.collectionspace.services.common.repository.DocumentException;
27 import org.collectionspace.services.common.repository.DocumentHandler.Action;
28 import org.nuxeo.common.utils.IdUtils;
29 import org.nuxeo.ecm.core.api.ClientException;
30 import org.nuxeo.ecm.core.api.DocumentModel;
31 import org.nuxeo.ecm.core.api.DocumentModelList;
32 import org.nuxeo.ecm.core.api.DocumentRef;
33 import org.nuxeo.ecm.core.api.IdRef;
34 import org.nuxeo.ecm.core.api.PathRef;
35 import org.nuxeo.ecm.core.api.repository.RepositoryInstance;
36 import org.nuxeo.ecm.core.client.NuxeoClient;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
41 * RepositoryJavaClient is used to perform CRUD operations on documents in Nuxeo
42 * repository using Remote Java APIs. It uses @see DocumentHandler as IOHandler
45 * $LastChangedRevision: $ $LastChangedDate: $
47 public class RepositoryJavaClient implements RepositoryClient {
49 private final Logger logger = LoggerFactory.getLogger(RepositoryJavaClient.class);
51 public RepositoryJavaClient() {
55 * create document in the Nuxeo repository
57 * @param ctx service context under which this method is invoked
59 * of the document created
61 * should be used by the caller to provide and transform the
63 * @return id in repository of the newly created document
64 * @throws DocumentException
67 public String create(ServiceContext ctx,
68 DocumentHandler handler) throws BadRequestException,
71 if(handler.getDocumentType() == null){
72 throw new IllegalArgumentException(
73 "RemoteRepositoryClient.create: docType is missing");
76 throw new IllegalArgumentException(
77 "RemoteRepositoryClient.create: handler is missing");
79 String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
80 if(nuxeoWspaceId == null){
81 throw new DocumentNotFoundException(
82 "Unable to find workspace for service " + ctx.getServiceName() +
83 " check if the workspace exists in the Nuxeo repository");
85 RepositoryInstance repoSession = null;
87 handler.prepare(Action.CREATE);
88 repoSession = getRepositorySession();
89 DocumentRef nuxeoWspace = new IdRef(nuxeoWspaceId);
90 DocumentModel wspaceDoc = repoSession.getDocument(nuxeoWspace);
91 String wspacePath = wspaceDoc.getPathAsString();
92 String id = IdUtils.generateId("New " + handler.getDocumentType());
93 // create document model
94 DocumentModel doc = repoSession.createDocumentModel(wspacePath, id,
95 handler.getDocumentType());
96 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
97 DocumentModelWrapper wrapDoc = new DocumentModelWrapper(doc);
98 handler.handle(Action.CREATE, wrapDoc);
99 // create document with documentmodel
100 doc = repoSession.createDocument(doc);
102 handler.complete(Action.CREATE, wrapDoc);
105 if(logger.isDebugEnabled()){
106 logger.debug("Caught exception ", e);
108 throw new DocumentException(e);
110 if(repoSession != null){
111 releaseRepositorySession(repoSession);
118 * get document from the Nuxeo repository
119 * @param ctx service context under which this method is invoked
121 * of the document to retrieve
123 * should be used by the caller to provide and transform the
125 * @throws DocumentException
128 public void get(ServiceContext ctx, String id, DocumentHandler handler)
129 throws DocumentNotFoundException, DocumentException {
132 throw new IllegalArgumentException(
133 "RemoteRepositoryClient.get: handler is missing");
135 RepositoryInstance repoSession = null;
138 handler.prepare(Action.GET);
139 repoSession = getRepositorySession();
140 //FIXME, there is a potential privacy violation here, one tenant could
141 //retrieve doc id of another tenant and could retrieve the document
142 //PathRef does not seem to come to rescue as expected. Needs more thoughts.
143 DocumentRef docRef = new IdRef(id);
144 DocumentModel doc = null;
146 doc = repoSession.getDocument(docRef);
147 }catch(ClientException ce){
148 String msg = "could not find document with id=" + id;
149 logger.error(msg, ce);
150 throw new DocumentNotFoundException(msg, ce);
152 //set reposession to handle the document
153 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
154 DocumentModelWrapper wrapDoc = new DocumentModelWrapper(doc);
155 handler.handle(Action.GET, wrapDoc);
156 handler.complete(Action.GET, wrapDoc);
157 }catch(IllegalArgumentException iae){
159 }catch(DocumentException de){
162 if(logger.isDebugEnabled()){
163 logger.debug("Caught exception ", e);
165 throw new DocumentException(e);
167 if(repoSession != null){
168 releaseRepositorySession(repoSession);
174 * getAll get all documents for an entity entity service from the Nuxeo
177 * @param ctx service context under which this method is invoked
179 * should be used by the caller to provide and transform the
181 * @throws DocumentException
184 public void getAll(ServiceContext ctx, DocumentHandler handler)
185 throws DocumentNotFoundException, DocumentException {
187 throw new IllegalArgumentException(
188 "RemoteRepositoryClient.getAll: handler is missing");
190 String nuxeoWspaceId = ctx.getRepositoryWorkspaceId();
191 if(nuxeoWspaceId == null){
192 throw new DocumentNotFoundException(
193 "Unable to find workspace for service " +
194 ctx.getServiceName() +
195 " check if the workspace exists in the Nuxeo repository");
197 RepositoryInstance repoSession = null;
200 handler.prepare(Action.GET_ALL);
201 repoSession = getRepositorySession();
202 DocumentRef wsDocRef = new IdRef(nuxeoWspaceId);
203 DocumentModelList docList = repoSession.getChildren(wsDocRef);
204 //set reposession to handle the document
205 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
206 DocumentModelListWrapper wrapDoc = new DocumentModelListWrapper(
208 handler.handle(Action.GET_ALL, wrapDoc);
209 handler.complete(Action.GET_ALL, wrapDoc);
210 }catch(DocumentException de){
213 if(logger.isDebugEnabled()){
214 logger.debug("Caught exception ", e);
216 throw new DocumentException(e);
218 if(repoSession != null){
219 releaseRepositorySession(repoSession);
225 * update given document in the Nuxeo repository
227 * @param ctx service context under which this method is invoked
231 * should be used by the caller to provide and transform the
233 * @throws DocumentException
236 public void update(ServiceContext ctx, String id, DocumentHandler handler)
237 throws BadRequestException, DocumentNotFoundException,
240 throw new BadRequestException(
241 "RemoteRepositoryClient.update: id is missing");
244 throw new IllegalArgumentException(
245 "RemoteRepositoryClient.update: handler is missing");
247 RepositoryInstance repoSession = null;
249 handler.prepare(Action.UPDATE);
250 repoSession = getRepositorySession();
251 //FIXME, there is a potential privacy violation here, one tenant could
252 //retrieve doc id of another tenant and could retrieve the document
253 //PathRef does not seem to come to rescue as expected. Needs more thoughts.
254 DocumentRef docRef = new IdRef(id);
255 DocumentModel doc = null;
257 doc = repoSession.getDocument(docRef);
258 }catch(ClientException ce){
259 String msg = "Could not find document to update with id=" + id;
260 logger.error(msg, ce);
261 throw new DocumentNotFoundException(msg, ce);
263 //set reposession to handle the document
264 ((DocumentModelHandler) handler).setRepositorySession(repoSession);
265 DocumentModelWrapper wrapDoc = new DocumentModelWrapper(doc);
266 handler.handle(Action.UPDATE, wrapDoc);
267 repoSession.saveDocument(doc);
269 handler.complete(Action.UPDATE, wrapDoc);
270 }catch(DocumentException de){
273 if(logger.isDebugEnabled()){
274 logger.debug("Caught exception ", e);
276 throw new DocumentException(e);
278 if(repoSession != null){
279 releaseRepositorySession(repoSession);
285 * delete a document from the Nuxeo repository
286 * @param ctx service context under which this method is invoked
289 * @throws DocumentException
292 public void delete(ServiceContext ctx, String id) throws DocumentNotFoundException,
295 if(logger.isDebugEnabled()){
296 logger.debug("deleting document with id=" + id);
298 RepositoryInstance repoSession = null;
300 repoSession = getRepositorySession();
301 //FIXME, there is a potential privacy violation here, one tenant could
302 //retrieve doc id of another tenant and could retrieve the document
303 //PathRef does not seem to come to rescue as expected. needs more thoughts.
304 DocumentRef docRef = new IdRef(id);
306 repoSession.removeDocument(docRef);
307 }catch(ClientException ce){
308 String msg = "could not find document to delete with id=" + id;
309 logger.error(msg, ce);
310 throw new DocumentNotFoundException(msg, ce);
313 }catch(DocumentException de){
316 if(logger.isDebugEnabled()){
317 logger.debug("Caught exception ", e);
319 throw new DocumentException(e);
321 if(repoSession != null){
322 releaseRepositorySession(repoSession);
328 public String createWorkspace(String tenantDomain, String workspaceName) throws Exception {
329 RepositoryInstance repoSession = null;
330 String workspaceId = null;
332 repoSession= getRepositorySession();
333 DocumentRef docRef = new PathRef(
336 DocumentModel parent = repoSession.getDocument(docRef);
337 DocumentModel doc = repoSession.createDocumentModel(parent.getPathAsString(),
338 workspaceName, "Workspace");
339 doc.setPropertyValue("dc:title", workspaceName);
340 doc.setPropertyValue("dc:description", "A CollectionSpace workspace for " +
342 doc = repoSession.createDocument(doc);
343 workspaceId = doc.getId();
345 if(logger.isDebugEnabled()){
346 logger.debug("created workspace name=" + workspaceName +
347 " id=" + workspaceId);
350 if(logger.isDebugEnabled()){
351 logger.debug("createWorkspace caught exception ", e);
355 if(repoSession != null){
356 releaseRepositorySession(repoSession);
363 public String getWorkspaceId(String tenantDomain, String workspaceName) throws Exception {
364 String workspaceId = null;
365 RepositoryInstance repoSession = null;
367 repoSession = getRepositorySession();
368 DocumentRef docRef = new PathRef(
371 "/" + workspaceName);
372 DocumentModel workspace = repoSession.getDocument(docRef);
373 workspaceId = workspace.getId();
374 }catch(DocumentException de){
377 if(logger.isDebugEnabled()){
378 logger.debug("Caught exception ", e);
380 throw new DocumentException(e);
382 if(repoSession != null){
383 releaseRepositorySession(repoSession);
389 private RepositoryInstance getRepositorySession() throws Exception {
390 // FIXME: is it possible to reuse repository session?
391 // Authentication failures happen while trying to reuse the session
392 NuxeoClient client = NuxeoConnector.getInstance().getClient();
393 RepositoryInstance repoSession = client.openRepository();
394 if(logger.isDebugEnabled()){
395 logger.debug("getRepository() repository root: " + repoSession.getRootDocument());
400 private void releaseRepositorySession(RepositoryInstance repoSession) {
402 NuxeoClient client = NuxeoConnector.getInstance().getClient();
404 client.releaseRepository(repoSession);
406 logger.error("Could not close the repository session", e);
407 // no need to throw this service specific exception