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