This project has retired. For details please refer to its
Attic page.
JcrRepository xref
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.chemistry.opencmis.jcr;
20
21 import org.apache.chemistry.opencmis.commons.PropertyIds;
22 import org.apache.chemistry.opencmis.commons.data.AllowableActions;
23 import org.apache.chemistry.opencmis.commons.data.ContentStream;
24 import org.apache.chemistry.opencmis.commons.data.FailedToDeleteData;
25 import org.apache.chemistry.opencmis.commons.data.ObjectData;
26 import org.apache.chemistry.opencmis.commons.data.ObjectInFolderContainer;
27 import org.apache.chemistry.opencmis.commons.data.ObjectInFolderData;
28 import org.apache.chemistry.opencmis.commons.data.ObjectInFolderList;
29 import org.apache.chemistry.opencmis.commons.data.ObjectList;
30 import org.apache.chemistry.opencmis.commons.data.ObjectParentData;
31 import org.apache.chemistry.opencmis.commons.data.Properties;
32 import org.apache.chemistry.opencmis.commons.data.RepositoryInfo;
33 import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
34 import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionContainer;
35 import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionList;
36 import org.apache.chemistry.opencmis.commons.enums.CapabilityAcl;
37 import org.apache.chemistry.opencmis.commons.enums.CapabilityChanges;
38 import org.apache.chemistry.opencmis.commons.enums.CapabilityContentStreamUpdates;
39 import org.apache.chemistry.opencmis.commons.enums.CapabilityJoin;
40 import org.apache.chemistry.opencmis.commons.enums.CapabilityQuery;
41 import org.apache.chemistry.opencmis.commons.enums.CapabilityRenditions;
42 import org.apache.chemistry.opencmis.commons.enums.VersioningState;
43 import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
44 import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
45 import org.apache.chemistry.opencmis.commons.exceptions.CmisNameConstraintViolationException;
46 import org.apache.chemistry.opencmis.commons.exceptions.CmisNotSupportedException;
47 import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
48 import org.apache.chemistry.opencmis.commons.exceptions.CmisPermissionDeniedException;
49 import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
50 import org.apache.chemistry.opencmis.commons.exceptions.CmisUpdateConflictException;
51 import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectInFolderContainerImpl;
52 import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectInFolderDataImpl;
53 import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectInFolderListImpl;
54 import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectListImpl;
55 import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectParentDataImpl;
56 import org.apache.chemistry.opencmis.commons.impl.dataobjects.RepositoryCapabilitiesImpl;
57 import org.apache.chemistry.opencmis.commons.impl.dataobjects.RepositoryInfoImpl;
58 import org.apache.chemistry.opencmis.commons.server.ObjectInfoHandler;
59 import org.apache.chemistry.opencmis.commons.spi.Holder;
60 import org.apache.chemistry.opencmis.jcr.query.QueryTranslator;
61 import org.apache.chemistry.opencmis.jcr.type.JcrDocumentTypeHandler;
62 import org.apache.chemistry.opencmis.jcr.type.JcrFolderTypeHandler;
63 import org.apache.chemistry.opencmis.jcr.type.JcrTypeHandlerManager;
64 import org.apache.chemistry.opencmis.jcr.util.Util;
65 import org.apache.commons.logging.Log;
66 import org.apache.commons.logging.LogFactory;
67
68 import javax.jcr.Credentials;
69 import javax.jcr.ItemNotFoundException;
70 import javax.jcr.LoginException;
71 import javax.jcr.NoSuchWorkspaceException;
72 import javax.jcr.Node;
73 import javax.jcr.NodeIterator;
74 import javax.jcr.PathNotFoundException;
75 import javax.jcr.Repository;
76 import javax.jcr.RepositoryException;
77 import javax.jcr.Session;
78 import javax.jcr.query.Query;
79 import javax.jcr.query.QueryManager;
80 import javax.jcr.query.QueryResult;
81 import java.math.BigInteger;
82 import java.util.ArrayList;
83 import java.util.Collections;
84 import java.util.HashSet;
85 import java.util.Iterator;
86 import java.util.List;
87 import java.util.Set;
88
89
90
91
92 public class JcrRepository {
93 private static final Log log = LogFactory.getLog(JcrRepository.class);
94
95 private final Repository repository;
96 private final JcrTypeManager typeManager;
97 private final PathManager pathManager;
98 private final JcrTypeHandlerManager typeHandlerManager;
99
100
101
102
103
104
105
106
107
108 public JcrRepository(Repository repository, PathManager pathManager, JcrTypeManager typeManager, JcrTypeHandlerManager typeHandlerManager) {
109 this.repository = repository;
110 this.typeManager = typeManager;
111 this.typeHandlerManager = typeHandlerManager;
112 this.pathManager = pathManager;
113 }
114
115
116
117
118
119
120
121
122
123
124
125 public Session login(Credentials credentials, String workspaceName) {
126 try {
127 return repository.login(credentials, workspaceName);
128 }
129 catch (LoginException e) {
130 log.debug(e.getMessage(), e);
131 throw new CmisPermissionDeniedException(e.getMessage(), e);
132 }
133 catch (NoSuchWorkspaceException e) {
134 log.debug(e.getMessage(), e);
135 throw new CmisObjectNotFoundException(e.getMessage(), e);
136 }
137 catch (RepositoryException e) {
138 log.debug(e.getMessage(), e);
139 throw new CmisRuntimeException(e.getMessage(), e);
140 }
141 }
142
143
144
145
146 public RepositoryInfo getRepositoryInfo(Session session) {
147 log.debug("getRepositoryInfo");
148
149 return compileRepositoryInfo(session.getWorkspace().getName());
150 }
151
152
153
154
155 public List<RepositoryInfo> getRepositoryInfos(Session session) {
156 try {
157 ArrayList<RepositoryInfo> infos = new ArrayList<RepositoryInfo>();
158 for (String wspName : session.getWorkspace().getAccessibleWorkspaceNames()) {
159 infos.add(compileRepositoryInfo(wspName));
160 }
161
162 return infos;
163 }
164 catch (RepositoryException e) {
165 log.debug(e.getMessage(), e);
166 throw new CmisRuntimeException(e.getMessage(), e);
167 }
168 }
169
170
171
172
173 public TypeDefinitionList getTypeChildren(Session session, String typeId, boolean includePropertyDefinitions,
174 BigInteger maxItems, BigInteger skipCount) {
175
176 log.debug("getTypesChildren");
177 return typeManager.getTypeChildren(typeId, includePropertyDefinitions, maxItems, skipCount);
178 }
179
180
181
182
183 public TypeDefinition getTypeDefinition(Session session, String typeId) {
184 log.debug("getTypeDefinition");
185
186 TypeDefinition type = typeManager.getType(typeId);
187 if (type == null) {
188 throw new CmisObjectNotFoundException("Type '" + typeId + "' is unknown!");
189 }
190
191 return JcrTypeManager.copyTypeDefinition(type);
192 }
193
194
195
196
197 public List<TypeDefinitionContainer> getTypesDescendants(Session session, String typeId, BigInteger depth,
198 Boolean includePropertyDefinitions) {
199
200 log.debug("getTypesDescendants");
201 return typeManager.getTypesDescendants(typeId, depth, includePropertyDefinitions);
202 }
203
204
205
206
207 public String createDocument(Session session, Properties properties, String folderId, ContentStream contentStream,
208 VersioningState versioningState) {
209
210 log.debug("createDocument");
211
212
213 if (properties == null || properties.getProperties() == null) {
214 throw new CmisInvalidArgumentException("Properties must be set!");
215 }
216
217
218 String typeId = PropertyHelper.getTypeId(properties);
219 TypeDefinition type = typeManager.getType(typeId);
220 if (type == null) {
221 throw new CmisObjectNotFoundException("Type '" + typeId + "' is unknown!");
222 }
223
224 boolean isVersionable = JcrTypeManager.isVersionable(type);
225 if (!isVersionable && versioningState != VersioningState.NONE) {
226 throw new CmisConstraintException("Versioning not supported for " + typeId);
227 }
228
229 if (isVersionable && versioningState == VersioningState.NONE) {
230 throw new CmisConstraintException("Versioning required for " + typeId);
231 }
232
233
234 String name = PropertyHelper.getStringProperty(properties, PropertyIds.NAME);
235 if (!JcrConverter.isValidJcrName(name)) {
236 throw new CmisNameConstraintViolationException("Name is not valid: " + name);
237 }
238
239
240 JcrFolder parent = getJcrNode(session, folderId).asFolder();
241 JcrDocumentTypeHandler typeHandler = typeHandlerManager.getDocumentTypeHandler(typeId);
242 JcrNode jcrNode = typeHandler.createDocument(parent, name, properties, contentStream, versioningState);
243 return jcrNode.getId();
244 }
245
246
247
248
249 public String createDocumentFromSource(Session session, String sourceId, Properties properties, String folderId,
250 VersioningState versioningState) {
251
252 log.debug("createDocumentFromSource");
253
254
255 JcrFolder parent = getJcrNode(session, folderId).asFolder();
256
257
258 JcrDocument source = getJcrNode(session, sourceId).asDocument();
259
260 boolean isVersionable = source.isVersionable();
261 if (!isVersionable && versioningState != VersioningState.NONE) {
262 throw new CmisConstraintException("Versioning not supported for " + sourceId);
263 }
264
265 if (isVersionable && versioningState == VersioningState.NONE) {
266 throw new CmisConstraintException("Versioning required for " + sourceId);
267 }
268
269
270 JcrNode jcrNode = parent.addNodeFromSource(source, properties);
271 return jcrNode.getId();
272 }
273
274
275
276
277 public String createFolder(Session session, Properties properties, String folderId) {
278 log.debug("createFolder");
279
280
281 if (properties == null || properties.getProperties() == null) {
282 throw new CmisInvalidArgumentException("Properties must be set!");
283 }
284
285
286 String typeId = PropertyHelper.getTypeId(properties);
287 TypeDefinition type = typeManager.getType(typeId);
288 if (type == null) {
289 throw new CmisObjectNotFoundException("Type '" + typeId + "' is unknown!");
290 }
291
292
293 String name = PropertyHelper.getStringProperty(properties, PropertyIds.NAME);
294 if (!JcrConverter.isValidJcrName(name)) {
295 throw new CmisNameConstraintViolationException("Name is not valid: " + name);
296 }
297
298
299 JcrFolder parent = getJcrNode(session, folderId).asFolder();
300 JcrFolderTypeHandler typeHandler = typeHandlerManager.getFolderTypeHandler(typeId);
301 JcrNode jcrNode = typeHandler.createFolder(parent, name, properties);
302 return jcrNode.getId();
303 }
304
305
306
307
308 public ObjectData moveObject(Session session, Holder<String> objectId, String targetFolderId,
309 ObjectInfoHandler objectInfos, boolean requiresObjectInfo) {
310
311 log.debug("moveObject");
312
313 if (objectId == null || objectId.getValue() == null) {
314 throw new CmisInvalidArgumentException("Id is not valid!");
315 }
316
317
318 JcrNode jcrNode = getJcrNode(session, objectId.getValue());
319 JcrFolder parent = getJcrNode(session, targetFolderId).asFolder();
320 jcrNode = jcrNode.move(parent);
321 objectId.setValue(jcrNode.getId());
322 return jcrNode.compileObjectType(null, false, objectInfos, requiresObjectInfo);
323 }
324
325
326
327
328 public void setContentStream(Session session, Holder<String> objectId, Boolean overwriteFlag,
329 ContentStream contentStream) {
330
331 log.debug("setContentStream or deleteContentStream");
332
333 if (objectId == null || objectId.getValue() == null) {
334 throw new CmisInvalidArgumentException("Id is not valid!");
335 }
336
337 JcrDocument jcrDocument = getJcrNode(session, objectId.getValue()).asDocument();
338 String id = jcrDocument.setContentStream(contentStream, Boolean.TRUE.equals(overwriteFlag)).getId();
339 objectId.setValue(id);
340 }
341
342
343
344
345 public void deleteObject(Session session, String objectId, Boolean allVersions) {
346 log.debug("deleteObject");
347
348
349 JcrNode jcrNode = getJcrNode(session, objectId);
350 jcrNode.delete(Boolean.TRUE.equals(allVersions), JcrPrivateWorkingCopy.isPwc(objectId));
351 }
352
353
354
355
356 public FailedToDeleteData deleteTree(Session session, String folderId) {
357 log.debug("deleteTree");
358
359
360 JcrFolder jcrFolder = getJcrNode(session, folderId).asFolder();
361 return jcrFolder.deleteTree();
362 }
363
364
365
366
367 public ObjectData updateProperties(Session session, Holder<String> objectId, Properties properties,
368 ObjectInfoHandler objectInfos, boolean objectInfoRequired) {
369
370 log.debug("updateProperties");
371
372 if (objectId == null) {
373 throw new CmisInvalidArgumentException("Id is not valid!");
374 }
375
376
377 JcrNode jcrNode = getJcrNode(session, objectId.getValue());
378 String id = jcrNode.updateProperties(properties).getId();
379 objectId.setValue(id);
380 return jcrNode.compileObjectType(null, false, objectInfos, objectInfoRequired);
381 }
382
383
384
385
386 public ObjectData getObject(Session session, String objectId, String filter, Boolean includeAllowableActions,
387 ObjectInfoHandler objectInfos, boolean requiresObjectInfo) {
388
389 log.debug("getObject");
390
391
392 if (objectId == null) {
393 throw new CmisInvalidArgumentException("Object Id must be set.");
394 }
395
396
397 JcrNode jcrNode = getJcrNode(session, objectId);
398
399
400 return jcrNode.compileObjectType(splitFilter(filter), includeAllowableActions, objectInfos, requiresObjectInfo);
401 }
402
403
404
405
406 public Properties getProperties(Session session, String objectId, String filter, Boolean includeAllowableActions,
407 ObjectInfoHandler objectInfos, boolean requiresObjectInfo) {
408
409 ObjectData object = getObject(session, objectId, filter, includeAllowableActions, objectInfos, requiresObjectInfo);
410 return object.getProperties();
411 }
412
413
414
415
416 public AllowableActions getAllowableActions(Session session, String objectId) {
417 log.debug("getAllowableActions");
418
419 JcrNode jcrNode = getJcrNode(session, objectId);
420 return jcrNode.getAllowableActions();
421 }
422
423
424
425
426 public ContentStream getContentStream(Session session, String objectId, BigInteger offset, BigInteger length) {
427 log.debug("getContentStream");
428
429 if (offset != null || length != null) {
430 throw new CmisInvalidArgumentException("Offset and Length are not supported!");
431 }
432
433
434 JcrDocument jcrDocument = getJcrNode(session, objectId).asDocument();
435 return jcrDocument.getContentStream();
436 }
437
438
439
440
441 public ObjectInFolderList getChildren(Session session, String folderId, String filter,
442 Boolean includeAllowableActions, Boolean includePathSegment, BigInteger maxItems, BigInteger skipCount,
443 ObjectInfoHandler objectInfos, boolean requiresObjectInfo) {
444
445 log.debug("getChildren");
446
447
448 int skip = skipCount == null ? 0 : skipCount.intValue();
449 if (skip < 0) {
450 skip = 0;
451 }
452
453 int max = maxItems == null ? Integer.MAX_VALUE : maxItems.intValue();
454 if (max < 0) {
455 max = Integer.MAX_VALUE;
456 }
457
458
459 JcrFolder jcrFolder = getJcrNode(session, folderId).asFolder();
460
461
462 if (requiresObjectInfo) {
463 jcrFolder.compileObjectType(null, false, objectInfos, requiresObjectInfo);
464 }
465
466
467 ObjectInFolderListImpl result = new ObjectInFolderListImpl();
468 result.setObjects(new ArrayList<ObjectInFolderData>());
469 result.setHasMoreItems(false);
470 int count = 0;
471
472
473 Set<String> splitFilter = splitFilter(filter);
474 Iterator<JcrNode> childNodes = jcrFolder.getNodes();
475 while (childNodes.hasNext()) {
476 JcrNode child = childNodes.next();
477 count++;
478
479 if (skip > 0) {
480 skip--;
481 continue;
482 }
483
484 if (result.getObjects().size() >= max) {
485 result.setHasMoreItems(true);
486 continue;
487 }
488
489
490 ObjectInFolderDataImpl objectInFolder = new ObjectInFolderDataImpl();
491 objectInFolder.setObject(child.compileObjectType(splitFilter, includeAllowableActions, objectInfos,
492 requiresObjectInfo));
493
494 if (Boolean.TRUE.equals(includePathSegment)) {
495 objectInFolder.setPathSegment(child.getName());
496 }
497
498 result.getObjects().add(objectInFolder);
499 }
500
501 result.setNumItems(BigInteger.valueOf(count));
502 return result;
503 }
504
505
506
507
508 public List<ObjectInFolderContainer> getDescendants(Session session, String folderId, BigInteger depth,
509 String filter, Boolean includeAllowableActions, Boolean includePathSegment, ObjectInfoHandler objectInfos,
510 boolean requiresObjectInfo, boolean foldersOnly) {
511
512 log.debug("getDescendants or getFolderTree");
513
514
515 int d = depth == null ? 2 : depth.intValue();
516 if (d == 0) {
517 throw new CmisInvalidArgumentException("Depth must not be 0!");
518 }
519 if (d < -1) {
520 d = -1;
521 }
522
523
524 JcrFolder jcrFolder = getJcrNode(session, folderId).asFolder();
525
526
527 if (requiresObjectInfo) {
528 jcrFolder.compileObjectType(null, false, objectInfos, requiresObjectInfo);
529 }
530
531
532 List<ObjectInFolderContainer> result = new ArrayList<ObjectInFolderContainer>();
533 gatherDescendants(jcrFolder, result, foldersOnly, d, splitFilter(filter), includeAllowableActions,
534 includePathSegment, objectInfos, requiresObjectInfo);
535
536 return result;
537 }
538
539
540
541
542 public ObjectData getFolderParent(Session session, String folderId, String filter, ObjectInfoHandler objectInfos,
543 boolean requiresObjectInfo) {
544
545 List<ObjectParentData> parents = getObjectParents(session, folderId, filter, false, false, objectInfos,
546 requiresObjectInfo);
547
548 if (parents.isEmpty()) {
549 throw new CmisInvalidArgumentException("The root folder has no parent!");
550 }
551
552 return parents.get(0).getObject();
553 }
554
555
556
557
558 public List<ObjectParentData> getObjectParents(Session session, String objectId, String filter,
559 Boolean includeAllowableActions, Boolean includeRelativePathSegment, ObjectInfoHandler objectInfos,
560 boolean requiresObjectInfo) {
561
562 log.debug("getObjectParents");
563
564
565 JcrNode jcrNode = getJcrNode(session, objectId);
566
567
568 if (jcrNode.isRoot()) {
569 return Collections.emptyList();
570 }
571
572
573 if (requiresObjectInfo) {
574 jcrNode.compileObjectType(null, false, objectInfos, requiresObjectInfo);
575 }
576
577
578 JcrNode parent = jcrNode.getParent();
579 ObjectData object = parent.compileObjectType(splitFilter(filter), includeAllowableActions, objectInfos,
580 requiresObjectInfo);
581
582 ObjectParentDataImpl result = new ObjectParentDataImpl();
583 result.setObject(object);
584 if (Boolean.TRUE.equals(includeRelativePathSegment)) {
585 result.setRelativePathSegment(parent.getName());
586 }
587
588 return Collections.singletonList((ObjectParentData) result);
589 }
590
591
592
593
594 public ObjectData getObjectByPath(Session session, String folderPath, String filter, boolean includeAllowableActions,
595 boolean includeACL, ObjectInfoHandler objectInfos, boolean requiresObjectInfo) {
596
597 log.debug("getObjectByPath");
598
599
600 if (folderPath == null || !PathManager.isAbsolute(folderPath)) {
601 throw new CmisInvalidArgumentException("Invalid folder path!");
602 }
603
604 JcrNode root = getJcrNode(session, PathManager.CMIS_ROOT_ID);
605 JcrNode jcrNode;
606 if (PathManager.isRoot(folderPath)) {
607 jcrNode = root;
608 }
609 else {
610 String path = PathManager.relativize(PathManager.CMIS_ROOT_PATH, folderPath);
611 jcrNode = root.getNode(path);
612 }
613
614 return jcrNode.compileObjectType(splitFilter(filter), includeAllowableActions, objectInfos, requiresObjectInfo);
615 }
616
617
618
619
620 public ObjectList getCheckedOutDocs(Session session, String folderId, String filter, String orderBy,
621 Boolean includeAllowableActions, BigInteger maxItems, BigInteger skipCount) {
622
623 log.debug("getCheckedOutDocs");
624
625
626 int skip = skipCount == null ? 0 : skipCount.intValue();
627 if (skip < 0) {
628 skip = 0;
629 }
630
631 int max = maxItems == null ? Integer.MAX_VALUE : maxItems.intValue();
632 if (max < 0) {
633 max = Integer.MAX_VALUE;
634 }
635
636 try {
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705 public void checkOut(Session session, Holder<String> objectId, Holder<Boolean> contentCopied) {
706 log.debug("checkout");
707
708
709 if (objectId == null || objectId.getValue() == null) {
710 throw new CmisInvalidArgumentException("Object Id must be set.");
711 }
712
713
714 JcrNode jcrNode = getJcrNode(session, objectId.getValue());
715 if (!jcrNode.isVersionable()) {
716 throw new CmisUpdateConflictException("Not a version: " + jcrNode);
717 }
718
719
720 JcrPrivateWorkingCopy pwc = jcrNode.asVersion().checkout();
721 objectId.setValue(pwc.getId());
722 if (contentCopied != null) {
723 contentCopied.setValue(true);
724 }
725 }
726
727
728
729
730 public void cancelCheckout(Session session, String objectId) {
731 log.debug("cancelCheckout");
732
733
734 if (objectId == null) {
735 throw new CmisInvalidArgumentException("Object Id must be set.");
736 }
737
738
739 JcrNode jcrNode = getJcrNode(session, objectId);
740 if (!jcrNode.isVersionable()) {
741 throw new CmisUpdateConflictException("Not a version: " + jcrNode);
742 }
743
744
745 jcrNode.asVersion().cancelCheckout();
746 }
747
748
749
750
751 public void checkIn(Session session, Holder<String> objectId, Boolean major, Properties properties,
752 ContentStream contentStream, String checkinComment) {
753
754 log.debug("checkin");
755
756
757 if (objectId == null || objectId.getValue() == null) {
758 throw new CmisInvalidArgumentException("Object Id must be set.");
759 }
760
761
762 JcrNode jcrNode;
763 try {
764 jcrNode = getJcrNode(session, objectId.getValue());
765 }
766 catch (CmisObjectNotFoundException e) {
767 throw new CmisUpdateConflictException(e.getCause().getMessage(), e.getCause());
768 }
769
770 if (!jcrNode.isVersionable()) {
771 throw new CmisUpdateConflictException("Not a version: " + jcrNode);
772 }
773
774
775 JcrVersion checkedIn = jcrNode.asVersion().checkin(properties, contentStream, checkinComment);
776 objectId.setValue(checkedIn.getId());
777 }
778
779
780
781
782 public List<ObjectData> getAllVersions(Session session, String objectId, String filter,
783 Boolean includeAllowableActions, ObjectInfoHandler objectInfos, boolean requiresObjectInfo) {
784
785 log.debug("getAllVersions");
786
787
788 if (objectId == null) {
789 throw new CmisInvalidArgumentException("Object Id must be set.");
790 }
791
792 Set<String> splitFilter = splitFilter(filter);
793
794
795 JcrNode jcrNode = getJcrNode(session, objectId);
796
797
798 if (jcrNode.isVersionable()) {
799 JcrVersionBase jcrVersion = jcrNode.asVersion();
800
801 Iterator<JcrVersion> versions = jcrVersion.getVersions();
802 if (versions.hasNext()) {
803 versions.next();
804 }
805
806 List<ObjectData> allVersions = new ArrayList<ObjectData>();
807 while (versions.hasNext()) {
808 JcrVersion version = versions.next();
809 ObjectData objectData = version.compileObjectType(splitFilter, includeAllowableActions, objectInfos,
810 requiresObjectInfo);
811 allVersions.add(objectData);
812 }
813
814
815 if (jcrVersion.isDocumentCheckedOut()) {
816 JcrPrivateWorkingCopy pwc = jcrVersion.getPwc();
817 ObjectData objectData = pwc.compileObjectType(splitFilter, includeAllowableActions, objectInfos,
818 requiresObjectInfo);
819
820 allVersions.add(objectData);
821 }
822
823
824 Collections.reverse(allVersions);
825 return allVersions;
826 }
827 else {
828
829 ObjectData objectData = jcrNode.compileObjectType(splitFilter, includeAllowableActions, objectInfos,
830 requiresObjectInfo);
831
832 return Collections.singletonList(objectData);
833 }
834
835 }
836
837
838
839
840 public ObjectList query(final Session session, String statement, Boolean searchAllVersions,
841 Boolean includeAllowableActions, BigInteger maxItems, BigInteger skipCount) {
842
843 log.debug("query");
844
845 if (searchAllVersions) {
846 throw new CmisNotSupportedException("Not supported: query for all versions");
847 }
848
849
850 int skip = skipCount == null ? 0 : skipCount.intValue();
851 if (skip < 0) {
852 skip = 0;
853 }
854
855 int max = maxItems == null ? Integer.MAX_VALUE : maxItems.intValue();
856 if (max < 0) {
857 max = Integer.MAX_VALUE;
858 }
859
860 QueryTranslator queryTranslator = new QueryTranslator(typeManager) {
861 @Override
862 protected String jcrPathFromId(String id) {
863 try {
864 JcrFolder folder = getJcrNode(session, id).asFolder();
865 String path = folder.getNode().getPath();
866 return Util.escape(path);
867 }
868 catch (RepositoryException e) {
869 log.debug(e.getMessage(), e);
870 throw new CmisRuntimeException(e.getMessage(), e);
871 }
872 }
873
874 @Override
875 protected String jcrPathFromCol(TypeDefinition fromType, String name) {
876 return typeHandlerManager.getIdentifierMap(fromType.getId()).jcrPathFromCol(name);
877 }
878
879 @Override
880 protected String jcrTypeName(TypeDefinition fromType) {
881 return typeHandlerManager.getIdentifierMap(fromType.getId()).jcrTypeName();
882 }
883
884 @Override
885 protected String jcrTypeCondition(TypeDefinition fromType) {
886 return typeHandlerManager.getIdentifierMap(fromType.getId()).jcrTypeCondition();
887 }
888 };
889
890 String xPath = queryTranslator.translateToXPath(statement);
891 try {
892
893 QueryManager queryManager = session.getWorkspace().getQueryManager();
894 Query query = queryManager.createQuery(xPath, Query.XPATH);
895
896 if (skip > 0) {
897 query.setOffset(skip);
898 }
899 if (max < Integer.MAX_VALUE) {
900 query.setLimit(max + 1);
901 }
902
903 QueryResult queryResult = query.execute();
904
905
906 ObjectListImpl result = new ObjectListImpl();
907 result.setObjects(new ArrayList<ObjectData>());
908 result.setHasMoreItems(false);
909
910
911 int count = 0;
912 NodeIterator nodes = queryResult.getNodes();
913 while (nodes.hasNext() && result.getObjects().size() < max) {
914 Node node = nodes.nextNode();
915 JcrNode jcrNode = typeHandlerManager.create(node);
916 count++;
917
918
919 if (jcrNode.isVersionable() && jcrNode.asVersion().isCheckedOut()) {
920 jcrNode = jcrNode.asVersion().getPwc();
921 }
922
923
924 ObjectData objectData = jcrNode.compileObjectType(null, includeAllowableActions, null, false);
925 result.getObjects().add(objectData);
926 }
927
928 result.setHasMoreItems(nodes.hasNext());
929 result.setNumItems(BigInteger.valueOf(count));
930 return result;
931 }
932 catch (RepositoryException e) {
933 log.debug(e.getMessage(), e);
934 throw new CmisRuntimeException(e.getMessage(), e);
935 }
936 }
937
938
939
940 protected RepositoryInfo compileRepositoryInfo(String repositoryId) {
941 RepositoryInfoImpl fRepositoryInfo = new RepositoryInfoImpl();
942
943 fRepositoryInfo.setId(repositoryId);
944 fRepositoryInfo.setName(getRepositoryName());
945 fRepositoryInfo.setDescription(getRepositoryDescription());
946
947 fRepositoryInfo.setCmisVersionSupported("1.0");
948
949 fRepositoryInfo.setProductName("OpenCMIS JCR");
950 fRepositoryInfo.setProductVersion("0.3");
951 fRepositoryInfo.setVendorName("OpenCMIS");
952
953 fRepositoryInfo.setRootFolder(PathManager.CMIS_ROOT_ID);
954 fRepositoryInfo.setThinClientUri("");
955
956 RepositoryCapabilitiesImpl capabilities = new RepositoryCapabilitiesImpl();
957 capabilities.setCapabilityAcl(CapabilityAcl.NONE);
958 capabilities.setAllVersionsSearchable(false);
959 capabilities.setCapabilityJoin(CapabilityJoin.NONE);
960 capabilities.setSupportsMultifiling(false);
961 capabilities.setSupportsUnfiling(false);
962 capabilities.setSupportsVersionSpecificFiling(false);
963 capabilities.setIsPwcSearchable(false);
964 capabilities.setIsPwcUpdatable(true);
965 capabilities.setCapabilityQuery(CapabilityQuery.BOTHCOMBINED);
966 capabilities.setCapabilityChanges(CapabilityChanges.NONE);
967 capabilities.setCapabilityContentStreamUpdates(CapabilityContentStreamUpdates.ANYTIME);
968 capabilities.setSupportsGetDescendants(true);
969 capabilities.setSupportsGetFolderTree(true);
970 capabilities.setCapabilityRendition(CapabilityRenditions.NONE);
971 fRepositoryInfo.setCapabilities(capabilities);
972
973 return fRepositoryInfo;
974 }
975
976 protected String getRepositoryName() {
977 return repository.getDescriptor(Repository.REP_NAME_DESC);
978 }
979
980 protected String getRepositoryDescription() {
981 StringBuilder description = new StringBuilder();
982
983 for (String key : repository.getDescriptorKeys()) {
984 description
985 .append(key)
986 .append('=')
987 .append(repository.getDescriptor(key))
988 .append('\n');
989 }
990
991 return description.toString();
992 }
993
994 protected JcrNode getJcrNode(Session session, String id) {
995 try {
996 if (id == null || id.length() == 0) {
997 throw new CmisInvalidArgumentException("Null or empty id");
998 }
999
1000 if (id.equals(PathManager.CMIS_ROOT_ID)) {
1001 return typeHandlerManager.create(getRootNode(session));
1002 }
1003
1004 int k = id.indexOf('/');
1005 if (k >= 0) {
1006 String nodeId = id.substring(0, k);
1007 String versionName = id.substring(k + 1);
1008
1009 Node node = session.getNodeByIdentifier(nodeId);
1010
1011 JcrNode jcrNode = typeHandlerManager.create(node);
1012 if (JcrPrivateWorkingCopy.denotesPwc(versionName)) {
1013 return jcrNode.asVersion().getPwc();
1014 }
1015 else {
1016 return jcrNode.asVersion().getVersion(versionName);
1017 }
1018 }
1019 else {
1020 Node node = session.getNodeByIdentifier(id);
1021 return typeHandlerManager.create(node);
1022 }
1023
1024 }
1025 catch (ItemNotFoundException e) {
1026 log.debug(e.getMessage(), e);
1027 throw new CmisObjectNotFoundException(e.getMessage(), e);
1028 }
1029 catch (RepositoryException e) {
1030 log.debug(e.getMessage(), e);
1031 throw new CmisRuntimeException(e.getMessage(), e);
1032 }
1033 }
1034
1035 protected Node getRootNode(Session session) {
1036 try {
1037 return session.getNode(pathManager.getJcrRootPath());
1038 }
1039 catch (PathNotFoundException e) {
1040 log.debug(e.getMessage(), e);
1041 throw new CmisObjectNotFoundException(e.getMessage(), e);
1042 }
1043 catch (ItemNotFoundException e) {
1044 log.debug(e.getMessage(), e);
1045 throw new CmisObjectNotFoundException(e.getMessage(), e);
1046 }
1047 catch (RepositoryException e) {
1048 log.debug(e.getMessage(), e);
1049 throw new CmisRuntimeException(e.getMessage(), e);
1050 }
1051 }
1052
1053
1054
1055
1056
1057
1058 private static void gatherDescendants(JcrFolder jcrFolder, List<ObjectInFolderContainer> list,
1059 boolean foldersOnly, int depth, Set<String> filter, Boolean includeAllowableActions,
1060 Boolean includePathSegments, ObjectInfoHandler objectInfos, boolean requiresObjectInfo) {
1061
1062
1063 Iterator<JcrNode> childNodes = jcrFolder.getNodes();
1064 while (childNodes.hasNext()) {
1065 JcrNode child = childNodes.next();
1066
1067
1068 if (foldersOnly && !child.isFolder()) {
1069 continue;
1070 }
1071
1072
1073 ObjectInFolderDataImpl objectInFolder = new ObjectInFolderDataImpl();
1074 objectInFolder.setObject(child.compileObjectType(filter, includeAllowableActions, objectInfos,
1075 requiresObjectInfo));
1076
1077 if (Boolean.TRUE.equals(includePathSegments)) {
1078 objectInFolder.setPathSegment(child.getName());
1079 }
1080
1081 ObjectInFolderContainerImpl container = new ObjectInFolderContainerImpl();
1082 container.setObject(objectInFolder);
1083
1084 list.add(container);
1085
1086
1087 if (depth != 1 && child.isFolder()) {
1088 container.setChildren(new ArrayList<ObjectInFolderContainer>());
1089 gatherDescendants(child.asFolder(), container.getChildren(), foldersOnly, depth - 1, filter,
1090 includeAllowableActions, includePathSegments, objectInfos, requiresObjectInfo);
1091 }
1092 }
1093 }
1094
1095
1096
1097
1098 private static Set<String> splitFilter(String filter) {
1099 if (filter == null) {
1100 return null;
1101 }
1102
1103 if (filter.trim().length() == 0) {
1104 return null;
1105 }
1106
1107 Set<String> result = new HashSet<String>();
1108 for (String s : filter.split(",")) {
1109 s = s.trim();
1110 if (s.equals("*")) {
1111 return null;
1112 } else if (s.length() > 0) {
1113 result.add(s);
1114 }
1115 }
1116
1117
1118
1119 result.add(PropertyIds.OBJECT_ID);
1120 result.add(PropertyIds.OBJECT_TYPE_ID);
1121 result.add(PropertyIds.BASE_TYPE_ID);
1122
1123 return result;
1124 }
1125 }