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