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