1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.cmis;
16  
17  import com.liferay.portal.cmis.model.CMISConstants;
18  import com.liferay.portal.cmis.model.CMISConstants_1_0_0;
19  import com.liferay.portal.cmis.model.CMISExtensionFactory;
20  import com.liferay.portal.cmis.model.CMISObject;
21  import com.liferay.portal.cmis.model.CMISRepositoryInfo;
22  import com.liferay.portal.kernel.log.Log;
23  import com.liferay.portal.kernel.log.LogFactoryUtil;
24  import com.liferay.portal.util.PropsValues;
25  
26  import java.io.InputStream;
27  
28  import java.util.ArrayList;
29  import java.util.List;
30  
31  import org.apache.abdera.Abdera;
32  import org.apache.abdera.factory.Factory;
33  import org.apache.abdera.model.Collection;
34  import org.apache.abdera.model.Element;
35  import org.apache.abdera.model.Entry;
36  import org.apache.abdera.model.Feed;
37  import org.apache.abdera.model.Link;
38  import org.apache.abdera.model.Service;
39  import org.apache.abdera.model.Workspace;
40  import org.apache.abdera.protocol.Response.ResponseType;
41  import org.apache.abdera.protocol.client.AbderaClient;
42  import org.apache.abdera.protocol.client.ClientResponse;
43  import org.apache.commons.httpclient.UsernamePasswordCredentials;
44  
45  /**
46   * <a href="CMISUtil.java.html"><b><i>View Source</i></b></a>
47   *
48   * @author Alexander Chow
49   */
50  public class CMISUtil {
51  
52      public static Entry createDocument(
53              Entry entry, String title, InputStream is)
54          throws CMISException {
55  
56          return _instance._createDocument(entry, title, is);
57      }
58  
59      public static Entry createDocument(String url, String title, InputStream is)
60          throws CMISException {
61  
62          return _instance._createDocument(url, title, is);
63      }
64  
65      public static Entry createFolder(Entry entry, String title)
66          throws CMISException {
67  
68          return _instance._createFolder(entry, title);
69      }
70  
71      public static Entry createFolder(String title) throws CMISException {
72          return _instance._createFolder(title);
73      }
74  
75      public static Entry createFolder(String url, String title)
76          throws CMISException {
77  
78          return _instance._createFolder(url, title);
79      }
80  
81      public static void delete(Entry entry) throws CMISException {
82          _instance._delete(entry);
83      }
84  
85      public static void delete(String url) throws CMISException {
86          _instance._delete(url);
87      }
88  
89      public static String getCollectionType(Collection collection) {
90          return _instance._getCollectionType(collection);
91      }
92  
93      public static String getCollectionUrl(
94          Workspace workspace, String collectionType) {
95  
96          return _instance._getCollectionUrl(workspace, collectionType);
97      }
98  
99      public static Entry getDocument(Entry entry, String title)
100         throws CMISException {
101 
102         return _instance._getDocument(entry, title);
103     }
104 
105     public static Entry getDocument(String url, String title)
106         throws CMISException {
107 
108         return _instance._getDocument(url, title);
109     }
110 
111     public static Entry getEntry(String url, String title, String baseType)
112         throws CMISException {
113 
114         return _instance._getEntry(url, title, baseType);
115     }
116 
117     public static Entry getFolder(Entry entry, String title)
118         throws CMISException {
119 
120         return _instance._getFolder(entry, title);
121     }
122 
123     public static Entry getFolder(String title) throws CMISException {
124         return _instance._getFolder(title);
125     }
126 
127     public static Entry getFolder(String url, String title)
128         throws CMISException {
129 
130         return _instance._getFolder(url, title);
131     }
132 
133     public static List<String> getFolders(Entry entry) throws CMISException {
134         return _instance._getFolders(entry);
135     }
136 
137     public static InputStream getInputStream(Entry entry) throws CMISException {
138         return _instance._getInputStream(entry);
139     }
140 
141     public static Service getService() throws CMISException {
142         return _instance._getService();
143     }
144 
145     public static String verifyRepository() throws Exception {
146         return _instance._verifyRepository();
147     }
148 
149     private CMISUtil() {
150         try {
151             _abdera = Abdera.getInstance();
152             _cmisConstants = CMISConstants.getInstance();
153             _usernamePasswordCredentials = new UsernamePasswordCredentials(
154                 PropsValues.CMIS_CREDENTIALS_USERNAME,
155                 PropsValues.CMIS_CREDENTIALS_PASSWORD);
156 
157             Factory factory = _abdera.getFactory();
158 
159             factory.registerExtension(new CMISExtensionFactory());
160         }
161         catch (Exception e) {
162             if (e instanceof RuntimeException) {
163                 throw (RuntimeException)e;
164             }
165             else {
166                 throw new RuntimeException(e);
167             }
168         }
169     }
170 
171     private Entry _createDocument(Entry entry, String title, InputStream is)
172         throws CMISException {
173 
174         Link link = entry.getLink(_cmisConstants.LINK_CHILDREN);
175 
176         return createDocument(link.getHref().toString(), title, is);
177     }
178 
179     private Entry _createDocument(String url, String title, InputStream is)
180         throws CMISException {
181 
182         Entry entry = _abdera.newEntry();
183 
184         entry.setTitle(title);
185 
186         if (is == null) {
187             CMISObject cmisObject = entry.addExtension(_cmisConstants.OBJECT);
188 
189             cmisObject.setValue(
190                 _cmisConstants.PROPERTY_NAME_OBJECT_TYPE_ID,
191                 _cmisConstants.BASE_TYPE_FOLDER);
192         }
193         else {
194             entry.setContent(is);
195 
196             CMISObject cmisObject = entry.addExtension(_cmisConstants.OBJECT);
197 
198             cmisObject.setValue(
199                 _cmisConstants.PROPERTY_NAME_OBJECT_TYPE_ID,
200                 _cmisConstants.BASE_TYPE_DOCUMENT);
201         }
202 
203         ClientResponse clientResponse = _getAbedraClient().post(
204             url, entry);
205 
206         _verify(clientResponse);
207 
208         if (ResponseType.select(
209                 clientResponse.getStatus()) != ResponseType.SUCCESS) {
210 
211             throw new CMISException(
212                 "Error creating " + title + " " +
213                     clientResponse.getStatusText());
214         }
215 
216         return (Entry)clientResponse.getDocument().getRoot();
217     }
218 
219     private Entry _createFolder(Entry entry, String title)
220         throws CMISException {
221 
222         return _createDocument(entry, title, null);
223     }
224 
225     private Entry _createFolder(String title) throws CMISException {
226         return _createFolder(_linkChildrenURL, title);
227     }
228 
229     private Entry _createFolder(String url, String title) throws CMISException {
230         return _createDocument(url, title, null);
231     }
232 
233     private void _delete(Entry entry) throws CMISException {
234         Link link = null;
235 
236         CMISObject cmisObject = entry.getFirstChild(_cmisConstants.OBJECT);
237 
238         if (cmisObject.getBaseType().equals(_cmisConstants.BASE_TYPE_FOLDER)) {
239             link = entry.getLink(_cmisConstants.LINK_CHILDREN);
240         }
241         else {
242             link = entry.getLink(_cmisConstants.LINK_ALL_VERSIONS);
243         }
244 
245         delete(link.getHref().toString());
246     }
247 
248     private void _delete(String url) throws CMISException {
249         ClientResponse clientResponse = _getAbedraClient().delete(url);
250 
251         _verify(clientResponse);
252 
253         if (ResponseType.select(
254                 clientResponse.getStatus()) != ResponseType.SUCCESS) {
255 
256             throw new CMISException(
257                 "Error deleting object at " + url + " " +
258                     clientResponse.getStatusText());
259         }
260     }
261 
262     private AbderaClient _getAbedraClient() throws CMISException {
263         try {
264             AbderaClient abderaClient = new AbderaClient(_abdera);
265 
266             abderaClient.addCredentials(
267                 null, null, null, _usernamePasswordCredentials);
268 
269             return abderaClient;
270         }
271         catch (Exception e) {
272             throw new CMISException(e);
273         }
274     }
275 
276     private String _getCollectionUrl(
277         Workspace workspace, String collectionType) {
278 
279         for (Collection collection : workspace.getCollections()) {
280             String curCollectionType = _getCollectionType(collection);
281 
282             if (collectionType.equals(curCollectionType)) {
283                 return collection.getHref().toString();
284             }
285         }
286 
287         return null;
288     }
289 
290     private Entry _getDocument(Entry entry, String title) throws CMISException {
291         Link link = entry.getLink(_cmisConstants.LINK_CHILDREN);
292 
293         return _getDocument(link.getHref().toString(), title);
294     }
295 
296     private Entry _getDocument(String url, String title) throws CMISException {
297         return _getEntry(url, title, _cmisConstants.BASE_TYPE_DOCUMENT);
298     }
299 
300     private Entry _getEntry(String url, String title, String baseType)
301         throws CMISException {
302 
303         ClientResponse clientResponse = _getAbedraClient().get(url);
304 
305         _verify(clientResponse);
306 
307         Feed feed = (Feed)clientResponse.getDocument().getRoot();
308 
309         for (Entry entry : feed.getEntries()) {
310             if (entry.getTitle().equals(title)) {
311                 CMISObject cmisObject = entry.getFirstChild(
312                     _cmisConstants.OBJECT);
313 
314                 if (baseType.equals(cmisObject.getBaseType())) {
315                     return entry;
316                 }
317             }
318         }
319 
320         return null;
321     }
322 
323     private Entry _getFolder(Entry entry, String title) throws CMISException {
324         Link link = entry.getLink(_cmisConstants.LINK_CHILDREN);
325 
326         return _getFolder(link.getHref().toString(), title);
327     }
328 
329     private Entry _getFolder(String title) throws CMISException {
330         return _getFolder(_linkChildrenURL, title);
331     }
332 
333     private Entry _getFolder(String url, String title) throws CMISException {
334         return _getEntry(url, title, _cmisConstants.BASE_TYPE_FOLDER);
335     }
336 
337     private List<String> _getFolders(Entry entry) throws CMISException {
338         List<String> folders = new ArrayList<String>();
339 
340         Link link = entry.getLink(_cmisConstants.LINK_CHILDREN);
341 
342         String url = link.getHref().toString();
343 
344         ClientResponse clientResponse = _getAbedraClient().get(url);
345 
346         _verify(clientResponse);
347 
348         Feed feed = (Feed)clientResponse.getDocument().getRoot();
349 
350         for (Entry curEntry : feed.getEntries()) {
351             folders.add(curEntry.getTitle());
352         }
353 
354         return folders;
355     }
356 
357     private InputStream _getInputStream(Entry entry) throws CMISException {
358         try {
359             Link link = entry.getLink(_cmisConstants.LINK_STREAM);
360 
361             String url = link.getHref().toString();
362 
363             ClientResponse clientResponse = _getAbedraClient().get(url);
364 
365             _verify(clientResponse);
366 
367             return clientResponse.getInputStream();
368         }
369         catch (Exception e) {
370             throw new CMISException(e);
371         }
372     }
373 
374     private Service _getService() throws CMISException {
375         ClientResponse clientResponse = _getAbedraClient().get(
376             PropsValues.CMIS_REPOSITORY_URL);
377 
378         _verify(clientResponse);
379 
380         return (Service)clientResponse.getDocument().getRoot();
381     }
382 
383     private void _verify(ClientResponse clientResponse) throws CMISException {
384         int status = clientResponse.getStatus();
385         String statusText = clientResponse.getStatusText();
386 
387         if (status >= 300) {
388             throw new CMISException(
389                 "CMIS server returned " + status + " " + statusText);
390         }
391     }
392 
393     private String _verifyRepository() throws Exception {
394         Service service = _getService();
395 
396         Workspace workspace = service.getWorkspaces().get(0);
397 
398         CMISRepositoryInfo cmisRepositoryInfo = workspace.getFirstChild(
399             _cmisConstants.REPOSITORY_INFO);
400 
401         // CMIS version
402 
403         String version = cmisRepositoryInfo.getVersionSupported();
404 
405         if (_log.isInfoEnabled()) {
406             _log.info(
407                 "Using CMIS repository " + cmisRepositoryInfo.getProductName() +
408                     " " + cmisRepositoryInfo.getProductVersion());
409             _log.info("CMIS repository supports CMIS version " + version);
410         }
411 
412         if (!version.equals(_cmisConstants.VERSION)) {
413             throw new RuntimeException(
414                 "CMIS repository is running an unsupported version");
415         }
416 
417         // Find root folder
418 
419         String url = _getCollectionUrl(
420             workspace, _cmisConstants.COLLECTION_ROOT);
421 
422         Entry entry = _getEntry(
423             url, PropsValues.CMIS_SYSTEM_ROOT_DIR,
424             _cmisConstants.BASE_TYPE_FOLDER);
425 
426         if (entry == null) {
427             entry = _createFolder(url, PropsValues.CMIS_SYSTEM_ROOT_DIR);
428         }
429 
430         Link link = entry.getLink(_cmisConstants.LINK_CHILDREN);
431 
432         _linkChildrenURL = link.getHref().toString();
433 
434         return version;
435     }
436 
437     private String _getCollectionType(Collection collection) {
438         if (_cmisConstants instanceof CMISConstants_1_0_0) {
439             Element element = collection.getFirstChild(
440                 _cmisConstants.COLLECTION_TYPE);
441 
442             if (element == null) {
443                 return null;
444             }
445             else {
446                 return element.getText();
447             }
448         }
449         else {
450             return collection.getAttributeValue(_cmisConstants.COLLECTION_TYPE);
451         }
452     }
453 
454     private static Log _log = LogFactoryUtil.getLog(CMISUtil.class);
455 
456     private static CMISUtil _instance = new CMISUtil();
457 
458     private Abdera _abdera;
459     private CMISConstants _cmisConstants;
460     private String _linkChildrenURL;
461     private UsernamePasswordCredentials _usernamePasswordCredentials;
462 
463 }