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