001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.cmis;
016    
017    import com.liferay.portal.cmis.model.CMISConstants;
018    import com.liferay.portal.cmis.model.CMISConstants_1_0_0;
019    import com.liferay.portal.cmis.model.CMISExtensionFactory;
020    import com.liferay.portal.cmis.model.CMISObject;
021    import com.liferay.portal.cmis.model.CMISRepositoryInfo;
022    import com.liferay.portal.kernel.log.Log;
023    import com.liferay.portal.kernel.log.LogFactoryUtil;
024    import com.liferay.portal.util.PropsValues;
025    
026    import java.io.InputStream;
027    
028    import java.util.ArrayList;
029    import java.util.List;
030    
031    import org.apache.abdera.Abdera;
032    import org.apache.abdera.factory.Factory;
033    import org.apache.abdera.model.Collection;
034    import org.apache.abdera.model.Element;
035    import org.apache.abdera.model.Entry;
036    import org.apache.abdera.model.Feed;
037    import org.apache.abdera.model.Link;
038    import org.apache.abdera.model.Service;
039    import org.apache.abdera.model.Workspace;
040    import org.apache.abdera.protocol.Response.ResponseType;
041    import org.apache.abdera.protocol.client.AbderaClient;
042    import org.apache.abdera.protocol.client.ClientResponse;
043    import org.apache.commons.httpclient.UsernamePasswordCredentials;
044    
045    /**
046     * @author Alexander Chow
047     */
048    public class CMISUtil {
049    
050            public static Entry createDocument(
051                            Entry entry, String title, InputStream is)
052                    throws CMISException {
053    
054                    return _instance._createDocument(entry, title, is);
055            }
056    
057            public static Entry createDocument(String url, String title, InputStream is)
058                    throws CMISException {
059    
060                    return _instance._createDocument(url, title, is);
061            }
062    
063            public static Entry createFolder(Entry entry, String title)
064                    throws CMISException {
065    
066                    return _instance._createFolder(entry, title);
067            }
068    
069            public static Entry createFolder(String title) throws CMISException {
070                    return _instance._createFolder(title);
071            }
072    
073            public static Entry createFolder(String url, String title)
074                    throws CMISException {
075    
076                    return _instance._createFolder(url, title);
077            }
078    
079            public static void delete(Entry entry) throws CMISException {
080                    _instance._delete(entry);
081            }
082    
083            public static void delete(String url) throws CMISException {
084                    _instance._delete(url);
085            }
086    
087            public static String getCollectionType(Collection collection) {
088                    return _instance._getCollectionType(collection);
089            }
090    
091            public static String getCollectionUrl(
092                    Workspace workspace, String collectionType) {
093    
094                    return _instance._getCollectionUrl(workspace, collectionType);
095            }
096    
097            public static Entry getDocument(Entry entry, String title)
098                    throws CMISException {
099    
100                    return _instance._getDocument(entry, title);
101            }
102    
103            public static Entry getDocument(String url, String title)
104                    throws CMISException {
105    
106                    return _instance._getDocument(url, title);
107            }
108    
109            public static Entry getEntry(String url, String title, String baseType)
110                    throws CMISException {
111    
112                    return _instance._getEntry(url, title, baseType);
113            }
114    
115            public static Entry getFolder(Entry entry, String title)
116                    throws CMISException {
117    
118                    return _instance._getFolder(entry, title);
119            }
120    
121            public static Entry getFolder(String title) throws CMISException {
122                    return _instance._getFolder(title);
123            }
124    
125            public static Entry getFolder(String url, String title)
126                    throws CMISException {
127    
128                    return _instance._getFolder(url, title);
129            }
130    
131            public static List<String> getFolders(Entry entry) throws CMISException {
132                    return _instance._getFolders(entry);
133            }
134    
135            public static InputStream getInputStream(Entry entry) throws CMISException {
136                    return _instance._getInputStream(entry);
137            }
138    
139            public static Service getService() throws CMISException {
140                    return _instance._getService();
141            }
142    
143            public static String verifyRepository() throws Exception {
144                    return _instance._verifyRepository();
145            }
146    
147            private CMISUtil() {
148                    try {
149                            _abdera = Abdera.getInstance();
150                            _cmisConstants = CMISConstants.getInstance();
151                            _usernamePasswordCredentials = new UsernamePasswordCredentials(
152                                    PropsValues.CMIS_CREDENTIALS_USERNAME,
153                                    PropsValues.CMIS_CREDENTIALS_PASSWORD);
154    
155                            Factory factory = _abdera.getFactory();
156    
157                            factory.registerExtension(new CMISExtensionFactory());
158                    }
159                    catch (Exception e) {
160                            if (e instanceof RuntimeException) {
161                                    throw (RuntimeException)e;
162                            }
163                            else {
164                                    throw new RuntimeException(e);
165                            }
166                    }
167            }
168    
169            private Entry _createDocument(Entry entry, String title, InputStream is)
170                    throws CMISException {
171    
172                    Link link = entry.getLink(_cmisConstants.LINK_CHILDREN);
173    
174                    return createDocument(link.getHref().toString(), title, is);
175            }
176    
177            private Entry _createDocument(String url, String title, InputStream is)
178                    throws CMISException {
179    
180                    Entry entry = _abdera.newEntry();
181    
182                    entry.setTitle(title);
183    
184                    if (is == null) {
185                            CMISObject cmisObject = entry.addExtension(_cmisConstants.OBJECT);
186    
187                            cmisObject.setValue(
188                                    _cmisConstants.PROPERTY_NAME_OBJECT_TYPE_ID,
189                                    _cmisConstants.BASE_TYPE_FOLDER);
190                    }
191                    else {
192                            entry.setContent(is);
193    
194                            CMISObject cmisObject = entry.addExtension(_cmisConstants.OBJECT);
195    
196                            cmisObject.setValue(
197                                    _cmisConstants.PROPERTY_NAME_OBJECT_TYPE_ID,
198                                    _cmisConstants.BASE_TYPE_DOCUMENT);
199                    }
200    
201                    ClientResponse clientResponse = _getAbedraClient().post(
202                            url, entry);
203    
204                    _verify(clientResponse);
205    
206                    if (ResponseType.select(
207                                    clientResponse.getStatus()) != ResponseType.SUCCESS) {
208    
209                            throw new CMISException(
210                                    "Error creating " + title + " " +
211                                            clientResponse.getStatusText());
212                    }
213    
214                    return (Entry)clientResponse.getDocument().getRoot();
215            }
216    
217            private Entry _createFolder(Entry entry, String title)
218                    throws CMISException {
219    
220                    return _createDocument(entry, title, null);
221            }
222    
223            private Entry _createFolder(String title) throws CMISException {
224                    return _createFolder(_linkChildrenURL, title);
225            }
226    
227            private Entry _createFolder(String url, String title) throws CMISException {
228                    return _createDocument(url, title, null);
229            }
230    
231            private void _delete(Entry entry) throws CMISException {
232                    Link link = null;
233    
234                    CMISObject cmisObject = entry.getFirstChild(_cmisConstants.OBJECT);
235    
236                    if (cmisObject.getBaseType().equals(_cmisConstants.BASE_TYPE_FOLDER)) {
237                            link = entry.getLink(_cmisConstants.LINK_CHILDREN);
238                    }
239                    else {
240                            link = entry.getLink(_cmisConstants.LINK_ALL_VERSIONS);
241                    }
242    
243                    delete(link.getHref().toString());
244            }
245    
246            private void _delete(String url) throws CMISException {
247                    ClientResponse clientResponse = _getAbedraClient().delete(url);
248    
249                    _verify(clientResponse);
250    
251                    if (ResponseType.select(
252                                    clientResponse.getStatus()) != ResponseType.SUCCESS) {
253    
254                            throw new CMISException(
255                                    "Error deleting object at " + url + " " +
256                                            clientResponse.getStatusText());
257                    }
258            }
259    
260            private AbderaClient _getAbedraClient() throws CMISException {
261                    try {
262                            AbderaClient abderaClient = new AbderaClient(_abdera);
263    
264                            abderaClient.addCredentials(
265                                    null, null, null, _usernamePasswordCredentials);
266    
267                            return abderaClient;
268                    }
269                    catch (Exception e) {
270                            throw new CMISException(e);
271                    }
272            }
273    
274            private String _getCollectionUrl(
275                    Workspace workspace, String collectionType) {
276    
277                    for (Collection collection : workspace.getCollections()) {
278                            String curCollectionType = _getCollectionType(collection);
279    
280                            if (collectionType.equals(curCollectionType)) {
281                                    return collection.getHref().toString();
282                            }
283                    }
284    
285                    return null;
286            }
287    
288            private Entry _getDocument(Entry entry, String title) throws CMISException {
289                    Link link = entry.getLink(_cmisConstants.LINK_CHILDREN);
290    
291                    return _getDocument(link.getHref().toString(), title);
292            }
293    
294            private Entry _getDocument(String url, String title) throws CMISException {
295                    return _getEntry(url, title, _cmisConstants.BASE_TYPE_DOCUMENT);
296            }
297    
298            private Entry _getEntry(String url, String title, String baseType)
299                    throws CMISException {
300    
301                    ClientResponse clientResponse = _getAbedraClient().get(url);
302    
303                    _verify(clientResponse);
304    
305                    Feed feed = (Feed)clientResponse.getDocument().getRoot();
306    
307                    for (Entry entry : feed.getEntries()) {
308                            if (entry.getTitle().equals(title)) {
309                                    CMISObject cmisObject = entry.getFirstChild(
310                                            _cmisConstants.OBJECT);
311    
312                                    if (baseType.equals(cmisObject.getBaseType())) {
313                                            return entry;
314                                    }
315                            }
316                    }
317    
318                    return null;
319            }
320    
321            private Entry _getFolder(Entry entry, String title) throws CMISException {
322                    Link link = entry.getLink(_cmisConstants.LINK_CHILDREN);
323    
324                    return _getFolder(link.getHref().toString(), title);
325            }
326    
327            private Entry _getFolder(String title) throws CMISException {
328                    return _getFolder(_linkChildrenURL, title);
329            }
330    
331            private Entry _getFolder(String url, String title) throws CMISException {
332                    return _getEntry(url, title, _cmisConstants.BASE_TYPE_FOLDER);
333            }
334    
335            private List<String> _getFolders(Entry entry) throws CMISException {
336                    List<String> folders = new ArrayList<String>();
337    
338                    Link link = entry.getLink(_cmisConstants.LINK_CHILDREN);
339    
340                    String url = link.getHref().toString();
341    
342                    ClientResponse clientResponse = _getAbedraClient().get(url);
343    
344                    _verify(clientResponse);
345    
346                    Feed feed = (Feed)clientResponse.getDocument().getRoot();
347    
348                    for (Entry curEntry : feed.getEntries()) {
349                            folders.add(curEntry.getTitle());
350                    }
351    
352                    return folders;
353            }
354    
355            private InputStream _getInputStream(Entry entry) throws CMISException {
356                    try {
357                            Link link = entry.getLink(_cmisConstants.LINK_STREAM);
358    
359                            String url = link.getHref().toString();
360    
361                            ClientResponse clientResponse = _getAbedraClient().get(url);
362    
363                            _verify(clientResponse);
364    
365                            return clientResponse.getInputStream();
366                    }
367                    catch (Exception e) {
368                            throw new CMISException(e);
369                    }
370            }
371    
372            private Service _getService() throws CMISException {
373                    ClientResponse clientResponse = _getAbedraClient().get(
374                            PropsValues.CMIS_REPOSITORY_URL);
375    
376                    _verify(clientResponse);
377    
378                    return (Service)clientResponse.getDocument().getRoot();
379            }
380    
381            private void _verify(ClientResponse clientResponse) throws CMISException {
382                    int status = clientResponse.getStatus();
383                    String statusText = clientResponse.getStatusText();
384    
385                    if (status >= 300) {
386                            throw new CMISException(
387                                    "CMIS server returned " + status + " " + statusText);
388                    }
389            }
390    
391            private String _verifyRepository() throws Exception {
392                    Service service = _getService();
393    
394                    Workspace workspace = service.getWorkspaces().get(0);
395    
396                    CMISRepositoryInfo cmisRepositoryInfo = workspace.getFirstChild(
397                            _cmisConstants.REPOSITORY_INFO);
398    
399                    // CMIS version
400    
401                    String version = cmisRepositoryInfo.getVersionSupported();
402    
403                    if (_log.isInfoEnabled()) {
404                            _log.info(
405                                    "Using CMIS repository " + cmisRepositoryInfo.getProductName() +
406                                            " " + cmisRepositoryInfo.getProductVersion());
407                            _log.info("CMIS repository supports CMIS version " + version);
408                    }
409    
410                    if (!version.equals(_cmisConstants.VERSION)) {
411                            throw new RuntimeException(
412                                    "CMIS repository is running an unsupported version");
413                    }
414    
415                    // Find root folder
416    
417                    String url = _getCollectionUrl(
418                            workspace, _cmisConstants.COLLECTION_ROOT);
419    
420                    Entry entry = _getEntry(
421                            url, PropsValues.CMIS_SYSTEM_ROOT_DIR,
422                            _cmisConstants.BASE_TYPE_FOLDER);
423    
424                    if (entry == null) {
425                            entry = _createFolder(url, PropsValues.CMIS_SYSTEM_ROOT_DIR);
426                    }
427    
428                    Link link = entry.getLink(_cmisConstants.LINK_CHILDREN);
429    
430                    _linkChildrenURL = link.getHref().toString();
431    
432                    return version;
433            }
434    
435            private String _getCollectionType(Collection collection) {
436                    if (_cmisConstants instanceof CMISConstants_1_0_0) {
437                            Element element = collection.getFirstChild(
438                                    _cmisConstants.COLLECTION_TYPE);
439    
440                            if (element == null) {
441                                    return null;
442                            }
443                            else {
444                                    return element.getText();
445                            }
446                    }
447                    else {
448                            return collection.getAttributeValue(_cmisConstants.COLLECTION_TYPE);
449                    }
450            }
451    
452            private static Log _log = LogFactoryUtil.getLog(CMISUtil.class);
453    
454            private static CMISUtil _instance = new CMISUtil();
455    
456            private Abdera _abdera;
457            private CMISConstants _cmisConstants;
458            private String _linkChildrenURL;
459            private UsernamePasswordCredentials _usernamePasswordCredentials;
460    
461    }