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.documentlibrary.util;
16  
17  import com.liferay.documentlibrary.DuplicateFileException;
18  import com.liferay.documentlibrary.NoSuchFileException;
19  import com.liferay.documentlibrary.model.FileModel;
20  import com.liferay.portal.cmis.CMISException;
21  import com.liferay.portal.cmis.CMISUtil;
22  import com.liferay.portal.cmis.model.CMISConstants;
23  import com.liferay.portal.cmis.model.CMISObject;
24  import com.liferay.portal.kernel.exception.PortalException;
25  import com.liferay.portal.kernel.log.Log;
26  import com.liferay.portal.kernel.log.LogFactoryUtil;
27  import com.liferay.portal.kernel.search.Document;
28  import com.liferay.portal.kernel.search.Indexer;
29  import com.liferay.portal.kernel.search.IndexerRegistryUtil;
30  import com.liferay.portal.kernel.search.SearchEngineUtil;
31  import com.liferay.portal.kernel.search.SearchException;
32  import com.liferay.portal.kernel.util.GetterUtil;
33  import com.liferay.portal.kernel.util.Validator;
34  import com.liferay.portal.service.ServiceContext;
35  import com.liferay.portlet.documentlibrary.util.DLUtil;
36  
37  import java.io.InputStream;
38  
39  import java.util.ArrayList;
40  import java.util.Collection;
41  import java.util.Date;
42  import java.util.List;
43  
44  import org.apache.abdera.model.Entry;
45  import org.apache.abdera.model.Link;
46  
47  /**
48   * <a href="CMISHook.java.html"><b><i>View Source</i></b></a>
49   *
50   * @author Alexander Chow
51   */
52  public class CMISHook extends BaseHook {
53  
54      public CMISHook() {
55          try {
56              String version = CMISUtil.verifyRepository();
57  
58              if (_log.isInfoEnabled()) {
59                  _log.info("CMIS Service is running version " + version);
60              }
61          }
62          catch (Exception e) {
63              _log.error(e, e);
64          }
65      }
66  
67      public void addDirectory(long companyId, long repositoryId, String dirName)
68          throws PortalException {
69  
70          Entry repositoryFolderEntry = getRepositoryFolderEntry(
71              companyId, repositoryId);
72  
73          CMISUtil.createFolder(repositoryFolderEntry, dirName);
74      }
75  
76      public void addFile(
77              long companyId, String portletId, long groupId, long repositoryId,
78              String fileName, long fileEntryId, String properties,
79              Date modifiedDate, ServiceContext serviceContext, InputStream is)
80          throws PortalException {
81  
82          updateFile(
83              companyId, portletId, groupId, repositoryId, fileName,
84              DEFAULT_VERSION, null, fileEntryId, properties, modifiedDate,
85              serviceContext, is);
86      }
87  
88      public void checkRoot(long companyId) {
89      }
90  
91      public void deleteDirectory(
92              long companyId, String portletId, long repositoryId, String dirName)
93          throws PortalException {
94  
95          Entry repositoryFolderEntry = getRepositoryFolderEntry(
96              companyId, repositoryId);
97  
98          Entry directory = CMISUtil.getFolder(repositoryFolderEntry, dirName);
99  
100         if (directory != null) {
101             CMISUtil.delete(directory);
102         }
103     }
104 
105     public void deleteFile(
106             long companyId, String portletId, long repositoryId,
107             String fileName)
108         throws PortalException {
109 
110         Entry versioningFolderEntry = getVersioningFolderEntry(
111             companyId, repositoryId, fileName, false);
112 
113         if (versioningFolderEntry == null) {
114             throw new NoSuchFileException();
115         }
116 
117         CMISUtil.delete(versioningFolderEntry);
118 
119         Indexer indexer = IndexerRegistryUtil.getIndexer(
120             FileModel.class);
121 
122         FileModel fileModel = new FileModel();
123 
124         fileModel.setCompanyId(companyId);
125         fileModel.setFileName(fileName);
126         fileModel.setPortletId(portletId);
127         fileModel.setRepositoryId(repositoryId);
128 
129         indexer.delete(fileModel);
130     }
131 
132     public void deleteFile(
133             long companyId, String portletId, long repositoryId,
134             String fileName, String versionNumber)
135         throws PortalException {
136 
137         Entry fileEntry = getVersionedFileEntry(
138             companyId, repositoryId, fileName, versionNumber);
139 
140         CMISUtil.delete(fileEntry);
141 
142         Indexer indexer = IndexerRegistryUtil.getIndexer(
143             FileModel.class);
144 
145         FileModel fileModel = new FileModel();
146 
147         fileModel.setCompanyId(companyId);
148         fileModel.setFileName(fileName);
149         fileModel.setPortletId(portletId);
150         fileModel.setRepositoryId(repositoryId);
151 
152         indexer.delete(fileModel);
153     }
154 
155     public InputStream getFileAsStream(
156             long companyId, long repositoryId, String fileName,
157             String versionNumber)
158         throws PortalException {
159 
160         if (Validator.isNull(versionNumber)) {
161             versionNumber = getHeadVersionNumber(
162                 companyId, repositoryId, fileName);
163         }
164 
165         Entry fileEntry = getVersionedFileEntry(
166             companyId, repositoryId, fileName, versionNumber);
167 
168         return CMISUtil.getInputStream(fileEntry);
169     }
170 
171     public String[] getFileNames(
172             long companyId, long repositoryId, String dirName)
173         throws PortalException {
174 
175         Entry repositoryFolderEntry = getRepositoryFolderEntry(
176             companyId, repositoryId);
177 
178         List<String> fileNames = CMISUtil.getFolders(repositoryFolderEntry);
179 
180         return fileNames.toArray(new String[fileNames.size()]);
181     }
182 
183     public long getFileSize(
184             long companyId, long repositoryId, String fileName)
185         throws PortalException {
186 
187         String versionNumber = getHeadVersionNumber(
188             companyId, repositoryId, fileName);
189 
190         Entry fileEntry = getVersionedFileEntry(
191             companyId, repositoryId, fileName, versionNumber);
192 
193         CMISObject cmisObject = fileEntry.getFirstChild(_cmisConstants.OBJECT);
194 
195         return cmisObject.getContentStreamLength();
196     }
197 
198     public String getHeadVersionNumber(
199             long companyId, long repositoryId, String dirName)
200         throws CMISException, NoSuchFileException {
201 
202         Entry versioningFolderEntry = getVersioningFolderEntry(
203             companyId, repositoryId, dirName, false);
204 
205         if (versioningFolderEntry == null) {
206             throw new NoSuchFileException();
207         }
208 
209         List<String> versionNumbers = CMISUtil.getFolders(
210             versioningFolderEntry);
211 
212         String headVersionNumber = DEFAULT_VERSION;
213 
214         for (String versionNumber : versionNumbers) {
215             if (DLUtil.compareVersions(versionNumber, headVersionNumber) > 0) {
216                 headVersionNumber = versionNumber;
217             }
218         }
219 
220         return headVersionNumber;
221     }
222 
223     public boolean hasFile(
224             long companyId, long repositoryId, String fileName,
225             String versionNumber)
226         throws PortalException {
227 
228         Entry versioningFolderEntry = getVersioningFolderEntry(
229             companyId, repositoryId, fileName, true);
230 
231         Link link = versioningFolderEntry.getLink(
232             _cmisConstants.LINK_DESCENDANTS);
233 
234         String url = link.getHref().toString();
235 
236         Entry fileEntry = CMISUtil.getEntry(
237             url, versionNumber, _cmisConstants.BASE_TYPE_DOCUMENT);
238 
239         if (fileEntry == null) {
240             return false;
241         }
242         else {
243             return true;
244         }
245     }
246 
247     public void move(String srcDir, String destDir) {
248     }
249 
250     public void reindex(String[] ids) throws SearchException {
251         long companyId = GetterUtil.getLong(ids[0]);
252         String portletId = ids[1];
253         long groupId = GetterUtil.getLong(ids[2]);
254         long repositoryId = GetterUtil.getLong(ids[3]);
255 
256         Collection<Document> documents = new ArrayList<Document>();
257 
258         try {
259             Entry repositoryFolderEntry = getRepositoryFolderEntry(
260                 companyId, repositoryId);
261 
262             List<String> fileNames = CMISUtil.getFolders(repositoryFolderEntry);
263 
264             for (String fileName : fileNames) {
265                 try {
266                     Indexer indexer = IndexerRegistryUtil.getIndexer(
267                         FileModel.class);
268 
269                     FileModel fileModel = new FileModel();
270 
271                     fileModel.setCompanyId(companyId);
272                     fileModel.setFileName(fileName);
273                     fileModel.setGroupId(groupId);
274                     fileModel.setPortletId(portletId);
275                     fileModel.setRepositoryId(repositoryId);
276 
277                     Document document = indexer.getDocument(fileModel);
278 
279                     if (document == null) {
280                         continue;
281                     }
282 
283                     documents.add(document);
284                 }
285                 catch (Exception e) {
286                     _log.error("Reindexing " + fileName, e);
287                 }
288             }
289         }
290         catch (CMISException cmise) {
291             if (_log.isErrorEnabled()) {
292                 _log.error(cmise, cmise);
293             }
294         }
295 
296         SearchEngineUtil.updateDocuments(companyId, documents);
297     }
298 
299     public void updateFile(
300             long companyId, String portletId, long groupId, long repositoryId,
301             long newRepositoryId, String fileName, long fileEntryId)
302         throws PortalException {
303 
304         Entry oldVersioningFolderEntry = getVersioningFolderEntry(
305             companyId, repositoryId, fileName, true);
306         Entry newVersioningFolderEntry = getVersioningFolderEntry(
307             companyId, newRepositoryId, fileName, true);
308 
309         List<String> fileNames = CMISUtil.getFolders(oldVersioningFolderEntry);
310 
311         for (String curFileName : fileNames) {
312             Entry entry = CMISUtil.getDocument(
313                 oldVersioningFolderEntry, curFileName);
314 
315             InputStream is = CMISUtil.getInputStream(entry);
316 
317             CMISUtil.createDocument(newVersioningFolderEntry, curFileName, is);
318         }
319 
320         CMISUtil.delete(oldVersioningFolderEntry);
321 
322         Indexer indexer = IndexerRegistryUtil.getIndexer(FileModel.class);
323 
324         FileModel fileModel = new FileModel();
325 
326         fileModel.setCompanyId(companyId);
327         fileModel.setFileName(fileName);
328         fileModel.setPortletId(portletId);
329         fileModel.setRepositoryId(repositoryId);
330 
331         indexer.delete(fileModel);
332 
333         fileModel.setRepositoryId(newRepositoryId);
334         fileModel.setGroupId(groupId);
335 
336         indexer.reindex(fileModel);
337     }
338 
339     public void updateFile(
340             long companyId, String portletId, long groupId, long repositoryId,
341             String fileName, String newFileName, boolean reindex)
342         throws PortalException {
343 
344         Entry oldVersioningFolderEntry = getVersioningFolderEntry(
345             companyId, repositoryId, fileName, true);
346         Entry newVersioningFolderEntry = getVersioningFolderEntry(
347             companyId, repositoryId, newFileName, true);
348 
349         List<String> fileNames = CMISUtil.getFolders(oldVersioningFolderEntry);
350 
351         for (String curFileName : fileNames) {
352             Entry entry = CMISUtil.getDocument(
353                 oldVersioningFolderEntry, curFileName);
354 
355             InputStream is = CMISUtil.getInputStream(entry);
356 
357             CMISUtil.createDocument(newVersioningFolderEntry, curFileName, is);
358         }
359 
360         CMISUtil.delete(oldVersioningFolderEntry);
361 
362         if (reindex) {
363             Indexer indexer = IndexerRegistryUtil.getIndexer(FileModel.class);
364 
365             FileModel fileModel = new FileModel();
366 
367             fileModel.setCompanyId(companyId);
368             fileModel.setFileName(fileName);
369             fileModel.setPortletId(portletId);
370             fileModel.setRepositoryId(repositoryId);
371 
372             indexer.delete(fileModel);
373 
374             fileModel.setFileName(newFileName);
375             fileModel.setGroupId(groupId);
376 
377             indexer.reindex(fileModel);
378         }
379     }
380 
381     public void updateFile(
382             long companyId, String portletId, long groupId, long repositoryId,
383             String fileName, String versionNumber, String sourceFileName,
384             long fileEntryId, String properties, Date modifiedDate,
385             ServiceContext serviceContext, InputStream is)
386         throws PortalException {
387 
388         Entry versioningFolderEntry = getVersioningFolderEntry(
389             companyId, repositoryId, fileName, true);
390 
391         Link link = versioningFolderEntry.getLink(
392             _cmisConstants.LINK_DESCENDANTS);
393 
394         String url = link.getHref().toString();
395 
396         String title = String.valueOf(versionNumber);
397 
398         Entry fileEntry = CMISUtil.getEntry(
399             url, title, _cmisConstants.BASE_TYPE_DOCUMENT);
400 
401         if (fileEntry != null) {
402             throw new DuplicateFileException();
403         }
404 
405         fileEntry = CMISUtil.createDocument(url, title, is);
406 
407         Indexer indexer = IndexerRegistryUtil.getIndexer(FileModel.class);
408 
409         FileModel fileModel = new FileModel();
410 
411         fileModel.setAssetCategoryIds(serviceContext.getAssetCategoryIds());
412         fileModel.setAssetTagNames(serviceContext.getAssetTagNames());
413         fileModel.setCompanyId(companyId);
414         fileModel.setFileEntryId(fileEntryId);
415         fileModel.setFileName(fileName);
416         fileModel.setGroupId(groupId);
417         fileModel.setModifiedDate(modifiedDate);
418         fileModel.setPortletId(portletId);
419         fileModel.setProperties(properties);
420         fileModel.setRepositoryId(repositoryId);
421 
422         indexer.reindex(fileModel);
423     }
424 
425     protected Entry getCompanyFolderEntry(long companyId) throws CMISException {
426         String title = String.valueOf(companyId);
427 
428         Entry companyFolderEntry = CMISUtil.getFolder(title);
429 
430         if (companyFolderEntry == null) {
431             companyFolderEntry = CMISUtil.createFolder(title);
432         }
433 
434         return companyFolderEntry;
435     }
436 
437     protected Entry getRepositoryFolderEntry(long companyId, long repositoryId)
438         throws CMISException {
439 
440         Entry companyFolderEntry = getCompanyFolderEntry(companyId);
441 
442         Link link = companyFolderEntry.getLink(_cmisConstants.LINK_DESCENDANTS);
443 
444         String url = link.getHref().toString();
445 
446         String title = String.valueOf(repositoryId);
447 
448         Entry repositoryFolderEntry = CMISUtil.getFolder(url, title);
449 
450         if (repositoryFolderEntry == null) {
451             repositoryFolderEntry = CMISUtil.createFolder(url, title);
452         }
453 
454         return repositoryFolderEntry;
455     }
456 
457     protected Entry getVersionedFileEntry(
458             long companyId, long repositoryId, String fileName,
459             String versionNumber)
460         throws CMISException, NoSuchFileException {
461 
462         Entry versioningFolderEntry = getVersioningFolderEntry(
463             companyId, repositoryId, fileName, false);
464 
465         if (versioningFolderEntry == null) {
466             throw new NoSuchFileException();
467         }
468 
469         Link link = versioningFolderEntry.getLink(
470             _cmisConstants.LINK_DESCENDANTS);
471 
472         String url = link.getHref().toString();
473 
474         Entry fileEntry = CMISUtil.getEntry(
475             url, String.valueOf(versionNumber),
476             _cmisConstants.BASE_TYPE_DOCUMENT);
477 
478         if (fileEntry == null) {
479             throw new NoSuchFileException();
480         }
481 
482         return fileEntry;
483     }
484 
485     protected Entry getVersioningFolderEntry(
486             long companyId, long repositoryId, String fileName, boolean create)
487         throws CMISException {
488 
489         Entry repositoryFolderEntry = getRepositoryFolderEntry(
490             companyId, repositoryId);
491 
492         Link link = repositoryFolderEntry.getLink(
493             _cmisConstants.LINK_DESCENDANTS);
494 
495         String url = link.getHref().toString();
496 
497         Entry versioningFolderEntry = CMISUtil.getEntry(
498             url, fileName, _cmisConstants.BASE_TYPE_FOLDER);
499 
500         if (create && (versioningFolderEntry == null)) {
501             versioningFolderEntry = CMISUtil.createFolder(url, fileName);
502         }
503 
504         return versioningFolderEntry;
505     }
506 
507     private static Log _log = LogFactoryUtil.getLog(CMISHook.class);
508 
509     private static CMISConstants _cmisConstants = CMISConstants.getInstance();
510 
511 }