001
014
015 package com.liferay.portal.repository.cmis;
016
017 import com.liferay.portal.NoSuchRepositoryEntryException;
018 import com.liferay.portal.kernel.dao.orm.QueryUtil;
019 import com.liferay.portal.kernel.exception.PortalException;
020 import com.liferay.portal.kernel.exception.SystemException;
021 import com.liferay.portal.kernel.log.Log;
022 import com.liferay.portal.kernel.log.LogFactoryUtil;
023 import com.liferay.portal.kernel.repository.RepositoryException;
024 import com.liferay.portal.kernel.repository.cmis.BaseCmisRepository;
025 import com.liferay.portal.kernel.repository.cmis.CMISRepositoryHandler;
026 import com.liferay.portal.kernel.repository.cmis.search.CMISSearchQueryBuilderUtil;
027 import com.liferay.portal.kernel.repository.model.FileEntry;
028 import com.liferay.portal.kernel.repository.model.FileVersion;
029 import com.liferay.portal.kernel.repository.model.Folder;
030 import com.liferay.portal.kernel.search.DocumentImpl;
031 import com.liferay.portal.kernel.search.Field;
032 import com.liferay.portal.kernel.search.Hits;
033 import com.liferay.portal.kernel.search.HitsImpl;
034 import com.liferay.portal.kernel.search.Query;
035 import com.liferay.portal.kernel.search.QueryConfig;
036 import com.liferay.portal.kernel.search.SearchContext;
037 import com.liferay.portal.kernel.search.SearchException;
038 import com.liferay.portal.kernel.servlet.PortalSessionThreadLocal;
039 import com.liferay.portal.kernel.util.ArrayUtil;
040 import com.liferay.portal.kernel.util.AutoResetThreadLocal;
041 import com.liferay.portal.kernel.util.ListUtil;
042 import com.liferay.portal.kernel.util.OrderByComparator;
043 import com.liferay.portal.kernel.util.StringBundler;
044 import com.liferay.portal.kernel.util.StringPool;
045 import com.liferay.portal.kernel.util.StringUtil;
046 import com.liferay.portal.kernel.util.Time;
047 import com.liferay.portal.kernel.util.TransientValue;
048 import com.liferay.portal.kernel.util.Validator;
049 import com.liferay.portal.model.Lock;
050 import com.liferay.portal.model.RepositoryEntry;
051 import com.liferay.portal.repository.cmis.model.CMISFileEntry;
052 import com.liferay.portal.repository.cmis.model.CMISFileVersion;
053 import com.liferay.portal.repository.cmis.model.CMISFolder;
054 import com.liferay.portal.security.auth.PrincipalException;
055 import com.liferay.portal.security.auth.PrincipalThreadLocal;
056 import com.liferay.portal.service.RepositoryEntryLocalServiceUtil;
057 import com.liferay.portal.service.ServiceContext;
058 import com.liferay.portal.service.persistence.RepositoryEntryUtil;
059 import com.liferay.portal.util.PropsValues;
060 import com.liferay.portlet.documentlibrary.DuplicateFileException;
061 import com.liferay.portlet.documentlibrary.DuplicateFolderNameException;
062 import com.liferay.portlet.documentlibrary.FileNameException;
063 import com.liferay.portlet.documentlibrary.NoSuchFileEntryException;
064 import com.liferay.portlet.documentlibrary.NoSuchFileVersionException;
065 import com.liferay.portlet.documentlibrary.NoSuchFolderException;
066 import com.liferay.portlet.documentlibrary.model.DLFileEntryConstants;
067 import com.liferay.portlet.documentlibrary.model.DLFolder;
068 import com.liferay.portlet.documentlibrary.service.persistence.DLFolderUtil;
069 import com.liferay.portlet.documentlibrary.util.comparator.RepositoryModelCreateDateComparator;
070 import com.liferay.portlet.documentlibrary.util.comparator.RepositoryModelModifiedDateComparator;
071 import com.liferay.portlet.documentlibrary.util.comparator.RepositoryModelNameComparator;
072 import com.liferay.portlet.documentlibrary.util.comparator.RepositoryModelSizeComparator;
073
074 import java.io.InputStream;
075
076 import java.math.BigInteger;
077
078 import java.util.ArrayList;
079 import java.util.HashMap;
080 import java.util.Iterator;
081 import java.util.List;
082 import java.util.Map;
083 import java.util.Set;
084
085 import javax.servlet.http.HttpSession;
086
087 import org.apache.chemistry.opencmis.client.api.CmisObject;
088 import org.apache.chemistry.opencmis.client.api.Document;
089 import org.apache.chemistry.opencmis.client.api.FileableCmisObject;
090 import org.apache.chemistry.opencmis.client.api.ItemIterable;
091 import org.apache.chemistry.opencmis.client.api.ObjectId;
092 import org.apache.chemistry.opencmis.client.api.QueryResult;
093 import org.apache.chemistry.opencmis.client.api.Session;
094 import org.apache.chemistry.opencmis.client.runtime.ObjectIdImpl;
095 import org.apache.chemistry.opencmis.commons.PropertyIds;
096 import org.apache.chemistry.opencmis.commons.data.AllowableActions;
097 import org.apache.chemistry.opencmis.commons.data.ContentStream;
098 import org.apache.chemistry.opencmis.commons.data.PropertyData;
099 import org.apache.chemistry.opencmis.commons.data.RepositoryCapabilities;
100 import org.apache.chemistry.opencmis.commons.data.RepositoryInfo;
101 import org.apache.chemistry.opencmis.commons.enums.Action;
102 import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
103 import org.apache.chemistry.opencmis.commons.enums.CapabilityQuery;
104 import org.apache.chemistry.opencmis.commons.enums.UnfileObject;
105 import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
106 import org.apache.chemistry.opencmis.commons.exceptions.CmisPermissionDeniedException;
107 import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
108 import org.apache.chemistry.opencmis.commons.impl.Base64;
109 import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl;
110
111
124 public class CMISRepository extends BaseCmisRepository {
125
126 public CMISRepository(CMISRepositoryHandler cmisRepositoryHandler) {
127 _cmisRepositoryHandler = cmisRepositoryHandler;
128 }
129
130 @Override
131 public FileEntry addFileEntry(
132 long folderId, String sourceFileName, String mimeType, String title,
133 String description, String changeLog, InputStream is, long size,
134 ServiceContext serviceContext)
135 throws PortalException, SystemException {
136
137 if (Validator.isNull(title)) {
138 if (size == 0) {
139 throw new FileNameException();
140 }
141 else {
142 title = sourceFileName;
143 }
144 }
145
146 try {
147 Session session = getSession();
148
149 validateTitle(session, folderId, title);
150
151 org.apache.chemistry.opencmis.client.api.Folder cmisFolder =
152 getCmisFolder(session, folderId);
153
154 Map<String, Object> properties = new HashMap<String, Object>();
155
156 properties.put(PropertyIds.NAME, title);
157 properties.put(
158 PropertyIds.OBJECT_TYPE_ID, BaseTypeId.CMIS_DOCUMENT.value());
159
160 ContentStream contentStream = new ContentStreamImpl(
161 title, BigInteger.valueOf(size), mimeType, is);
162
163 return toFileEntry(
164 cmisFolder.createDocument(properties, contentStream, null));
165 }
166 catch (PortalException pe) {
167 throw pe;
168 }
169 catch (SystemException se) {
170 throw se;
171 }
172 catch (Exception e) {
173 processException(e);
174
175 throw new RepositoryException(e);
176 }
177 }
178
179 @Override
180 public Folder addFolder(
181 long parentFolderId, String title, String description,
182 ServiceContext serviceContext)
183 throws PortalException, SystemException {
184
185 try {
186 Session session = getSession();
187
188 validateTitle(session, parentFolderId, title);
189
190 org.apache.chemistry.opencmis.client.api.Folder cmisFolder =
191 getCmisFolder(session, parentFolderId);
192
193 Map<String, Object> properties = new HashMap<String, Object>();
194
195 properties.put(PropertyIds.NAME, title);
196 properties.put(
197 PropertyIds.OBJECT_TYPE_ID, BaseTypeId.CMIS_FOLDER.value());
198
199 return toFolder(cmisFolder.createFolder(properties));
200 }
201 catch (PortalException pe) {
202 throw pe;
203 }
204 catch (SystemException se) {
205 throw se;
206 }
207 catch (Exception e) {
208 processException(e);
209
210 throw new RepositoryException(e);
211 }
212 }
213
214 @Override
215 public FileVersion cancelCheckOut(long fileEntryId) throws SystemException {
216 Document draftDocument = null;
217
218 try {
219 Session session = getSession();
220
221 String versionSeriesId = toFileEntryId(fileEntryId);
222
223 Document document = (Document)session.getObject(versionSeriesId);
224
225 document.refresh();
226
227 String versionSeriesCheckedOutId =
228 document.getVersionSeriesCheckedOutId();
229
230 if (Validator.isNotNull(versionSeriesCheckedOutId)) {
231 draftDocument = (Document)session.getObject(
232 versionSeriesCheckedOutId);
233
234 draftDocument.cancelCheckOut();
235
236 document = (Document)session.getObject(versionSeriesId);
237
238 document.refresh();
239 }
240 }
241 catch (Exception e) {
242 _log.error(
243 "Unable to cancel checkout for file entry with {fileEntryId=" +
244 fileEntryId + "}",
245 e);
246 }
247
248 if (draftDocument != null) {
249 return toFileVersion(draftDocument);
250 }
251
252 return null;
253 }
254
255 @Override
256 public void checkInFileEntry(
257 long fileEntryId, boolean major, String changeLog,
258 ServiceContext serviceContext) {
259
260 try {
261 clearManualCheckInRequired(fileEntryId, serviceContext);
262
263 Session session = getSession();
264
265 String versionSeriesId = toFileEntryId(fileEntryId);
266
267 Document document = (Document)session.getObject(versionSeriesId);
268
269 document.refresh();
270
271 String versionSeriesCheckedOutId =
272 document.getVersionSeriesCheckedOutId();
273
274 if (Validator.isNotNull(versionSeriesCheckedOutId)) {
275 if (!isSupportsMinorVersions()) {
276 major = true;
277 }
278
279 document = (Document)session.getObject(
280 versionSeriesCheckedOutId);
281
282 document.checkIn(major, null, null, changeLog);
283
284 document = (Document)session.getObject(versionSeriesId);
285
286 document.refresh();
287 }
288 }
289 catch (Exception e) {
290 _log.error(
291 "Unable to check in file entry with {fileEntryId=" +
292 fileEntryId + "}", e);
293 }
294 }
295
296 @Override
297 public void checkInFileEntry(
298 long fileEntryId, String lockUuid, ServiceContext serviceContext) {
299
300 checkInFileEntry(fileEntryId, false, StringPool.BLANK, serviceContext);
301 }
302
303 @Override
304 public FileEntry checkOutFileEntry(
305 long fileEntryId, ServiceContext serviceContext)
306 throws PortalException, SystemException {
307
308 try {
309 setManualCheckInRequired(fileEntryId, serviceContext);
310
311 Session session = getSession();
312
313 String versionSeriesId = toFileEntryId(fileEntryId);
314
315 Document document = (Document)session.getObject(versionSeriesId);
316
317 document.refresh();
318
319 document.checkOut();
320
321 document = (Document)session.getObject(versionSeriesId);
322
323 document.refresh();
324 }
325 catch (Exception e) {
326 _log.error(
327 "Unable checkout file entry with {fileEntryId=" + fileEntryId +
328 "}",
329 e);
330 }
331
332 return getFileEntry(fileEntryId);
333 }
334
335 @Override
336 public FileEntry checkOutFileEntry(
337 long fileEntryId, String owner, long expirationTime,
338 ServiceContext serviceContext) {
339
340 throw new UnsupportedOperationException();
341 }
342
343 @Override
344 public FileEntry copyFileEntry(
345 long groupId, long fileEntryId, long destFolderId,
346 ServiceContext serviceContext)
347 throws PortalException, SystemException {
348
349 try {
350 Session session = getSession();
351
352 Document document = getDocument(session, fileEntryId);
353
354 validateTitle(session, destFolderId, document.getName());
355
356 String destFolderObjectId = toFolderId(session, destFolderId);
357
358 Document newDocument = document.copy(
359 new ObjectIdImpl(destFolderObjectId));
360
361 return toFileEntry(newDocument);
362 }
363 catch (CmisObjectNotFoundException confe) {
364 throw new NoSuchFolderException(
365 "No CMIS folder with {folderId=" + destFolderId + "}", confe);
366 }
367 catch (PortalException pe) {
368 throw pe;
369 }
370 catch (SystemException se) {
371 throw se;
372 }
373 catch (Exception e) {
374 processException(e);
375
376 throw new RepositoryException(e);
377 }
378 }
379
380 @Override
381 public void deleteFileEntry(long fileEntryId)
382 throws PortalException, SystemException {
383
384 try {
385 Session session = getSession();
386
387 Document document = getDocument(session, fileEntryId);
388
389 deleteMappedFileEntry(document);
390
391 document.deleteAllVersions();
392 }
393 catch (PortalException pe) {
394 throw pe;
395 }
396 catch (SystemException se) {
397 throw se;
398 }
399 catch (Exception e) {
400 processException(e);
401
402 throw new RepositoryException(e);
403 }
404 }
405
406 @Override
407 public void deleteFolder(long folderId)
408 throws PortalException, SystemException {
409
410 try {
411 Session session = getSession();
412
413 org.apache.chemistry.opencmis.client.api.Folder cmisFolder =
414 getCmisFolder(session, folderId);
415
416 deleteMappedFolder(cmisFolder);
417
418 cmisFolder.deleteTree(true, UnfileObject.DELETE, false);
419 }
420 catch (PortalException pe) {
421 throw pe;
422 }
423 catch (SystemException se) {
424 throw se;
425 }
426 catch (Exception e) {
427 processException(e);
428
429 throw new RepositoryException(e);
430 }
431 }
432
433 @Override
434 public List<FileEntry> getFileEntries(
435 long folderId, int start, int end, OrderByComparator obc)
436 throws SystemException {
437
438 List<FileEntry> fileEntries = getFileEntries(folderId);
439
440 return subList(fileEntries, start, end, obc);
441 }
442
443 @Override
444 public List<FileEntry> getFileEntries(
445 long folderId, long fileEntryTypeId, int start, int end,
446 OrderByComparator obc) {
447
448 return new ArrayList<FileEntry>();
449 }
450
451 @Override
452 public List<FileEntry> getFileEntries(
453 long folderId, String[] mimeTypes, int start, int end,
454 OrderByComparator obc)
455 throws PortalException, SystemException {
456
457 Map<Long, List<FileEntry>> fileEntriesCache = _fileEntriesCache.get();
458
459 List<FileEntry> fileEntries = fileEntriesCache.get(folderId);
460
461 if ((fileEntries == null) || (mimeTypes != null)) {
462 fileEntries = new ArrayList<FileEntry>();
463
464 List<String> documentIds = getDocumentIds(
465 getSession(), folderId, mimeTypes);
466
467 for (String documentId : documentIds) {
468 FileEntry fileEntry = toFileEntry(documentId);
469
470 fileEntries.add(fileEntry);
471 }
472
473 if (mimeTypes == null) {
474 fileEntriesCache.put(folderId, fileEntries);
475 }
476 }
477
478 return subList(fileEntries, start, end, obc);
479 }
480
481 @Override
482 public int getFileEntriesCount(long folderId) throws SystemException {
483 List<FileEntry> fileEntries = getFileEntries(folderId);
484
485 return fileEntries.size();
486 }
487
488 @Override
489 public int getFileEntriesCount(long folderId, long fileEntryTypeId) {
490 List<FileEntry> fileEntries = getFileEntries(folderId, fileEntryTypeId);
491
492 return fileEntries.size();
493 }
494
495 @Override
496 public int getFileEntriesCount(long folderId, String[] mimeTypes)
497 throws PortalException, SystemException {
498
499 Session session = getSession();
500
501 List<String> documentIds = getDocumentIds(session, folderId, mimeTypes);
502
503 return documentIds.size();
504 }
505
506 @Override
507 public FileEntry getFileEntry(long fileEntryId)
508 throws PortalException, SystemException {
509
510 try {
511 Session session = getSession();
512
513 Document document = getDocument(session, fileEntryId);
514
515 return toFileEntry(document);
516 }
517 catch (PortalException pe) {
518 throw pe;
519 }
520 catch (SystemException se) {
521 throw se;
522 }
523 catch (Exception e) {
524 processException(e);
525
526 throw new RepositoryException(e);
527 }
528 }
529
530 @Override
531 public FileEntry getFileEntry(long folderId, String title)
532 throws PortalException, SystemException {
533
534 try {
535 Session session = getSession();
536
537 String objectId = getObjectId(session, folderId, true, title);
538
539 if (objectId != null) {
540 CmisObject cmisObject = session.getObject(objectId);
541
542 Document document = (Document)cmisObject;
543
544 return toFileEntry(document);
545 }
546 }
547 catch (CmisObjectNotFoundException confe) {
548 throw new NoSuchFileEntryException(
549 "No CMIS file entry with {folderId=" + folderId + ", title=" +
550 title + "}",
551 confe);
552 }
553 catch (PortalException pe) {
554 throw pe;
555 }
556 catch (SystemException se) {
557 throw se;
558 }
559 catch (Exception e) {
560 processException(e);
561
562 throw new RepositoryException(e);
563 }
564
565 throw new NoSuchFileEntryException(
566 "No CMIS file entry with {folderId=" + folderId + ", title=" +
567 title + "}");
568 }
569
570 @Override
571 public FileEntry getFileEntryByUuid(String uuid)
572 throws PortalException, SystemException {
573
574 try {
575 Session session = getSession();
576
577 RepositoryEntry repositoryEntry = RepositoryEntryUtil.findByUUID_G(
578 uuid, getGroupId());
579
580 String objectId = repositoryEntry.getMappedId();
581
582 return toFileEntry((Document)session.getObject(objectId));
583 }
584 catch (CmisObjectNotFoundException confe) {
585 throw new NoSuchFileEntryException(
586 "No CMIS file entry with {uuid=" + uuid + "}", confe);
587 }
588 catch (NoSuchRepositoryEntryException nsree) {
589 throw new NoSuchFileEntryException(nsree);
590 }
591 catch (SystemException se) {
592 throw se;
593 }
594 catch (Exception e) {
595 processException(e);
596
597 throw new RepositoryException(e);
598 }
599 }
600
601 @Override
602 public FileVersion getFileVersion(long fileVersionId)
603 throws PortalException, SystemException {
604
605 try {
606 Session session = getSession();
607
608 return getFileVersion(session, fileVersionId);
609 }
610 catch (PortalException pe) {
611 throw pe;
612 }
613 catch (SystemException se) {
614 throw se;
615 }
616 catch (Exception e) {
617 processException(e);
618
619 throw new RepositoryException(e);
620 }
621 }
622
623 @Override
624 public Folder getFolder(long folderId)
625 throws PortalException, SystemException {
626
627 try {
628 Session session = getSession();
629
630 return getFolder(session, folderId);
631 }
632 catch (PortalException pe) {
633 throw pe;
634 }
635 catch (SystemException se) {
636 throw se;
637 }
638 catch (Exception e) {
639 processException(e);
640
641 throw new RepositoryException(e);
642 }
643 }
644
645 @Override
646 public Folder getFolder(long parentFolderId, String title)
647 throws PortalException, SystemException {
648
649 try {
650 Session session = getSession();
651
652 String objectId = getObjectId(
653 session, parentFolderId, false, title);
654
655 if (objectId != null) {
656 CmisObject cmisObject = session.getObject(objectId);
657
658 return toFolder(
659 (org.apache.chemistry.opencmis.client.api.Folder)
660 cmisObject);
661 }
662 }
663 catch (CmisObjectNotFoundException confe) {
664 throw new NoSuchFolderException(
665 "No CMIS folder with {parentFolderId=" + parentFolderId +
666 ", title=" + title + "}",
667 confe);
668 }
669 catch (PortalException pe) {
670 throw pe;
671 }
672 catch (SystemException se) {
673 throw se;
674 }
675 catch (Exception e) {
676 processException(e);
677
678 throw new RepositoryException(e);
679 }
680
681 throw new NoSuchFolderException(
682 "No CMIS folder with {parentFolderId=" + parentFolderId +
683 ", title=" + title + "}");
684 }
685
686 @Override
687 public List<Folder> getFolders(
688 long parentFolderId, boolean includeMountfolders, int start,
689 int end, OrderByComparator obc)
690 throws PortalException, SystemException {
691
692 List<Folder> folders = getFolders(parentFolderId);
693
694 return subList(folders, start, end, obc);
695 }
696
697 @Override
698 public List<Object> getFoldersAndFileEntries(
699 long folderId, int start, int end, OrderByComparator obc)
700 throws SystemException {
701
702 List<Object> foldersAndFileEntries = getFoldersAndFileEntries(folderId);
703
704 return subList(foldersAndFileEntries, start, end, obc);
705 }
706
707 @Override
708 public List<Object> getFoldersAndFileEntries(
709 long folderId, String[] mimeTypes, int start, int end,
710 OrderByComparator obc)
711 throws PortalException, SystemException {
712
713 Map<Long, List<Object>> foldersAndFileEntriesCache =
714 _foldersAndFileEntriesCache.get();
715
716 List<Object> foldersAndFileEntries = foldersAndFileEntriesCache.get(
717 folderId);
718
719 if ((foldersAndFileEntries == null) || (mimeTypes != null)) {
720 foldersAndFileEntries = new ArrayList<Object>(getFolders(folderId));
721
722 List<FileEntry> fileEntries = getFileEntries(
723 folderId, mimeTypes, QueryUtil.ALL_POS, QueryUtil.ALL_POS,
724 null);
725
726 foldersAndFileEntries.addAll(fileEntries);
727
728 if (mimeTypes == null) {
729 foldersAndFileEntriesCache.put(folderId, foldersAndFileEntries);
730 }
731 }
732
733 return subList(foldersAndFileEntries, start, end, obc);
734 }
735
736 @Override
737 public int getFoldersAndFileEntriesCount(long folderId)
738 throws SystemException {
739
740 List<Object> foldersAndFileEntries = getFoldersAndFileEntries(folderId);
741
742 return foldersAndFileEntries.size();
743 }
744
745 @Override
746 public int getFoldersAndFileEntriesCount(long folderId, String[] mimeTypes)
747 throws PortalException, SystemException {
748
749 if (ArrayUtil.isNotEmpty(mimeTypes)) {
750 List<Folder> folders = getFolders(folderId);
751
752 Session session = getSession();
753
754 List<String> documentIds = getDocumentIds(
755 session, folderId, mimeTypes);
756
757 return folders.size() + documentIds.size();
758 }
759
760 List<Object> foldersAndFileEntries = getFoldersAndFileEntries(folderId);
761
762 return foldersAndFileEntries.size();
763 }
764
765 @Override
766 public int getFoldersCount(long parentFolderId, boolean includeMountfolders)
767 throws PortalException, SystemException {
768
769 List<Folder> folders = getFolders(parentFolderId);
770
771 return folders.size();
772 }
773
774 @Override
775 public int getFoldersFileEntriesCount(List<Long> folderIds, int status)
776 throws SystemException {
777
778 int count = 0;
779
780 for (long folderId : folderIds) {
781 List<FileEntry> fileEntries = getFileEntries(folderId);
782
783 count += fileEntries.size();
784 }
785
786 return count;
787 }
788
789 @Override
790 public String getLatestVersionId(String objectId) throws SystemException {
791 try {
792 Session session = getSession();
793
794 Document document = (Document)session.getObject(objectId);
795
796 List<Document> documentVersions = document.getAllVersions();
797
798 document = documentVersions.get(0);
799
800 return document.getId();
801 }
802 catch (Exception e) {
803 throw new RepositoryException(e);
804 }
805 }
806
807 @Override
808 public List<Folder> getMountFolders(
809 long parentFolderId, int start, int end, OrderByComparator obc) {
810
811 return new ArrayList<Folder>();
812 }
813
814 @Override
815 public int getMountFoldersCount(long parentFolderId) {
816 return 0;
817 }
818
819 @Override
820 public String getObjectName(String objectId)
821 throws PortalException, SystemException {
822
823 Session session = getSession();
824
825 CmisObject cmisObject = session.getObject(objectId);
826
827 return cmisObject.getName();
828 }
829
830 @Override
831 public List<String> getObjectPaths(String objectId)
832 throws PortalException, SystemException {
833
834 Session session = getSession();
835
836 CmisObject cmisObject = session.getObject(objectId);
837
838 if (cmisObject instanceof FileableCmisObject) {
839 FileableCmisObject fileableCmisObject =
840 (FileableCmisObject)cmisObject;
841
842 return fileableCmisObject.getPaths();
843 }
844
845 throw new RepositoryException(
846 "CMIS object is unfileable for id " + objectId);
847 }
848
849 public Session getSession() throws PortalException, SystemException {
850 Session session = getCachedSession();
851
852 if (session != null) {
853 return session;
854 }
855
856 SessionImpl sessionImpl =
857 (SessionImpl)_cmisRepositoryHandler.getSession();
858
859 session = sessionImpl.getSession();
860
861 setCachedSession(session);
862
863 return session;
864 }
865
866 @Override
867 public void getSubfolderIds(List<Long> folderIds, long folderId)
868 throws SystemException {
869
870 try {
871 List<Folder> subfolders = getFolders(
872 folderId, false, QueryUtil.ALL_POS, QueryUtil.ALL_POS, null);
873
874 getSubfolderIds(folderIds, subfolders, true);
875 }
876 catch (SystemException se) {
877 throw se;
878 }
879 catch (Exception e) {
880 throw new RepositoryException(e);
881 }
882 }
883
884 @Override
885 public List<Long> getSubfolderIds(long folderId, boolean recurse)
886 throws SystemException {
887
888 try {
889 List<Long> subfolderIds = new ArrayList<Long>();
890
891 List<Folder> subfolders = getFolders(
892 folderId, false, QueryUtil.ALL_POS, QueryUtil.ALL_POS, null);
893
894 getSubfolderIds(subfolderIds, subfolders, recurse);
895
896 return subfolderIds;
897 }
898 catch (SystemException se) {
899 throw se;
900 }
901 catch (Exception e) {
902 throw new RepositoryException(e);
903 }
904 }
905
906 @Override
907 public String[] getSupportedConfigurations() {
908 return _cmisRepositoryHandler.getSupportedConfigurations();
909 }
910
911 @Override
912 public String[][] getSupportedParameters() {
913 return _cmisRepositoryHandler.getSupportedParameters();
914 }
915
916 @Override
917 public void initRepository() throws PortalException, SystemException {
918 try {
919 _sessionKey =
920 Session.class.getName().concat(StringPool.POUND).concat(
921 String.valueOf(getRepositoryId()));
922
923 Session session = getSession();
924
925 session.getRepositoryInfo();
926 }
927 catch (PortalException pe) {
928 throw pe;
929 }
930 catch (SystemException se) {
931 throw se;
932 }
933 catch (Exception e) {
934 processException(e);
935
936 throw new RepositoryException(
937 "Unable to initialize CMIS session for repository with " +
938 "{repositoryId=" + getRepositoryId() + "}",
939 e);
940 }
941 }
942
943 @Override
944 public boolean isCancelCheckOutAllowable(String objectId)
945 throws PortalException, SystemException {
946
947 return isActionAllowable(objectId, Action.CAN_CANCEL_CHECK_OUT);
948 }
949
950 @Override
951 public boolean isCheckInAllowable(String objectId)
952 throws PortalException, SystemException {
953
954 return isActionAllowable(objectId, Action.CAN_CHECK_IN);
955 }
956
957 @Override
958 public boolean isCheckOutAllowable(String objectId)
959 throws PortalException, SystemException {
960
961 return isActionAllowable(objectId, Action.CAN_CHECK_OUT);
962 }
963
964 public boolean isDocumentRetrievableByVersionSeriesId() {
965 return _cmisRepositoryHandler.isDocumentRetrievableByVersionSeriesId();
966 }
967
968 public boolean isRefreshBeforePermissionCheck() {
969 return _cmisRepositoryHandler.isRefreshBeforePermissionCheck();
970 }
971
972 @Override
973 public boolean isSupportsMinorVersions()
974 throws PortalException, SystemException {
975
976 try {
977 Session session = getSession();
978
979 RepositoryInfo repositoryInfo = session.getRepositoryInfo();
980
981 String productName = repositoryInfo.getProductName();
982
983 return _cmisRepositoryHandler.isSupportsMinorVersions(productName);
984 }
985 catch (PortalException pe) {
986 throw pe;
987 }
988 catch (SystemException se) {
989 throw se;
990 }
991 catch (Exception e) {
992 processException(e);
993
994 throw new RepositoryException(e);
995 }
996 }
997
998 @Override
999 public Lock lockFolder(long folderId) {
1000 throw new UnsupportedOperationException();
1001 }
1002
1003 @Override
1004 public Lock lockFolder(
1005 long folderId, String owner, boolean inheritable, long expirationTime) {
1006
1007 throw new UnsupportedOperationException();
1008 }
1009
1010 @Override
1011 public FileEntry moveFileEntry(
1012 long fileEntryId, long newFolderId, ServiceContext serviceContext)
1013 throws PortalException, SystemException {
1014
1015 try {
1016 Session session = getSession();
1017
1018 String newFolderObjectId = toFolderId(session, newFolderId);
1019
1020 Document document = getDocument(session, fileEntryId);
1021
1022 validateTitle(session, newFolderId, document.getName());
1023
1024 String oldFolderObjectId = document.getParents().get(0).getId();
1025
1026 if (oldFolderObjectId.equals(newFolderObjectId)) {
1027 return toFileEntry(document);
1028 }
1029
1030 document = (Document)document.move(
1031 new ObjectIdImpl(oldFolderObjectId),
1032 new ObjectIdImpl(newFolderObjectId));
1033
1034 String versionSeriesId = toFileEntryId(fileEntryId);
1035
1036 String newObjectId = document.getVersionSeriesId();
1037
1038 if (!versionSeriesId.equals(newObjectId)) {
1039 document = (Document)session.getObject(newObjectId);
1040
1041 updateMappedId(fileEntryId, document.getVersionSeriesId());
1042 }
1043
1044 FileEntry fileEntry = toFileEntry(document);
1045
1046 document = null;
1047
1048 return fileEntry;
1049 }
1050 catch (CmisObjectNotFoundException confe) {
1051 throw new NoSuchFolderException(
1052 "No CMIS folder with {folderId=" + newFolderId + "}", confe);
1053 }
1054 catch (PortalException pe) {
1055 throw pe;
1056 }
1057 catch (SystemException se) {
1058 throw se;
1059 }
1060 catch (Exception e) {
1061 processException(e);
1062
1063 throw new RepositoryException(e);
1064 }
1065 }
1066
1067 @Override
1068 public Folder moveFolder(
1069 long folderId, long parentFolderId, ServiceContext serviceContext)
1070 throws PortalException, SystemException {
1071
1072 try {
1073 Session session = getSession();
1074
1075 org.apache.chemistry.opencmis.client.api.Folder cmisFolder =
1076 getCmisFolder(session, folderId);
1077
1078 validateTitle(session, parentFolderId, cmisFolder.getName());
1079
1080 org.apache.chemistry.opencmis.client.api.Folder parentCmisFolder =
1081 cmisFolder.getFolderParent();
1082
1083 if (parentCmisFolder == null) {
1084 throw new RepositoryException(
1085 "Unable to move CMIS root folder with {folderId=" +
1086 folderId + "}");
1087 }
1088
1089 String objectId = toFolderId(session, folderId);
1090
1091 String sourceFolderId = parentCmisFolder.getId();
1092
1093 String targetFolderId = toFolderId(session, parentFolderId);
1094
1095 if (!sourceFolderId.equals(targetFolderId) &&
1096 !targetFolderId.equals(objectId)) {
1097
1098 cmisFolder =
1099 (org.apache.chemistry.opencmis.client.api.Folder)
1100 cmisFolder.move(
1101 new ObjectIdImpl(sourceFolderId),
1102 new ObjectIdImpl(targetFolderId));
1103 }
1104
1105 return toFolder(cmisFolder);
1106 }
1107 catch (CmisObjectNotFoundException confe) {
1108 throw new NoSuchFolderException(
1109 "No CMIS folder with {folderId=" + parentFolderId + "}", confe);
1110 }
1111 catch (PortalException pe) {
1112 throw pe;
1113 }
1114 catch (SystemException se) {
1115 throw se;
1116 }
1117 catch (Exception e) {
1118 processException(e);
1119
1120 throw new RepositoryException(e);
1121 }
1122 }
1123
1124 @Override
1125 public Lock refreshFileEntryLock(
1126 String lockUuid, long companyId, long expirationTime) {
1127
1128 throw new UnsupportedOperationException();
1129 }
1130
1131 @Override
1132 public Lock refreshFolderLock(
1133 String lockUuid, long companyId, long expirationTime) {
1134
1135 throw new UnsupportedOperationException();
1136 }
1137
1138 @Override
1139 public void revertFileEntry(
1140 long fileEntryId, String version, ServiceContext serviceContext)
1141 throws PortalException, SystemException {
1142
1143 try {
1144 Session session = getSession();
1145
1146 Document document = getDocument(session, fileEntryId);
1147
1148 Document oldVersion = null;
1149
1150 List<Document> documentVersions = document.getAllVersions();
1151
1152 for (Document currentVersion : documentVersions) {
1153 String currentVersionLabel = currentVersion.getVersionLabel();
1154
1155 if (Validator.isNull(currentVersionLabel)) {
1156 currentVersionLabel = DLFileEntryConstants.VERSION_DEFAULT;
1157 }
1158
1159 if (currentVersionLabel.equals(version)) {
1160 oldVersion = currentVersion;
1161
1162 break;
1163 }
1164 }
1165
1166 String mimeType = oldVersion.getContentStreamMimeType();
1167 String changeLog = "Reverted to " + version;
1168 String title = oldVersion.getName();
1169 ContentStream contentStream = oldVersion.getContentStream();
1170
1171 updateFileEntry(
1172 fileEntryId, contentStream.getFileName(), mimeType, title,
1173 StringPool.BLANK, changeLog, true, contentStream.getStream(),
1174 contentStream.getLength(), serviceContext);
1175 }
1176 catch (PortalException pe) {
1177 throw pe;
1178 }
1179 catch (SystemException se) {
1180 throw se;
1181 }
1182 catch (Exception e) {
1183 processException(e);
1184
1185 throw new RepositoryException(e);
1186 }
1187 }
1188
1189 @Override
1190 public Hits search(long creatorUserId, int status, int start, int end) {
1191 throw new UnsupportedOperationException();
1192 }
1193
1194 @Override
1195 public Hits search(
1196 long creatorUserId, long folderId, String[] mimeTypes, int status,
1197 int start, int end) {
1198
1199 throw new UnsupportedOperationException();
1200 }
1201
1202 @Override
1203 public Hits search(SearchContext searchContext, Query query)
1204 throws SearchException {
1205
1206 try {
1207 QueryConfig queryConfig = searchContext.getQueryConfig();
1208
1209 queryConfig.setScoreEnabled(false);
1210
1211 return doSearch(searchContext, query);
1212 }
1213 catch (Exception e) {
1214 throw new SearchException(e);
1215 }
1216 }
1217
1218 public FileEntry toFileEntry(Document document)
1219 throws PortalException, SystemException {
1220
1221 return toFileEntry(document, false);
1222 }
1223
1224 @Override
1225 public FileEntry toFileEntry(String objectId)
1226 throws PortalException, SystemException {
1227
1228 return toFileEntry(objectId, false);
1229 }
1230
1231 public FileVersion toFileVersion(Document version) throws SystemException {
1232 Object[] ids = getRepositoryEntryIds(version.getId());
1233
1234 long fileVersionId = (Long)ids[0];
1235 String uuid = (String)ids[1];
1236
1237 return new CMISFileVersion(this, uuid, fileVersionId, version);
1238 }
1239
1240 public Folder toFolder(
1241 org.apache.chemistry.opencmis.client.api.Folder cmisFolder)
1242 throws SystemException {
1243
1244 Object[] ids = getRepositoryEntryIds(cmisFolder.getId());
1245
1246 long folderId = (Long)ids[0];
1247 String uuid = (String)ids[1];
1248
1249 return new CMISFolder(this, uuid, folderId, cmisFolder);
1250 }
1251
1252 @Override
1253 public Folder toFolder(String objectId)
1254 throws PortalException, SystemException {
1255
1256 try {
1257 Session session = getSession();
1258
1259 org.apache.chemistry.opencmis.client.api.Folder cmisFolder =
1260 (org.apache.chemistry.opencmis.client.api.Folder)
1261 session.getObject(objectId);
1262
1263 return toFolder(cmisFolder);
1264 }
1265 catch (CmisObjectNotFoundException confe) {
1266 throw new NoSuchFolderException(
1267 "No CMIS folder with {objectId=" + objectId + "}", confe);
1268 }
1269 catch (SystemException se) {
1270 throw se;
1271 }
1272 catch (Exception e) {
1273 processException(e);
1274
1275 throw new RepositoryException(e);
1276 }
1277 }
1278
1279 @Override
1280 public void unlockFolder(long folderId, String lockUuid) {
1281 throw new UnsupportedOperationException();
1282 }
1283
1284 @Override
1285 public FileEntry updateFileEntry(
1286 long fileEntryId, String sourceFileName, String mimeType,
1287 String title, String description, String changeLog,
1288 boolean majorVersion, InputStream is, long size,
1289 ServiceContext serviceContext)
1290 throws PortalException, SystemException {
1291
1292 Document document = null;
1293
1294 ObjectId checkOutDocumentObjectId = null;
1295
1296 try {
1297 Session session = getSession();
1298
1299 document = getDocument(session, fileEntryId);
1300
1301 String versionSeriesCheckedOutId =
1302 document.getVersionSeriesCheckedOutId();
1303
1304 if (Validator.isNotNull(versionSeriesCheckedOutId)) {
1305 document = (Document)session.getObject(
1306 versionSeriesCheckedOutId);
1307
1308 document.refresh();
1309 }
1310
1311 String currentTitle = document.getName();
1312
1313 AllowableActions allowableActions = document.getAllowableActions();
1314
1315 Set<Action> allowableActionsSet =
1316 allowableActions.getAllowableActions();
1317
1318 if (allowableActionsSet.contains(Action.CAN_CHECK_OUT)) {
1319 checkOutDocumentObjectId = document.checkOut();
1320
1321 document = (Document)session.getObject(
1322 checkOutDocumentObjectId);
1323 }
1324
1325 Map<String, Object> properties = null;
1326
1327 ContentStream contentStream = null;
1328
1329 if (Validator.isNotNull(title) && !title.equals(currentTitle)) {
1330 properties = new HashMap<String, Object>();
1331
1332 properties.put(PropertyIds.NAME, title);
1333 }
1334
1335 if (is != null) {
1336 contentStream = new ContentStreamImpl(
1337 sourceFileName, BigInteger.valueOf(size), mimeType, is);
1338 }
1339
1340 checkUpdatable(allowableActionsSet, properties, contentStream);
1341
1342 if (checkOutDocumentObjectId != null) {
1343 if (!isSupportsMinorVersions()) {
1344 majorVersion = true;
1345 }
1346
1347 document.checkIn(
1348 majorVersion, properties, contentStream, changeLog);
1349
1350 checkOutDocumentObjectId = null;
1351 }
1352 else {
1353 if (properties != null) {
1354 document = (Document)document.updateProperties(properties);
1355 }
1356
1357 if (contentStream != null) {
1358 document.setContentStream(contentStream, true, false);
1359 }
1360 }
1361
1362 String versionSeriesId = toFileEntryId(fileEntryId);
1363
1364 document = (Document)session.getObject(versionSeriesId);
1365
1366 return toFileEntry(document);
1367 }
1368 catch (PortalException pe) {
1369 throw pe;
1370 }
1371 catch (SystemException se) {
1372 throw se;
1373 }
1374 catch (Exception e) {
1375 processException(e);
1376
1377 throw new RepositoryException(e);
1378 }
1379 finally {
1380 if (checkOutDocumentObjectId != null) {
1381 document.cancelCheckOut();
1382 }
1383 }
1384 }
1385
1386 @Override
1387 public FileEntry updateFileEntry(
1388 String objectId, String mimeType, Map<String, Object> properties,
1389 InputStream is, String sourceFileName, long size,
1390 ServiceContext serviceContext)
1391 throws PortalException, SystemException {
1392
1393 try {
1394 Session session = getSession();
1395
1396 Document document = (Document)session.getObject(objectId);
1397
1398 AllowableActions allowableActions = document.getAllowableActions();
1399
1400 Set<Action> allowableActionsSet =
1401 allowableActions.getAllowableActions();
1402
1403 ContentStream contentStream = null;
1404
1405 if (is != null) {
1406 is = new Base64.InputStream(is, Base64.ENCODE);
1407
1408 contentStream = new ContentStreamImpl(
1409 sourceFileName, BigInteger.valueOf(size), mimeType, is);
1410 }
1411
1412 checkUpdatable(allowableActionsSet, properties, contentStream);
1413
1414 if (properties != null) {
1415 document = (Document)document.updateProperties(properties);
1416 }
1417
1418 if (contentStream != null) {
1419 document.setContentStream(contentStream, true, false);
1420 }
1421
1422 return toFileEntry(document);
1423 }
1424 catch (PortalException pe) {
1425 throw pe;
1426 }
1427 catch (SystemException se) {
1428 throw se;
1429 }
1430 catch (Exception e) {
1431 processException(e);
1432
1433 throw new RepositoryException(e);
1434 }
1435 }
1436
1437 @Override
1438 public Folder updateFolder(
1439 long folderId, String title, String description,
1440 ServiceContext serviceContext)
1441 throws PortalException, SystemException {
1442
1443 try {
1444 Session session = getSession();
1445
1446 String objectId = toFolderId(session, folderId);
1447
1448 org.apache.chemistry.opencmis.client.api.Folder cmisFolder =
1449 (org.apache.chemistry.opencmis.client.api.Folder)
1450 session.getObject(objectId);
1451
1452 String currentTitle = cmisFolder.getName();
1453
1454 Map<String, Object> properties = new HashMap<String, Object>();
1455
1456 if (Validator.isNotNull(title) && !title.equals(currentTitle)) {
1457 properties.put(PropertyIds.NAME, title);
1458 }
1459
1460 String newObjectId = cmisFolder.updateProperties(
1461 properties, true).getId();
1462
1463 if (!objectId.equals(newObjectId)) {
1464 cmisFolder =
1465 (org.apache.chemistry.opencmis.client.api.Folder)
1466 session.getObject(newObjectId);
1467
1468 updateMappedId(folderId, newObjectId);
1469 }
1470
1471 return toFolder(cmisFolder);
1472 }
1473 catch (CmisObjectNotFoundException confe) {
1474 throw new NoSuchFolderException(
1475 "No CMIS folder with {folderId=" + folderId + "}", confe);
1476 }
1477 catch (PortalException pe) {
1478 throw pe;
1479 }
1480 catch (SystemException se) {
1481 throw se;
1482 }
1483 catch (Exception e) {
1484 processException(e);
1485
1486 throw new RepositoryException(e);
1487 }
1488 }
1489
1490 @Override
1491 public boolean verifyFileEntryCheckOut(long fileEntryId, String lockUuid) {
1492 throw new UnsupportedOperationException();
1493 }
1494
1495 @Override
1496 public boolean verifyInheritableLock(long folderId, String lockUuid) {
1497 throw new UnsupportedOperationException();
1498 }
1499
1500 protected void cacheFoldersAndFileEntries(long folderId)
1501 throws SystemException {
1502
1503 try {
1504 Map<Long, List<Object>> foldersAndFileEntriesCache =
1505 _foldersAndFileEntriesCache.get();
1506
1507 if (foldersAndFileEntriesCache.containsKey(folderId)) {
1508 return;
1509 }
1510
1511 List<Object> foldersAndFileEntries = new ArrayList<Object>();
1512 List<Folder> folders = new ArrayList<Folder>();
1513 List<FileEntry> fileEntries = new ArrayList<FileEntry>();
1514
1515 Session session = getSession();
1516
1517 org.apache.chemistry.opencmis.client.api.Folder cmisParentFolder =
1518 getCmisFolder(session, folderId);
1519
1520 Folder parentFolder = toFolder(cmisParentFolder);
1521
1522 ItemIterable<CmisObject> cmisObjects =
1523 cmisParentFolder.getChildren();
1524
1525 for (CmisObject cmisObject : cmisObjects) {
1526 if (cmisObject instanceof
1527 org.apache.chemistry.opencmis.client.api.Folder) {
1528
1529 CMISFolder cmisFolder = (CMISFolder)toFolder(
1530 (org.apache.chemistry.opencmis.client.api.Folder)
1531 cmisObject);
1532
1533 cmisFolder.setParentFolder(parentFolder);
1534
1535 foldersAndFileEntries.add(cmisFolder);
1536 folders.add(cmisFolder);
1537 }
1538 else if (cmisObject instanceof Document) {
1539 CMISFileEntry cmisFileEntry = (CMISFileEntry)toFileEntry(
1540 (Document)cmisObject);
1541
1542 cmisFileEntry.setParentFolder(parentFolder);
1543
1544 foldersAndFileEntries.add(cmisFileEntry);
1545 fileEntries.add(cmisFileEntry);
1546 }
1547 }
1548
1549 foldersAndFileEntriesCache.put(folderId, foldersAndFileEntries);
1550
1551 Map<Long, List<Folder>> foldersCache = _foldersCache.get();
1552
1553 foldersCache.put(folderId, folders);
1554
1555 Map<Long, List<FileEntry>> fileEntriesCache =
1556 _fileEntriesCache.get();
1557
1558 fileEntriesCache.put(folderId, fileEntries);
1559 }
1560 catch (SystemException se) {
1561 throw se;
1562 }
1563 catch (Exception e) {
1564 throw new RepositoryException(e);
1565 }
1566 }
1567
1568 protected void checkUpdatable(
1569 Set<Action> allowableActionsSet, Map<String, Object> properties,
1570 ContentStream contentStream)
1571 throws PrincipalException {
1572
1573 if (properties != null) {
1574 if (!allowableActionsSet.contains(Action.CAN_UPDATE_PROPERTIES)) {
1575 throw new PrincipalException();
1576 }
1577 }
1578
1579 if (contentStream != null) {
1580 if (!allowableActionsSet.contains(Action.CAN_SET_CONTENT_STREAM)) {
1581 throw new PrincipalException();
1582 }
1583 }
1584 }
1585
1586 protected void deleteMappedFileEntry(Document document)
1587 throws SystemException {
1588
1589 if (PropsValues.DL_REPOSITORY_CMIS_DELETE_DEPTH == _DELETE_NONE) {
1590 return;
1591 }
1592
1593 List<Document> documentVersions = document.getAllVersions();
1594
1595 for (Document version : documentVersions) {
1596 try {
1597 RepositoryEntryUtil.removeByR_M(
1598 getRepositoryId(), version.getId());
1599 }
1600 catch (NoSuchRepositoryEntryException nsree) {
1601 }
1602 }
1603
1604 try {
1605 RepositoryEntryUtil.removeByR_M(
1606 getRepositoryId(), document.getId());
1607 }
1608 catch (NoSuchRepositoryEntryException nsree) {
1609 }
1610 }
1611
1612 protected void deleteMappedFolder(
1613 org.apache.chemistry.opencmis.client.api.Folder cmisFolder)
1614 throws SystemException {
1615
1616 if (PropsValues.DL_REPOSITORY_CMIS_DELETE_DEPTH == _DELETE_NONE) {
1617 return;
1618 }
1619
1620 ItemIterable<CmisObject> cmisObjects = cmisFolder.getChildren();
1621
1622 for (CmisObject cmisObject : cmisObjects) {
1623 if (cmisObject instanceof Document) {
1624 Document document = (Document)cmisObject;
1625
1626 deleteMappedFileEntry(document);
1627 }
1628 else if (cmisObject instanceof
1629 org.apache.chemistry.opencmis.client.api.Folder) {
1630
1631 org.apache.chemistry.opencmis.client.api.Folder cmisSubfolder =
1632 (org.apache.chemistry.opencmis.client.api.Folder)cmisObject;
1633
1634 try {
1635 RepositoryEntryUtil.removeByR_M(
1636 getRepositoryId(), cmisObject.getId());
1637
1638 if (PropsValues.DL_REPOSITORY_CMIS_DELETE_DEPTH ==
1639 _DELETE_DEEP) {
1640
1641 deleteMappedFolder(cmisSubfolder);
1642 }
1643 }
1644 catch (NoSuchRepositoryEntryException nsree) {
1645 }
1646 }
1647 }
1648 }
1649
1650 protected Hits doSearch(SearchContext searchContext, Query query)
1651 throws Exception {
1652
1653 long startTime = System.currentTimeMillis();
1654
1655 Session session = getSession();
1656
1657 RepositoryInfo repositoryInfo = session.getRepositoryInfo();
1658
1659 RepositoryCapabilities repositoryCapabilities =
1660 repositoryInfo.getCapabilities();
1661
1662 QueryConfig queryConfig = searchContext.getQueryConfig();
1663
1664 CapabilityQuery capabilityQuery =
1665 repositoryCapabilities.getQueryCapability();
1666
1667 queryConfig.setAttribute("capabilityQuery", capabilityQuery.value());
1668
1669 String queryString = CMISSearchQueryBuilderUtil.buildQuery(
1670 searchContext, query);
1671
1672 String productName = repositoryInfo.getProductName();
1673 String productVersion = repositoryInfo.getProductVersion();
1674
1675 if (productName.contains("Nuxeo") && productVersion.contains("5.4")) {
1676 queryString +=
1677 " AND (" + PropertyIds.IS_LATEST_VERSION + " = true)";
1678 }
1679
1680 if (_log.isDebugEnabled()) {
1681 _log.debug("CMIS search query: " + queryString);
1682 }
1683
1684 ItemIterable<QueryResult> queryResults = session.query(
1685 queryString, false);
1686
1687 int start = searchContext.getStart();
1688 int end = searchContext.getEnd();
1689
1690 if ((start == QueryUtil.ALL_POS) && (end == QueryUtil.ALL_POS)) {
1691 start = 0;
1692 }
1693
1694 int total = 0;
1695
1696 List<com.liferay.portal.kernel.search.Document> documents =
1697 new ArrayList<com.liferay.portal.kernel.search.Document>();
1698 List<String> snippets = new ArrayList<String>();
1699 List<Float> scores = new ArrayList<Float>();
1700
1701 for (QueryResult queryResult : queryResults) {
1702 total++;
1703
1704 if (total <= start) {
1705 continue;
1706 }
1707
1708 if ((total > end) && (end != QueryUtil.ALL_POS)) {
1709 continue;
1710 }
1711
1712 com.liferay.portal.kernel.search.Document document =
1713 new DocumentImpl();
1714
1715 String objectId = queryResult.getPropertyValueByQueryName(
1716 PropertyIds.OBJECT_ID);
1717
1718 if (_log.isDebugEnabled()) {
1719 _log.debug("Search result object ID " + objectId);
1720 }
1721
1722 FileEntry fileEntry = null;
1723
1724 try {
1725 fileEntry = toFileEntry(objectId, true);
1726 }
1727 catch (Exception e) {
1728 if (_log.isDebugEnabled()) {
1729 Throwable cause = e.getCause();
1730
1731 if (cause != null) {
1732 cause = cause.getCause();
1733 }
1734
1735 if (cause instanceof CmisObjectNotFoundException) {
1736 _log.debug(
1737 "Search result ignored for CMIS document which " +
1738 "has a version with an invalid object ID " +
1739 cause.getMessage());
1740 }
1741 else {
1742 _log.debug(
1743 "Search result ignored for invalid object ID", e);
1744 }
1745 }
1746
1747 total--;
1748
1749 continue;
1750 }
1751
1752 document.addKeyword(
1753 Field.ENTRY_CLASS_NAME, fileEntry.getModelClassName());
1754 document.addKeyword(
1755 Field.ENTRY_CLASS_PK, fileEntry.getFileEntryId());
1756 document.addKeyword(Field.TITLE, fileEntry.getTitle());
1757
1758 documents.add(document);
1759
1760 if (queryConfig.isScoreEnabled()) {
1761 Object scoreObj = queryResult.getPropertyValueByQueryName(
1762 "HITS");
1763
1764 if (scoreObj != null) {
1765 scores.add(Float.valueOf(scoreObj.toString()));
1766 }
1767 else {
1768 scores.add(1.0f);
1769 }
1770 }
1771 else {
1772 scores.add(1.0f);
1773 }
1774
1775 snippets.add(StringPool.BLANK);
1776 }
1777
1778 float searchTime =
1779 (float)(System.currentTimeMillis() - startTime) / Time.SECOND;
1780
1781 Hits hits = new HitsImpl();
1782
1783 hits.setDocs(
1784 documents.toArray(
1785 new com.liferay.portal.kernel.search.Document[
1786 documents.size()]));
1787 hits.setLength(total);
1788 hits.setQuery(query);
1789 hits.setQueryTerms(new String[0]);
1790 hits.setScores(scores.toArray(new Float[scores.size()]));
1791 hits.setSearchTime(searchTime);
1792 hits.setSnippets(snippets.toArray(new String[snippets.size()]));
1793 hits.setStart(startTime);
1794
1795 return hits;
1796 }
1797
1798 protected Session getCachedSession() {
1799 HttpSession httpSession = PortalSessionThreadLocal.getHttpSession();
1800
1801 if (httpSession == null) {
1802 return null;
1803 }
1804
1805 TransientValue<Session> transientValue =
1806 (TransientValue<Session>)httpSession.getAttribute(_sessionKey);
1807
1808 if (transientValue == null) {
1809 return null;
1810 }
1811
1812 return transientValue.getValue();
1813 }
1814
1815 protected org.apache.chemistry.opencmis.client.api.Folder getCmisFolder(
1816 Session session, long folderId)
1817 throws PortalException, SystemException {
1818
1819 Folder folder = getFolder(session, folderId);
1820
1821 org.apache.chemistry.opencmis.client.api.Folder cmisFolder =
1822 (org.apache.chemistry.opencmis.client.api.Folder)folder.getModel();
1823
1824 return cmisFolder;
1825 }
1826
1827 protected List<String> getCmisFolderIds(Session session, long folderId)
1828 throws PortalException, SystemException {
1829
1830 StringBundler sb = new StringBundler(4);
1831
1832 sb.append("SELECT cmis:objectId FROM cmis:folder");
1833
1834 if (folderId > 0) {
1835 sb.append(" WHERE IN_FOLDER(");
1836
1837 String objectId = toFolderId(session, folderId);
1838
1839 sb.append(StringUtil.quote(objectId));
1840 sb.append(StringPool.CLOSE_PARENTHESIS);
1841 }
1842
1843 String query = sb.toString();
1844
1845 if (_log.isDebugEnabled()) {
1846 _log.debug("Calling query " + query);
1847 }
1848
1849 ItemIterable<QueryResult> queryResults = session.query(
1850 query, isAllVersionsSearchableSupported(session));
1851
1852 List<String> cmsFolderIds = new ArrayList<String>();
1853
1854 for (QueryResult queryResult : queryResults) {
1855 PropertyData<String> propertyData = queryResult.getPropertyById(
1856 PropertyIds.OBJECT_ID);
1857
1858 List<String> values = propertyData.getValues();
1859
1860 String value = values.get(0);
1861
1862 cmsFolderIds.add(value);
1863 }
1864
1865 return cmsFolderIds;
1866 }
1867
1868 protected Document getDocument(Session session, long fileEntryId)
1869 throws PortalException, SystemException {
1870
1871 try {
1872 String versionSeriesId = toFileEntryId(fileEntryId);
1873
1874 Document document = (Document)session.getObject(versionSeriesId);
1875
1876 return document;
1877 }
1878 catch (CmisObjectNotFoundException confe) {
1879 throw new NoSuchFileEntryException(
1880 "No CMIS file entry with {fileEntryId=" + fileEntryId+ "}",
1881 confe);
1882 }
1883 }
1884
1885 protected List<String> getDocumentIds(
1886 Session session, long folderId, String[] mimeTypes)
1887 throws PortalException, SystemException {
1888
1889 StringBundler sb = new StringBundler();
1890
1891 sb.append("SELECT cmis:objectId FROM cmis:document");
1892
1893 if (ArrayUtil.isNotEmpty(mimeTypes)) {
1894 sb.append(" WHERE cmis:contentStreamMimeType IN (");
1895
1896 for (int i = 0; i < mimeTypes.length; i++) {
1897 sb.append(StringUtil.quote(mimeTypes[i]));
1898
1899 if ((i + 1) < mimeTypes.length) {
1900 sb.append(", ");
1901 }
1902 }
1903
1904 sb.append(StringPool.CLOSE_PARENTHESIS);
1905 }
1906
1907 if (folderId > 0) {
1908 if (ArrayUtil.isNotEmpty(mimeTypes)) {
1909 sb.append(" AND ");
1910 }
1911 else {
1912 sb.append(" WHERE ");
1913 }
1914
1915 sb.append("IN_FOLDER(");
1916
1917 String objectId = toFolderId(session, folderId);
1918
1919 sb.append(StringUtil.quote(objectId));
1920 sb.append(StringPool.CLOSE_PARENTHESIS);
1921 }
1922
1923 String query = sb.toString();
1924
1925 if (_log.isDebugEnabled()) {
1926 _log.debug("Calling query " + query);
1927 }
1928
1929 ItemIterable<QueryResult> queryResults = session.query(query, false);
1930
1931 List<String> cmisDocumentIds = new ArrayList<String>();
1932
1933 for (QueryResult queryResult : queryResults) {
1934 String objectId = queryResult.getPropertyValueByQueryName(
1935 PropertyIds.OBJECT_ID);
1936
1937 cmisDocumentIds.add(objectId);
1938 }
1939
1940 return cmisDocumentIds;
1941 }
1942
1943 protected List<FileEntry> getFileEntries(long folderId)
1944 throws SystemException {
1945
1946 cacheFoldersAndFileEntries(folderId);
1947
1948 Map<Long, List<FileEntry>> fileEntriesCache = _fileEntriesCache.get();
1949
1950 return fileEntriesCache.get(folderId);
1951 }
1952
1953 protected List<FileEntry> getFileEntries(long folderId, long repositoryId) {
1954 return new ArrayList<FileEntry>();
1955 }
1956
1957 protected FileVersion getFileVersion(Session session, long fileVersionId)
1958 throws PortalException, SystemException {
1959
1960 try {
1961 String objectId = toFileVersionId(fileVersionId);
1962
1963 return toFileVersion((Document)session.getObject(objectId));
1964 }
1965 catch (CmisObjectNotFoundException confe) {
1966 throw new NoSuchFileVersionException(
1967 "No CMIS file version with {fileVersionId=" + fileVersionId +
1968 "}",
1969 confe);
1970 }
1971 }
1972
1973 protected Folder getFolder(Session session, long folderId)
1974 throws PortalException, SystemException {
1975
1976 try {
1977 String objectId = toFolderId(session, folderId);
1978
1979 CmisObject cmisObject = session.getObject(objectId);
1980
1981 return (Folder)toFolderOrFileEntry(cmisObject);
1982 }
1983 catch (CmisObjectNotFoundException confe) {
1984 throw new NoSuchFolderException(
1985 "No CMIS folder with {folderId=" + folderId + "}", confe);
1986 }
1987 }
1988
1989 protected List<Folder> getFolders(long parentFolderId)
1990 throws PortalException, SystemException {
1991
1992 Map<Long, List<Folder>> foldersCache = _foldersCache.get();
1993
1994 List<Folder> folders = foldersCache.get(parentFolderId);
1995
1996 if (folders == null) {
1997 List<String> folderIds = getCmisFolderIds(
1998 getSession(), parentFolderId);
1999
2000 folders = new ArrayList<Folder>(folderIds.size());
2001
2002 for (String folderId : folderIds) {
2003 folders.add(toFolder(folderId));
2004 }
2005
2006 foldersCache.put(parentFolderId, folders);
2007 }
2008
2009 return folders;
2010 }
2011
2012 protected List<Object> getFoldersAndFileEntries(long folderId)
2013 throws SystemException {
2014
2015 cacheFoldersAndFileEntries(folderId);
2016
2017 Map<Long, List<Object>> foldersAndFileEntriesCache =
2018 _foldersAndFileEntriesCache.get();
2019
2020 return foldersAndFileEntriesCache.get(folderId);
2021 }
2022
2023 protected String getObjectId(
2024 Session session, long folderId, boolean fileEntry, String name)
2025 throws PortalException, SystemException {
2026
2027 String objectId = toFolderId(session, folderId);
2028
2029 StringBundler sb = new StringBundler(7);
2030
2031 sb.append("SELECT cmis:objectId FROM ");
2032
2033 if (fileEntry) {
2034 sb.append("cmis:document ");
2035 }
2036 else {
2037 sb.append("cmis:folder ");
2038 }
2039
2040 sb.append("WHERE cmis:name = '");
2041 sb.append(name);
2042 sb.append("' AND IN_FOLDER('");
2043 sb.append(objectId);
2044 sb.append("')");
2045
2046 String query = sb.toString();
2047
2048 if (_log.isDebugEnabled()) {
2049 _log.debug("Calling query " + query);
2050 }
2051
2052 ItemIterable<QueryResult> queryResults = session.query(query, false);
2053
2054 Iterator<QueryResult> itr = queryResults.iterator();
2055
2056 if (itr.hasNext()) {
2057 QueryResult queryResult = itr.next();
2058
2059 PropertyData<String> propertyData = queryResult.getPropertyById(
2060 PropertyIds.OBJECT_ID);
2061
2062 List<String> values = propertyData.getValues();
2063
2064 return values.get(0);
2065 }
2066
2067 return null;
2068 }
2069
2070 protected void getSubfolderIds(
2071 List<Long> subfolderIds, List<Folder> subfolders, boolean recurse)
2072 throws PortalException, SystemException {
2073
2074 for (Folder subfolder : subfolders) {
2075 long subfolderId = subfolder.getFolderId();
2076
2077 subfolderIds.add(subfolderId);
2078
2079 if (recurse) {
2080 List<Folder> subSubFolders = getFolders(
2081 subfolderId, false, QueryUtil.ALL_POS, QueryUtil.ALL_POS,
2082 null);
2083
2084 getSubfolderIds(subfolderIds, subSubFolders, recurse);
2085 }
2086 }
2087 }
2088
2089 protected boolean isActionAllowable(String objectId, Action action)
2090 throws PortalException, SystemException {
2091
2092 Session session = getSession();
2093
2094 Document document = (Document)session.getObject(objectId);
2095
2096 AllowableActions allowableActions = document.getAllowableActions();
2097
2098 Set<Action> allowableActionsSet =
2099 allowableActions.getAllowableActions();
2100
2101 if (allowableActionsSet.contains(action)) {
2102 return true;
2103 }
2104 else {
2105 return false;
2106 }
2107 }
2108
2109 protected boolean isAllVersionsSearchableSupported(Session session) {
2110 RepositoryInfo repositoryInfo = session.getRepositoryInfo();
2111
2112 RepositoryCapabilities repositoryCapabilities =
2113 repositoryInfo.getCapabilities();
2114
2115 return repositoryCapabilities.isAllVersionsSearchableSupported();
2116 }
2117
2118 protected void processException(Exception e) throws PortalException {
2119 if ((e instanceof CmisRuntimeException &&
2120 e.getMessage().contains("authorized")) ||
2121 (e instanceof CmisPermissionDeniedException)) {
2122
2123 String message = e.getMessage();
2124
2125 try {
2126 message =
2127 "Unable to login with user " +
2128 _cmisRepositoryHandler.getLogin();
2129 }
2130 catch (Exception e2) {
2131 }
2132
2133 throw new PrincipalException(message, e);
2134 }
2135 }
2136
2137 protected void setCachedSession(Session session) {
2138 HttpSession httpSession = PortalSessionThreadLocal.getHttpSession();
2139
2140 if (httpSession == null) {
2141 if (_log.isWarnEnabled()) {
2142 _log.warn("Unable to get HTTP session");
2143 }
2144
2145 return;
2146 }
2147
2148 httpSession.setAttribute(
2149 _sessionKey, new TransientValue<Session>(session));
2150 }
2151
2152 protected <E> List<E> subList(
2153 List<E> list, int start, int end, OrderByComparator obc) {
2154
2155 if ((obc != null) &&
2156 ((obc instanceof RepositoryModelCreateDateComparator) ||
2157 (obc instanceof RepositoryModelModifiedDateComparator) ||
2158 (obc instanceof RepositoryModelNameComparator) ||
2159 (obc instanceof RepositoryModelSizeComparator))) {
2160
2161 list = ListUtil.sort(list, obc);
2162 }
2163
2164 return ListUtil.subList(list, start, end);
2165 }
2166
2167 protected FileEntry toFileEntry(Document document, boolean strict)
2168 throws PortalException, SystemException {
2169
2170 Object[] ids = null;
2171
2172 if (isDocumentRetrievableByVersionSeriesId()) {
2173 ids = getRepositoryEntryIds(document.getVersionSeriesId());
2174 }
2175 else {
2176 ids = getRepositoryEntryIds(document.getId());
2177 }
2178
2179 long fileEntryId = (Long)ids[0];
2180 String uuid = (String)ids[1];
2181
2182 FileEntry fileEntry = new CMISFileEntry(
2183 this, uuid, fileEntryId, document);
2184
2185 FileVersion fileVersion = null;
2186
2187 try {
2188 fileVersion = fileEntry.getFileVersion();
2189 }
2190 catch (Exception e) {
2191 if (strict) {
2192 if ((Boolean)ids[2]) {
2193 RepositoryEntryUtil.remove(fileEntryId);
2194 }
2195
2196 if (e instanceof CmisObjectNotFoundException) {
2197 throw new NoSuchFileVersionException(
2198 "No CMIS file version with CMIS file entry {objectId=" +
2199 document.getId() + "}",
2200 e);
2201 }
2202 else if (e instanceof SystemException) {
2203 throw (SystemException)e;
2204 }
2205 else {
2206 processException(e);
2207
2208 throw new RepositoryException(e);
2209 }
2210 }
2211 else {
2212 _log.error("Unable to update asset", e);
2213 }
2214 }
2215
2216 dlAppHelperLocalService.checkAssetEntry(
2217 PrincipalThreadLocal.getUserId(), fileEntry, fileVersion);
2218
2219 return fileEntry;
2220 }
2221
2222 protected FileEntry toFileEntry(String objectId, boolean strict)
2223 throws PortalException, SystemException {
2224
2225 try {
2226 Session session = getSession();
2227
2228 Document document = (Document)session.getObject(objectId);
2229
2230 return toFileEntry(document, strict);
2231 }
2232 catch (CmisObjectNotFoundException confe) {
2233 throw new NoSuchFileEntryException(
2234 "No CMIS file entry with {objectId=" + objectId + "}", confe);
2235 }
2236 catch (SystemException se) {
2237 throw se;
2238 }
2239 catch (Exception e) {
2240 processException(e);
2241
2242 throw new RepositoryException(e);
2243 }
2244 }
2245
2246 protected String toFileEntryId(long fileEntryId)
2247 throws PortalException, SystemException {
2248
2249 RepositoryEntry repositoryEntry = RepositoryEntryUtil.fetchByPrimaryKey(
2250 fileEntryId);
2251
2252 if (repositoryEntry == null) {
2253 throw new NoSuchFileEntryException(
2254 "No CMIS file entry with {fileEntryId=" + fileEntryId + "}");
2255 }
2256
2257 return repositoryEntry.getMappedId();
2258 }
2259
2260 protected String toFileVersionId(long fileVersionId)
2261 throws PortalException, SystemException {
2262
2263 RepositoryEntry repositoryEntry = RepositoryEntryUtil.fetchByPrimaryKey(
2264 fileVersionId);
2265
2266 if (repositoryEntry == null) {
2267 throw new NoSuchFileVersionException(
2268 "No CMIS file version with {fileVersionId=" + fileVersionId +
2269 "}");
2270 }
2271
2272 return repositoryEntry.getMappedId();
2273 }
2274
2275 protected String toFolderId(Session session, long folderId)
2276 throws PortalException, SystemException {
2277
2278 RepositoryEntry repositoryEntry = RepositoryEntryUtil.fetchByPrimaryKey(
2279 folderId);
2280
2281 if (repositoryEntry != null) {
2282 return repositoryEntry.getMappedId();
2283 }
2284
2285 DLFolder dlFolder = DLFolderUtil.fetchByPrimaryKey(folderId);
2286
2287 if (dlFolder == null) {
2288 throw new NoSuchFolderException(
2289 "No CMIS folder with {folderId=" + folderId + "}");
2290 }
2291 else if (!dlFolder.isMountPoint()) {
2292 throw new RepositoryException(
2293 "CMIS repository should not be used with {folderId=" +
2294 folderId + "}");
2295 }
2296
2297 RepositoryInfo repositoryInfo = session.getRepositoryInfo();
2298
2299 String rootFolderId = repositoryInfo.getRootFolderId();
2300
2301 repositoryEntry = RepositoryEntryUtil.fetchByR_M(
2302 getRepositoryId(), rootFolderId);
2303
2304 if (repositoryEntry == null) {
2305 repositoryEntry =
2306 RepositoryEntryLocalServiceUtil.addRepositoryEntry(
2307 dlFolder.getUserId(), getGroupId(), getRepositoryId(),
2308 rootFolderId, new ServiceContext());
2309 }
2310
2311 return repositoryEntry.getMappedId();
2312 }
2313
2314 protected Object toFolderOrFileEntry(CmisObject cmisObject)
2315 throws PortalException, SystemException {
2316
2317 if (cmisObject instanceof Document) {
2318 FileEntry fileEntry = toFileEntry((Document)cmisObject);
2319
2320 return fileEntry;
2321 }
2322 else if (cmisObject instanceof
2323 org.apache.chemistry.opencmis.client.api.Folder) {
2324
2325 org.apache.chemistry.opencmis.client.api.Folder cmisFolder =
2326 (org.apache.chemistry.opencmis.client.api.Folder)cmisObject;
2327
2328 Folder folder = toFolder(cmisFolder);
2329
2330 return folder;
2331 }
2332 else {
2333 return null;
2334 }
2335 }
2336
2337 protected void updateMappedId(long repositoryEntryId, String mappedId)
2338 throws PortalException, SystemException {
2339
2340 RepositoryEntry repositoryEntry = RepositoryEntryUtil.findByPrimaryKey(
2341 repositoryEntryId);
2342
2343 if (!mappedId.equals(repositoryEntry.getMappedId())) {
2344 RepositoryEntryLocalServiceUtil.updateRepositoryEntry(
2345 repositoryEntryId, mappedId);
2346 }
2347 }
2348
2349 protected void validateTitle(Session session, long folderId, String title)
2350 throws PortalException, SystemException {
2351
2352 String objectId = getObjectId(session, folderId, true, title);
2353
2354 if (objectId != null) {
2355 throw new DuplicateFileException(title);
2356 }
2357
2358 objectId = getObjectId(session, folderId, false, title);
2359
2360 if (objectId != null) {
2361 throw new DuplicateFolderNameException(title);
2362 }
2363 }
2364
2365 private static final int _DELETE_DEEP = -1;
2366
2367 private static final int _DELETE_NONE = 0;
2368
2369 private static Log _log = LogFactoryUtil.getLog(CMISRepository.class);
2370
2371 private static ThreadLocal<Map<Long, List<FileEntry>>> _fileEntriesCache =
2372 new AutoResetThreadLocal<Map<Long, List<FileEntry>>>(
2373 CMISRepository.class + "._fileEntriesCache",
2374 new HashMap<Long, List<FileEntry>>());
2375 private static ThreadLocal<Map<Long, List<Object>>>
2376 _foldersAndFileEntriesCache =
2377 new AutoResetThreadLocal<Map<Long, List<Object>>>(
2378 CMISRepository.class + "._foldersAndFileEntriesCache",
2379 new HashMap<Long, List<Object>>());
2380 private static ThreadLocal<Map<Long, List<Folder>>> _foldersCache =
2381 new AutoResetThreadLocal<Map<Long, List<Folder>>>(
2382 CMISRepository.class + "._foldersCache",
2383 new HashMap<Long, List<Folder>>());
2384
2385 private CMISRepositoryHandler _cmisRepositoryHandler;
2386 private String _sessionKey;
2387
2388 }