]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
9a762fd1d92a6b5f6fe0471c3f85657f19ca3a83
[tmp/jakarta-migration.git] /
1 /**
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:
5
6  *  http://www.collectionspace.org
7  *  http://wiki.collectionspace.org
8
9  *  Copyright 2009 University of California at Berkeley
10
11  *  Licensed under the Educational Community License (ECL), Version 2.0.
12  *  You may not use this file except in compliance with this License.
13
14  *  You may obtain a copy of the ECL 2.0 License at
15
16  *  https://source.collectionspace.org/collection-space/LICENSE.txt
17
18  *  Unless required by applicable law or agreed to in writing, software
19  *  distributed under the License is distributed on an "AS IS" BASIS,
20  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  *  See the License for the specific language governing permissions and
22  *  limitations under the License.
23  */
24 package org.collectionspace.services.nuxeo.client.rest;
25
26 import java.io.ByteArrayInputStream;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.io.OutputStream;
30 import java.util.ArrayList;
31 import java.util.HashMap;
32 import java.util.Iterator;
33 import org.collectionspace.services.common.repository.DocumentException;
34 import org.collectionspace.services.common.repository.DocumentHandler;
35 import org.collectionspace.services.common.repository.RepositoryClient;
36
37 import org.restlet.data.Request;
38
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41
42 import java.util.List;
43 import java.util.Map;
44
45 import org.collectionspace.services.common.ServiceConfig;
46 import org.collectionspace.services.common.ServiceConfig.NuxeoClientConfig;
47 import org.collectionspace.services.common.ServiceMain;
48 import org.collectionspace.services.common.repository.BadRequestException;
49 import org.collectionspace.services.common.repository.DocumentNotFoundException;
50 import org.collectionspace.services.common.repository.DocumentHandler.Action;
51 import org.dom4j.Document;
52 import org.dom4j.Element;
53 import org.dom4j.io.SAXReader;
54 import org.dom4j.tree.DefaultDocument;
55 import org.restlet.data.MediaType;
56 import org.restlet.data.Method;
57 import org.restlet.data.Response;
58 import org.restlet.data.Status;
59 import org.restlet.resource.OutputRepresentation;
60 import org.restlet.resource.Representation;
61
62 /**
63  * RepositoryRESTClient is used to perform CRUD operations on documents
64  * in Nuxeo repository using Nuxeo RESTful APIs. It uses @see DocumentHandler
65  * as IOHandler with the client.
66  *
67  * v2 NuxeoClient
68  *
69  * $LastChangedRevision: $
70  * $LastChangedDate: $
71  */
72 public class RepositoryRESTClient implements RepositoryClient {
73
74     private final Logger logger = LoggerFactory.getLogger(RepositoryRESTClient.class);
75     private NuxeoRESTClient nuxeoRestClient;
76
77     public RepositoryRESTClient() {
78     }
79
80     @Override
81     public String create(String serviceName, DocumentHandler handler) throws BadRequestException, DocumentException {
82         if(serviceName == null){
83             throw new IllegalArgumentException("RepositoryRESTClient.create: serviceName is missing");
84         }
85         if(handler.getDocumentType() == null){
86             throw new IllegalArgumentException("RepositoryRESTClient.create: docType is missing");
87         }
88         if(handler == null){
89             throw new IllegalArgumentException("RepositoryRESTClient.create: handler is missing");
90         }
91         ServiceMain smain = ServiceMain.getInstance();
92         String nuxeoWspaceId = smain.getWorkspaceId(serviceName);
93         if(nuxeoWspaceId == null){
94             throw new DocumentNotFoundException("Unable to find workspace for service " + serviceName +
95                     " check if the mapping exists in service-config.xml or " +
96                     " the the mapped workspace exists in the Nuxeo repository");
97         }
98         try{
99             RepresentationHandler repHandler = (RepresentationHandler) handler;
100             repHandler.prepare(Action.CREATE);
101             List<String> pathParams = new ArrayList<String>();
102             pathParams.add("default");
103             pathParams.add(nuxeoWspaceId);
104             pathParams.add("createDocument");
105             if(repHandler.getPathParams().size() > 0){
106                 pathParams.addAll(repHandler.getPathParams());
107             }
108             Map<String, String> queryParams = new HashMap<String, String>();
109             queryParams.put("docType", handler.getDocumentType());
110             // a default title for the Dublin Core schema
111             queryParams.put("dublincore:title", "CollectionSpace-" + handler.getDocumentType());
112             if(repHandler.getQueryParams().size() > 0){
113                 queryParams.putAll(repHandler.getQueryParams());
114             }
115
116             String completeURL = getNuxeoRestClient().buildUrl(pathParams, queryParams);
117             if(logger.isDebugEnabled()){
118                 logger.debug("create using url=" + completeURL);
119             }
120             Request request = buildRequest(Method.POST, completeURL);
121
122             //write out create stream, this is not needed as queryParams
123             //contain the document
124             final InputStream in = new ByteArrayInputStream(new byte[0]);
125             request.setEntity(new OutputRepresentation(
126                     MediaType.MULTIPART_FORM_DATA) {
127
128                 @Override
129                 public void write(OutputStream outputStream) throws IOException {
130                     byte[] buffer = new byte[1024 * 64];
131                     int read;
132                     while((read = in.read(buffer)) != -1){
133                         outputStream.write(buffer, 0, read);
134                     }
135                 }
136             });
137             //following call to handler.handle is not needed as queryparams
138             //contains the real data
139             RepresentationWrapper wrapDoc = new RepresentationWrapper(new DefaultDocument());
140             repHandler.handle(Action.CREATE, wrapDoc);
141             //read response
142             //Nuxeo does not set 201 SUCCESS_CREATED on successful creation
143             Document document = executeRequest(request, completeURL, Status.SUCCESS_OK);
144             //handle is not needed on create as queryparams have all data
145             return extractId(document);
146
147         }catch(Exception e){
148             if(logger.isDebugEnabled()){
149                 logger.debug("Caught exception ", e);
150             }
151             throw new DocumentException(e);
152         }finally{
153         }
154     }
155
156     @Override
157     public void get(String id, DocumentHandler handler) throws DocumentNotFoundException, DocumentException {
158
159         if(handler == null){
160             throw new IllegalArgumentException("RepositoryRESTClient.get: handler is missing");
161         }
162
163         try{
164             RepresentationHandler repHandler = (RepresentationHandler) handler;
165             repHandler.prepare(Action.GET);
166             ArrayList pathParams = new ArrayList();
167             pathParams.add("default");
168             pathParams.add(id);
169             pathParams.add("export");
170             if(repHandler.getPathParams().size() > 0){
171                 pathParams.addAll(repHandler.getPathParams());
172             }
173             HashMap<String, String> queryParams = new HashMap<String, String>();
174             queryParams.put("format", "XML");
175             if(repHandler.getQueryParams().size() > 0){
176                 queryParams.putAll(repHandler.getQueryParams());
177             }
178             String completeURL = getNuxeoRestClient().buildUrl(pathParams, queryParams);
179             if(logger.isDebugEnabled()){
180                 logger.debug("get using url=" + completeURL);
181             }
182             Request request = buildRequest(Method.GET, completeURL);
183             Document document = executeRequest(request, completeURL, Status.SUCCESS_OK);
184             RepresentationWrapper wrapDoc = new RepresentationWrapper(document);
185             repHandler.handle(Action.GET, wrapDoc);
186         }catch(Exception e){
187             if(logger.isDebugEnabled()){
188                 logger.debug("Caught exception ", e);
189             }
190             throw new DocumentException(e);
191         }finally{
192         }
193     }
194
195     @Override
196     public void getAll(String serviceName, DocumentHandler handler) throws DocumentNotFoundException, DocumentException {
197         if(serviceName == null){
198             throw new IllegalArgumentException("RepositoryRESTClient.getAll: serviceName is missing");
199         }
200         if(handler == null){
201             throw new IllegalArgumentException("RepositoryRESTClient.getAll: handler is missing");
202         }
203         ServiceMain smain = ServiceMain.getInstance();
204         String nuxeoWspaceId = smain.getWorkspaceId(serviceName);
205         if(nuxeoWspaceId == null){
206             throw new DocumentNotFoundException("Unable to find workspace for service " + serviceName +
207                     " check if the mapping exists in service-config.xml or " +
208                     " the the mapped workspace exists in the Nuxeo repository");
209         }
210         try{
211             RepresentationHandler repHandler = (RepresentationHandler) handler;
212             repHandler.prepare(Action.GET_ALL);
213             ArrayList pathParams = new ArrayList();
214             pathParams.add("default");
215             pathParams.add(nuxeoWspaceId);
216             pathParams.add("browse");
217             if(repHandler.getPathParams().size() > 0){
218                 pathParams.addAll(repHandler.getPathParams());
219             }
220             String completeURL = getNuxeoRestClient().buildUrl(pathParams, repHandler.getQueryParams());
221             if(logger.isDebugEnabled()){
222                 logger.debug("getAll using url=" + completeURL);
223             }
224             Request request = buildRequest(Method.GET, completeURL);
225             Document document = executeRequest(request, completeURL, Status.SUCCESS_OK);
226             RepresentationWrapper wrapDoc = new RepresentationWrapper(document);
227             repHandler.handle(Action.GET_ALL, wrapDoc);
228         }catch(Exception e){
229             if(logger.isDebugEnabled()){
230                 logger.debug("Caught exception ", e);
231             }
232             throw new DocumentException(e);
233         }finally{
234         }
235     }
236
237     @Override
238     public void update(String id, DocumentHandler handler) throws BadRequestException, DocumentNotFoundException, DocumentException {
239         if(handler == null){
240             throw new IllegalArgumentException("RepositoryRESTClient.update: handler is missing");
241         }
242
243         try{
244             RepresentationHandler repHandler = (RepresentationHandler) handler;
245             repHandler.prepare(Action.UPDATE);
246             List<String> pathParams = new ArrayList<String>();
247             pathParams.add("default");
248             pathParams.add(id);
249             pathParams.add("updateDocumentRestlet");
250             if(repHandler.getPathParams().size() > 0){
251                 pathParams.addAll(repHandler.getPathParams());
252             }
253             String completeURL = getNuxeoRestClient().buildUrl(pathParams, repHandler.getQueryParams());
254             if(logger.isDebugEnabled()){
255                 logger.debug("update using url=" + completeURL);
256             }
257             //repHandler.handle is not needed as queryParams contain all the data
258             RepresentationWrapper wrapDoc = new RepresentationWrapper(new DefaultDocument());
259             repHandler.handle(Action.UPDATE, wrapDoc);
260             Request request = buildRequest(Method.PUT, completeURL);
261             Document document = executeRequest(request, completeURL, Status.SUCCESS_OK);
262
263         }catch(Exception e){
264             if(logger.isDebugEnabled()){
265                 logger.debug("Caught exception ", e);
266             }
267             throw new DocumentException(e);
268         }finally{
269         }
270     }
271
272     @Override
273     public void delete(String id) throws DocumentNotFoundException, DocumentException {
274
275         if(logger.isDebugEnabled()){
276             logger.debug("deleting document with id=" + id);
277         }
278
279         try{
280             List<String> pathParams = new ArrayList<String>();
281             pathParams.add("default");
282             pathParams.add(id);
283             pathParams.add("deleteDocumentRestlet");
284
285             Map<String, String> queryParams = new HashMap<String, String>();
286             String completeURL = getNuxeoRestClient().buildUrl(pathParams, queryParams);
287             if(logger.isDebugEnabled()){
288                 logger.debug("delete using url=" + completeURL);
289             }
290             Request request = buildRequest(Method.DELETE, completeURL);
291             Document document = executeRequest(request, completeURL, Status.SUCCESS_OK);
292             //FIXME error handling?
293             //            Document document = service.deleteCollectionObject(csid);
294 //            Element root = document.getRootElement();
295 //            for(Iterator i = root.elementIterator(); i.hasNext();){
296 //                Element element = (Element) i.next();
297 //                if("docRef".equals(element.getName())){
298 //                    String status = (String) element.getData();
299 //                    verbose("deleteCollectionObjectt response: " + status);
300 //                }
301 //            }
302
303         }catch(Exception e){
304             if(logger.isDebugEnabled()){
305                 logger.debug("Caught exception ", e);
306             }
307             throw new DocumentException(e);
308         }finally{
309         }
310     }
311
312     /**
313      * buildRequest build HTTP request given parameters
314      * @param method
315      * @param completeURL
316      * @return
317      */
318     private Request buildRequest(Method method, String completeURL) {
319         Request request = new Request(method, completeURL);
320         getNuxeoRestClient().setupAuth(request);
321         getNuxeoRestClient().setupCookies(request);
322         return request;
323     }
324
325     /**
326      * executeRequest execute given HTTP request
327      * @param request
328      * @param completeURL
329      * @return
330      * @throws Exception
331      */
332     private Document executeRequest(Request request, String completeURL, Status expected) throws Exception {
333         //execute
334         Response res = getNuxeoRestClient().getRestClient().handle(request);
335         Status status = res.getStatus();
336         if(status.getCode() != expected.getCode()){
337             logger.error("failed to execute request=" + request.getMethod() +
338                     " with error status=" + status +
339                     " url=" + completeURL +
340                     " response=" + res.toString());
341             throw new DocumentException(status.getCode(), status.getDescription());
342         }
343         Representation rep = res.getEntity();
344
345         //read response
346         return retrieveResponse(rep);
347     }
348
349     /**
350      * retrieveResponse retrieves DOM document from Restlet Represeantion
351      * @param request
352      * @return
353      * @throws Exception
354      */
355     private Document retrieveResponse(Representation rep) throws Exception {
356         SAXReader reader = new SAXReader();
357         Document document = reader.read(rep.getStream());
358         return document;
359     }
360
361     /**
362      * extractId extract document id from response
363      * @param document
364      * @return
365      */
366     private String extractId(Document document) {
367         String csid = null;
368         Element root = document.getRootElement();
369         for(Iterator i = root.elementIterator(); i.hasNext();){
370             Element element = (Element) i.next();
371             if("docRef".equals(element.getName())){
372                 csid = (String) element.getData();
373                 break;
374             }
375         }
376         return csid;
377     }
378
379     private NuxeoRESTClient getNuxeoRestClient() {
380         if(nuxeoRestClient == null){
381             ServiceConfig sconfig = ServiceMain.getInstance().getServiceConfig();
382             NuxeoClientConfig nxConfig = sconfig.getNuxeoClientConfig();
383             String protocol = "http";
384             if(nxConfig.getProtocol() != null && !"".equals(nxConfig.getProtocol())){
385                 protocol = nxConfig.getProtocol();
386             }
387             NuxeoRESTClient tempClient = new NuxeoRESTClient(protocol,
388                     nxConfig.getHost(), "" + nxConfig.getPort());
389
390             tempClient.setBasicAuthentication(nxConfig.getUser(), nxConfig.getPassword());
391
392             nuxeoRestClient = tempClient;
393
394         }
395         return nuxeoRestClient;
396     }
397 }