001/* 002 * Copyright 2017 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.workspaces.cmis; 017 018import java.io.InputStream; 019import java.math.BigInteger; 020import java.util.ArrayList; 021import java.util.Arrays; 022import java.util.Collection; 023import java.util.Collections; 024import java.util.Date; 025import java.util.EnumSet; 026import java.util.GregorianCalendar; 027import java.util.HashSet; 028import java.util.List; 029import java.util.Map; 030import java.util.Set; 031 032import javax.jcr.RepositoryException; 033 034import org.apache.chemistry.opencmis.commons.PropertyIds; 035import org.apache.chemistry.opencmis.commons.data.AllowableActions; 036import org.apache.chemistry.opencmis.commons.data.ContentStream; 037import org.apache.chemistry.opencmis.commons.data.FailedToDeleteData; 038import org.apache.chemistry.opencmis.commons.data.ObjectData; 039import org.apache.chemistry.opencmis.commons.data.ObjectInFolderData; 040import org.apache.chemistry.opencmis.commons.data.ObjectInFolderList; 041import org.apache.chemistry.opencmis.commons.data.ObjectParentData; 042import org.apache.chemistry.opencmis.commons.data.Properties; 043import org.apache.chemistry.opencmis.commons.data.PropertyData; 044import org.apache.chemistry.opencmis.commons.data.RepositoryInfo; 045import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition; 046import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition; 047import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionList; 048import org.apache.chemistry.opencmis.commons.enums.Action; 049import org.apache.chemistry.opencmis.commons.enums.BaseTypeId; 050import org.apache.chemistry.opencmis.commons.enums.CapabilityAcl; 051import org.apache.chemistry.opencmis.commons.enums.CapabilityChanges; 052import org.apache.chemistry.opencmis.commons.enums.CapabilityContentStreamUpdates; 053import org.apache.chemistry.opencmis.commons.enums.CapabilityJoin; 054import org.apache.chemistry.opencmis.commons.enums.CapabilityRenditions; 055import org.apache.chemistry.opencmis.commons.enums.CmisVersion; 056import org.apache.chemistry.opencmis.commons.enums.Updatability; 057import org.apache.chemistry.opencmis.commons.enums.VersioningState; 058import org.apache.chemistry.opencmis.commons.exceptions.CmisBaseException; 059import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException; 060import org.apache.chemistry.opencmis.commons.exceptions.CmisContentAlreadyExistsException; 061import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException; 062import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException; 063import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException; 064import org.apache.chemistry.opencmis.commons.exceptions.CmisStorageException; 065import org.apache.chemistry.opencmis.commons.exceptions.CmisStreamNotSupportedException; 066import org.apache.chemistry.opencmis.commons.impl.dataobjects.AllowableActionsImpl; 067import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl; 068import org.apache.chemistry.opencmis.commons.impl.dataobjects.FailedToDeleteDataImpl; 069import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectDataImpl; 070import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectInFolderDataImpl; 071import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectInFolderListImpl; 072import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectParentDataImpl; 073import org.apache.chemistry.opencmis.commons.impl.dataobjects.PartialContentStreamImpl; 074import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertiesImpl; 075import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyBooleanImpl; 076import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyDateTimeImpl; 077import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIdImpl; 078import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIntegerImpl; 079import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyStringImpl; 080import org.apache.chemistry.opencmis.commons.impl.dataobjects.RepositoryCapabilitiesImpl; 081import org.apache.chemistry.opencmis.commons.impl.dataobjects.RepositoryInfoImpl; 082import org.apache.chemistry.opencmis.commons.impl.server.ObjectInfoImpl; 083import org.apache.chemistry.opencmis.commons.server.CallContext; 084import org.apache.chemistry.opencmis.commons.server.ObjectInfoHandler; 085import org.apache.chemistry.opencmis.commons.spi.Holder; 086import org.apache.commons.lang.IllegalClassException; 087import org.apache.commons.lang3.StringUtils; 088 089import org.ametys.core.util.URIUtils; 090import org.ametys.plugins.explorer.resources.ModifiableResource; 091import org.ametys.plugins.explorer.resources.ModifiableResourceCollection; 092import org.ametys.plugins.explorer.resources.actions.AddOrUpdateResourceHelper.ResourceOperationMode; 093import org.ametys.plugins.explorer.resources.actions.AddOrUpdateResourceHelper.ResourceOperationResult; 094import org.ametys.plugins.repository.AmetysObject; 095import org.ametys.plugins.repository.AmetysObjectIterable; 096import org.ametys.plugins.workspaces.documents.DocumentWorkspaceModule; 097import org.ametys.plugins.workspaces.project.objects.Project; 098 099/** 100 * Helper class to retreive CMIS objects 101 * 102 */ 103public class CmisRepository 104{ 105 private static final String USER_UNKNOWN = "<unknown>"; 106 107 /** 108 * retreive informations for a repository 109 * @param context call context 110 * @param project project 111 * @param factory factory 112 * @return RepositoryInfo 113 */ 114 public RepositoryInfo getRepositoryInfo(CallContext context, Project project, CmisServiceFactory factory) 115 { 116 String id = project.getId(); 117 String name = project.getName(); 118 if (id == null || id.trim().length() == 0 || name == null || name.trim().length() == 0) 119 { 120 throw new CmisInvalidArgumentException("Invalid repository!"); 121 } 122 123 // set up repository infos 124 return createRepositoryInfo(project, factory, CmisVersion.CMIS_1_1); 125 } 126 127 private RepositoryInfo createRepositoryInfo(Project project, CmisServiceFactory factory, CmisVersion cmisVersion) 128 { 129 assert cmisVersion != null; 130 131 RepositoryInfoImpl repositoryInfo = new RepositoryInfoImpl(); 132 133 String id = project.getId(); 134 ModifiableResourceCollection documentRoot = getRoot(project, factory); 135 136 String root = ""; 137 if (documentRoot != null) 138 { 139 root = documentRoot.getId(); 140 } 141 142 id = URIUtils.encodeParameter(URIUtils.encodeParameter(id)); 143 root = URIUtils.encodeParameter(URIUtils.encodeParameter(root)); 144 145 repositoryInfo.setId(id); 146 repositoryInfo.setName(project.getName()); 147 repositoryInfo.setDescription(project.getDescription()); 148 149 repositoryInfo.setCmisVersionSupported(cmisVersion.value()); 150 151 repositoryInfo.setProductName("Ametys CMIS Server"); 152 repositoryInfo.setProductVersion("1.0"); 153 repositoryInfo.setVendorName("Ametys"); 154 155 repositoryInfo.setRootFolder(root); 156 157 repositoryInfo.setThinClientUri(""); 158 repositoryInfo.setChangesIncomplete(false); 159 RepositoryCapabilitiesImpl capabilities = new RepositoryCapabilitiesImpl(); 160 capabilities.setCapabilityAcl(CapabilityAcl.NONE); 161 capabilities.setAllVersionsSearchable(false); 162 capabilities.setCapabilityJoin(CapabilityJoin.NONE); 163 capabilities.setSupportsMultifiling(false); 164 capabilities.setSupportsUnfiling(false); 165 capabilities.setSupportsVersionSpecificFiling(false); 166 capabilities.setIsPwcSearchable(false); 167 capabilities.setIsPwcUpdatable(false); 168 //capabilities.setCapabilityQuery(CapabilityQuery.METADATAONLY); 169 capabilities.setCapabilityChanges(CapabilityChanges.NONE); 170 capabilities.setCapabilityContentStreamUpdates(CapabilityContentStreamUpdates.ANYTIME); 171 capabilities.setSupportsGetDescendants(false); 172 capabilities.setSupportsGetFolderTree(false); 173 capabilities.setCapabilityRendition(CapabilityRenditions.NONE); 174 175 repositoryInfo.setCapabilities(capabilities); 176 177 return repositoryInfo; 178 } 179 180 /** 181 * getTypeDefinition 182 * @param context call context 183 * @param typeId type ID 184 * @param factory factory 185 * @return the type definition 186 */ 187 public TypeDefinition getTypeDefinition(CallContext context, String typeId, CmisServiceFactory factory) 188 { 189 //checkUser(context, false); 190 191 return factory.getTypeManager().getTypeDefinition(context, typeId); 192 } 193 194 /** 195 * getTypeChildren 196 * @param context context 197 * @param typeId typeId 198 * @param includePropertyDefinitions includePropertyDefinitions 199 * @param maxItems maxItems 200 * @param skipCount skipCount 201 * @param factory factory 202 * @return the type definition list 203 */ 204 public TypeDefinitionList getTypeChildren(CallContext context, String typeId, Boolean includePropertyDefinitions, 205 BigInteger maxItems, BigInteger skipCount, CmisServiceFactory factory) 206 { 207 //checkUser(context, false); 208 209 return factory.getTypeManager().getTypeChildren(context, typeId, includePropertyDefinitions, maxItems, skipCount); 210 } 211 212 /** 213 * getObject 214 * @param context context 215 * @param project Project 216 * @param objectId objectId 217 * @param versionServicesId versionServicesId 218 * @param filter filter 219 * @param includeAllowableActions includeAllowableActions 220 * @param includeAcl includeAcl 221 * @param objectInfos objectInfos 222 * @param factory factory 223 * @return ObjectData ObjectData 224 */ 225 public ObjectData getObject(CallContext context, Project project, String objectId, String versionServicesId, String filter, 226 Boolean includeAllowableActions, Boolean includeAcl, ObjectInfoHandler objectInfos, 227 CmisServiceFactory factory) 228 { 229 // check id 230 if (objectId == null && versionServicesId == null) 231 { 232 throw new CmisInvalidArgumentException("Object Id must be set."); 233 } 234 235 AmetysObject ametysObject = factory.getResolver().resolveById(objectId); 236 237 boolean userReadOnly = false; 238 239 // set defaults if values not set 240 boolean iaa = CmisUtils.getBooleanParameter(includeAllowableActions, false); 241 boolean iacl = false; //CmisUtils.getBooleanParameter(includeAcl, false); 242 243 // split filter 244 Set<String> filterCollection = CmisUtils.splitFilter(filter); 245 246 // gather properties 247 248 return compileObjectData(context, ametysObject, project, filterCollection, iaa, iacl, userReadOnly, objectInfos, factory); 249 } 250 251 252 private ObjectData compileObjectData(CallContext context, AmetysObject ametysObject, Project project, Set<String> filter, 253 boolean includeAllowableActions, boolean includeAcl, boolean userReadOnly, ObjectInfoHandler objectInfos, 254 CmisServiceFactory factory) 255 { 256 ObjectDataImpl result = new ObjectDataImpl(); 257 ObjectInfoImpl objectInfo = new ObjectInfoImpl(); 258 259 result.setProperties(compileProperties(context, ametysObject, project, filter, objectInfo, factory)); 260 261 if (includeAllowableActions) 262 { 263 result.setAllowableActions(compileAllowableActions(ametysObject, project, factory, userReadOnly)); 264 } 265 266 if (includeAcl) 267 { 268 result.setIsExactAcl(true); 269 } 270 result.setIsExactAcl(true); 271 272 if (context.isObjectInfoRequired()) 273 { 274 objectInfo.setObject(result); 275 objectInfos.addObjectInfo(objectInfo); 276 } 277 278 return result; 279 } 280 281 private Properties compileProperties(CallContext context, AmetysObject ametysObject, Project project, Set<String> orgfilter, 282 ObjectInfoImpl objectInfo, CmisServiceFactory factory) 283 { 284 // copy filter 285 Set<String> filter = orgfilter == null ? null : new HashSet<>(orgfilter); 286 287 // find base type 288 String typeId = null; 289 Boolean isFolder = true; 290 291 if (ametysObject != null && ametysObject instanceof ModifiableResource) 292 { 293 isFolder = false; 294 typeId = BaseTypeId.CMIS_DOCUMENT.value(); 295 objectInfo.setBaseType(BaseTypeId.CMIS_DOCUMENT); 296 objectInfo.setTypeId(typeId); 297 objectInfo.setHasAcl(false); 298 objectInfo.setHasContent(true); 299 objectInfo.setHasParent(true); 300 objectInfo.setVersionSeriesId(null); 301 objectInfo.setIsCurrentVersion(true); 302 objectInfo.setRelationshipSourceIds(null); 303 objectInfo.setRelationshipTargetIds(null); 304 objectInfo.setRenditionInfos(null); 305 objectInfo.setSupportsDescendants(false); 306 objectInfo.setSupportsFolderTree(false); 307 objectInfo.setSupportsPolicies(false); 308 objectInfo.setSupportsRelationships(false); 309 objectInfo.setWorkingCopyId(null); 310 objectInfo.setWorkingCopyOriginalId(null); 311 } 312 else if (ametysObject != null && ametysObject instanceof ModifiableResourceCollection) 313 { 314 isFolder = true; 315 typeId = BaseTypeId.CMIS_FOLDER.value(); 316 objectInfo.setBaseType(BaseTypeId.CMIS_FOLDER); 317 objectInfo.setTypeId(typeId); 318 objectInfo.setContentType(null); 319 objectInfo.setFileName(null); 320 objectInfo.setHasAcl(false); 321 objectInfo.setHasContent(false); 322 objectInfo.setVersionSeriesId(null); 323 objectInfo.setIsCurrentVersion(true); 324 objectInfo.setRelationshipSourceIds(null); 325 objectInfo.setRelationshipTargetIds(null); 326 objectInfo.setRenditionInfos(null); 327 objectInfo.setSupportsDescendants(true); 328 objectInfo.setSupportsFolderTree(true); 329 objectInfo.setSupportsPolicies(false); 330 objectInfo.setSupportsRelationships(false); 331 objectInfo.setWorkingCopyId(null); 332 objectInfo.setWorkingCopyOriginalId(null); 333 } 334 else 335 { 336 throw new IllegalArgumentException("Resource not found"); 337 } 338 339 try 340 { 341 PropertiesImpl result = new PropertiesImpl(); 342 343 addPropertyId(result, typeId, filter, PropertyIds.OBJECT_ID, ametysObject.getId(), factory); 344 objectInfo.setId(ametysObject.getId()); 345 346 // name 347 String name = ametysObject.getName(); 348 addPropertyString(result, typeId, filter, PropertyIds.NAME, name, factory); 349 objectInfo.setName(name); 350 351 if (isFolder) 352 { 353 ModifiableResourceCollection folder = (ModifiableResourceCollection) ametysObject; 354 addPropertyString(result, typeId, filter, PropertyIds.CREATED_BY, USER_UNKNOWN, factory); 355 addPropertyString(result, typeId, filter, PropertyIds.LAST_MODIFIED_BY, USER_UNKNOWN, factory); 356 objectInfo.setCreatedBy(USER_UNKNOWN); 357 addPropertyString(result, typeId, filter, PropertyIds.DESCRIPTION, folder.getDescription(), factory); 358 359 // base type and type name 360 addPropertyId(result, typeId, filter, PropertyIds.BASE_TYPE_ID, BaseTypeId.CMIS_FOLDER.value(), factory); 361 addPropertyId(result, typeId, filter, PropertyIds.OBJECT_TYPE_ID, BaseTypeId.CMIS_FOLDER.value(), factory); 362 363 String path = ((ModifiableResourceCollection) ametysObject).getExplorerPath(); 364 ModifiableResourceCollection root = getRoot(project, factory); 365 path = path.substring(root.getExplorerPath().length()); 366 if (path.length() == 0) 367 { 368 path = "/"; 369 } 370 addPropertyString(result, typeId, filter, PropertyIds.PATH, path, factory); 371 372 // folder properties 373 374 //On évite d'appeler isRoot qui ferait un appel JCR de plus 375 if (ametysObject.equals(root)) 376 { 377 addPropertyId(result, typeId, filter, PropertyIds.PARENT_ID, null, factory); 378 objectInfo.setHasParent(false); 379 } 380 else 381 { 382 String parentId = ametysObject.getParent().getId(); 383 addPropertyId(result, typeId, filter, PropertyIds.PARENT_ID, parentId, factory); 384 objectInfo.setHasParent(true); 385 } 386 387 addPropertyIdList(result, typeId, filter, PropertyIds.ALLOWED_CHILD_OBJECT_TYPE_IDS, null, factory); 388 } 389 else 390 { 391 ModifiableResource modifiableResource = (ModifiableResource) ametysObject; 392 String author = modifiableResource.getCreator().getLogin(); 393 String contributor = modifiableResource.getLastContributor().getLogin(); 394 addPropertyString(result, typeId, filter, PropertyIds.CREATED_BY, author, factory); 395 addPropertyString(result, typeId, filter, PropertyIds.LAST_MODIFIED_BY, contributor, factory); 396 addPropertyString(result, typeId, filter, PropertyIds.DESCRIPTION, modifiableResource.getDCDescription(), factory); 397 objectInfo.setCreatedBy(author); 398 399 Date lastModifiedDate = modifiableResource.getLastModified(); 400 GregorianCalendar lastModified = new GregorianCalendar(); 401 lastModified.setTime(lastModifiedDate); 402 Date creationDate = modifiableResource.getCreationDate(); 403 GregorianCalendar creation = new GregorianCalendar(); 404 creation.setTime(creationDate); 405 addPropertyDateTime(result, typeId, filter, PropertyIds.CREATION_DATE, creation, factory); 406 addPropertyDateTime(result, typeId, filter, PropertyIds.LAST_MODIFICATION_DATE, lastModified, factory); 407 objectInfo.setCreationDate(creation); 408 objectInfo.setLastModificationDate(lastModified); 409 410 // base type and type name 411 addPropertyId(result, typeId, filter, PropertyIds.BASE_TYPE_ID, BaseTypeId.CMIS_DOCUMENT.value(), factory); 412 addPropertyId(result, typeId, filter, PropertyIds.OBJECT_TYPE_ID, BaseTypeId.CMIS_DOCUMENT.value(), factory); 413 414 // file properties 415 addPropertyBoolean(result, typeId, filter, PropertyIds.IS_IMMUTABLE, false, factory); 416 addPropertyBoolean(result, typeId, filter, PropertyIds.IS_LATEST_VERSION, true, factory); 417 addPropertyBoolean(result, typeId, filter, PropertyIds.IS_MAJOR_VERSION, true, factory); 418 addPropertyBoolean(result, typeId, filter, PropertyIds.IS_LATEST_MAJOR_VERSION, true, factory); 419 addPropertyString(result, typeId, filter, PropertyIds.VERSION_LABEL, modifiableResource.getName(), factory); 420 //addPropertyId(result, typeId, filter, PropertyIds.VERSION_SERIES_ID, fileToId(file), factory); 421 addPropertyBoolean(result, typeId, filter, PropertyIds.IS_VERSION_SERIES_CHECKED_OUT, false, factory); 422 addPropertyString(result, typeId, filter, PropertyIds.VERSION_SERIES_CHECKED_OUT_BY, null, factory); 423 addPropertyString(result, typeId, filter, PropertyIds.VERSION_SERIES_CHECKED_OUT_ID, null, factory); 424 addPropertyString(result, typeId, filter, PropertyIds.CHECKIN_COMMENT, "", factory); 425 if (context.getCmisVersion() != CmisVersion.CMIS_1_0) 426 { 427 addPropertyBoolean(result, typeId, filter, PropertyIds.IS_PRIVATE_WORKING_COPY, false, factory); 428 } 429 430 431 if (modifiableResource.getLength() == 0) 432 { 433 addPropertyBigInteger(result, typeId, filter, PropertyIds.CONTENT_STREAM_LENGTH, null, factory); 434 addPropertyString(result, typeId, filter, PropertyIds.CONTENT_STREAM_MIME_TYPE, null, factory); 435 addPropertyString(result, typeId, filter, PropertyIds.CONTENT_STREAM_FILE_NAME, null, factory); 436 437 objectInfo.setHasContent(false); 438 objectInfo.setContentType(null); 439 objectInfo.setFileName(null); 440 } 441 else 442 { 443 444 addPropertyInteger(result, typeId, filter, PropertyIds.CONTENT_STREAM_LENGTH, modifiableResource.getLength(), factory); 445 addPropertyString(result, typeId, filter, PropertyIds.CONTENT_STREAM_MIME_TYPE, 446 modifiableResource.getMimeType(), factory); 447 addPropertyString(result, typeId, filter, PropertyIds.CONTENT_STREAM_FILE_NAME, modifiableResource.getName(), factory); 448 449 objectInfo.setHasContent(true); 450 objectInfo.setContentType(modifiableResource.getMimeType()); 451 objectInfo.setFileName(modifiableResource.getName()); 452 } 453 454 addPropertyId(result, typeId, filter, PropertyIds.CONTENT_STREAM_ID, null, factory); 455 } 456 457 458 459 // change token - always null 460 addPropertyString(result, typeId, filter, PropertyIds.CHANGE_TOKEN, null, factory); 461 462 // CMIS 1.1 properties 463 if (context.getCmisVersion() != CmisVersion.CMIS_1_0) 464 { 465 addPropertyString(result, typeId, filter, PropertyIds.DESCRIPTION, null, factory); 466 addPropertyIdList(result, typeId, filter, PropertyIds.SECONDARY_OBJECT_TYPE_IDS, null, factory); 467 } 468 469 return result; 470 } 471 catch (CmisBaseException cbe) 472 { 473 throw cbe; 474 } 475 catch (Exception e) 476 { 477 throw new CmisRuntimeException(e.getMessage(), e); 478 } 479 } 480 481 /** 482 * get children of a folder 483 * @param context call context 484 * @param folderId folder Id 485 * @param project Project 486 * @param filter filters 487 * @param includeAllowableActions allowable actions 488 * @param includePathSegment include path segment 489 * @param maxItems max items 490 * @param skipCount skip count 491 * @param objectInfos object infos 492 * @param factory factory 493 * @return ObjectInFolderList 494 */ 495 public ObjectInFolderList getChildren(CallContext context, String folderId, Project project, String filter, 496 Boolean includeAllowableActions, Boolean includePathSegment, BigInteger maxItems, BigInteger skipCount, 497 ObjectInfoHandler objectInfos, CmisServiceFactory factory) 498 { 499 boolean userReadOnly = false; 500 501 // split filter 502 Set<String> filterCollection = CmisUtils.splitFilter(filter); 503 504 // set defaults if values not set 505 boolean iaa = CmisUtils.getBooleanParameter(includeAllowableActions, false); 506 boolean ips = CmisUtils.getBooleanParameter(includePathSegment, false); 507 508 // skip and max 509 int skip = skipCount == null ? 0 : skipCount.intValue(); 510 if (skip < 0) 511 { 512 skip = 0; 513 } 514 515 int max = maxItems == null ? Integer.MAX_VALUE : maxItems.intValue(); 516 if (max < 0) 517 { 518 max = Integer.MAX_VALUE; 519 } 520 521 // get the folder 522 AmetysObject ametysObject = factory.getResolver().resolveById(folderId); 523 if (!(ametysObject instanceof ModifiableResourceCollection)) 524 { 525 throw new CmisObjectNotFoundException("Not a folder!"); 526 } 527 ModifiableResourceCollection folder = (ModifiableResourceCollection) ametysObject; 528 529 // set object info of the the folder 530 if (context.isObjectInfoRequired()) 531 { 532 compileObjectData(context, ametysObject, project, null, false, false, userReadOnly, objectInfos, factory); 533 } 534 535 // prepare result 536 ObjectInFolderListImpl result = new ObjectInFolderListImpl(); 537 result.setObjects(new ArrayList<ObjectInFolderData>()); 538 result.setHasMoreItems(false); 539 int count = 0; 540 541 // iterate through children 542 AmetysObjectIterable<AmetysObject> children = folder.getChildren(); 543 for (AmetysObject child : children) 544 //for (File child : folder.listFiles()) 545 { 546 // skip nodes other than ModifiableResource or ModifiableResourceCollection 547 if (!(child instanceof ModifiableResource || child instanceof ModifiableResourceCollection)) 548 { 549 continue; 550 } 551 552 count++; 553 554 if (skip > 0) 555 { 556 skip--; 557 continue; 558 } 559 560 if (result.getObjects().size() >= max) 561 { 562 result.setHasMoreItems(true); 563 continue; 564 } 565 566 // build and add child object 567 ObjectInFolderDataImpl objectInFolder = new ObjectInFolderDataImpl(); 568 objectInFolder.setObject(compileObjectData(context, child, project, filterCollection, iaa, false, userReadOnly, 569 objectInfos, factory)); 570 if (ips) 571 { 572 objectInFolder.setPathSegment(child.getName()); 573 } 574 575 result.getObjects().add(objectInFolder); 576 } 577 578 result.setNumItems(BigInteger.valueOf(count)); 579 580 return result; 581 } 582 583 /** 584 * get the parents of an object 585 * @param context call context 586 * @param objectId Object Id 587 * @param project Project 588 * @param filter filters 589 * @param includeAllowableActions allowable actions 590 * @param includeRelativePathSegment relative path segment 591 * @param objectInfos object infos 592 * @param factory factory 593 * @return List of ObjectParentData 594 */ 595 public List<ObjectParentData> getObjectParents(CallContext context, String objectId, Project project, String filter, 596 Boolean includeAllowableActions, Boolean includeRelativePathSegment, ObjectInfoHandler objectInfos, CmisServiceFactory factory) 597 { 598 boolean userReadOnly = false; 599 600 // split filter 601 Set<String> filterCollection = CmisUtils.splitFilter(filter); 602 603 // set defaults if values not set 604 boolean iaa = CmisUtils.getBooleanParameter(includeAllowableActions, false); 605 boolean irps = CmisUtils.getBooleanParameter(includeRelativePathSegment, false); 606 607 // get the file or folder 608 //File file = getFile(objectId); 609 610 // don't climb above the root folder 611 AmetysObject ametysObject = factory.getResolver().resolveById(objectId); 612 if (isRoot(ametysObject, project, factory)) 613 { 614 return Collections.emptyList(); 615 } 616 617 // set object info of the the object 618 if (context.isObjectInfoRequired()) 619 { 620 compileObjectData(context, ametysObject, project, null, false, false, userReadOnly, objectInfos, factory); 621 } 622 623 // get parent folder 624 AmetysObject parent = ametysObject.getParent(); 625 //File parent = file.getParentFile(); 626 ObjectData object = compileObjectData(context, parent, project, filterCollection, iaa, false, userReadOnly, objectInfos, factory); 627 628 ObjectParentDataImpl result = new ObjectParentDataImpl(); 629 result.setObject(object); 630 if (irps) 631 { 632 result.setRelativePathSegment(ametysObject.getName()); 633 } 634 635 return Collections.<ObjectParentData> singletonList(result); 636 } 637 /** 638 * get the inputstream to read a file 639 * @param context call context 640 * @param objectId object Id 641 * @param offset offset 642 * @param length lenght 643 * @param factory factory 644 * @return ContentStream 645 */ 646 public ContentStream getContentStream(CallContext context, String objectId, BigInteger offset, BigInteger length, CmisServiceFactory factory) 647 { 648 // get the file 649 AmetysObject ametysObject = factory.getResolver().resolveById(objectId); 650 if (!(ametysObject instanceof ModifiableResource)) 651 { 652 throw new CmisStreamNotSupportedException("Not a file!"); 653 } 654 ModifiableResource res = (ModifiableResource) ametysObject; 655 656 if (res.getLength() == 0) 657 { 658 throw new CmisConstraintException("Document has no content!"); 659 } 660 661 InputStream stream = null; 662 stream = res.getInputStream(); 663 if (offset != null || length != null) 664 { 665 stream = new CmisContentRangeInputStream(stream, offset, length); 666 } 667 668 // compile data 669 ContentStreamImpl result; 670 if ((offset != null && offset.longValue() > 0) || length != null) 671 { 672 result = new PartialContentStreamImpl(); 673 } 674 else 675 { 676 result = new ContentStreamImpl(); 677 } 678 679 result.setFileName(res.getName()); 680 result.setLength(BigInteger.valueOf(res.getLength())); 681 result.setMimeType(res.getMimeType()); 682 result.setStream(stream); 683 684 return result; 685 } 686 687 /** 688 * get an object by it's path 689 * @param context call context 690 * @param project Project 691 * @param folderPath path of the object/folder 692 * @param filter filters for metadata 693 * @param includeAllowableActions allowable actions 694 * @param includeACL ACL 695 * @param objectInfos infos 696 * @param factory factory 697 * @return datas of the object 698 */ 699 public ObjectData getObjectByPath(CallContext context, Project project, String folderPath, String filter, 700 boolean includeAllowableActions, boolean includeACL, ObjectInfoHandler objectInfos, CmisServiceFactory factory) 701 { 702 boolean userReadOnly = false; 703 704 // split filter 705 Set<String> filterCollection = CmisUtils.splitFilter(filter); 706 707 // check path 708 if (folderPath == null || folderPath.length() == 0 || folderPath.charAt(0) != '/') 709 { 710 throw new CmisInvalidArgumentException("Invalid folder path!"); 711 } 712 713 // get the file or folder 714 AmetysObject root = getRoot(project, factory); 715 AmetysObject file = null; 716 if (folderPath.length() == 1) 717 { 718 file = root; 719 } 720 else 721 { 722 file = factory.getResolver().resolveByPath(root.getPath() + folderPath); 723 //String path = folderPath.replace('/', File.separatorChar).substring(1); 724 //file = new File(root, path); 725 } 726 727 if (file == null) 728 { 729 throw new CmisObjectNotFoundException("Path doesn't exist."); 730 } 731 return compileObjectData(context, file, project, filterCollection, includeAllowableActions, includeACL, userReadOnly, 732 objectInfos, factory); 733 } 734 735 /** 736 * Create a new folder in another one 737 * @param context call context 738 * @param properties properties 739 * @param project Project 740 * @param folderId folder Id 741 * @param factory factory 742 * @return id of the created folder 743 */ 744 public String createFolder(CallContext context, Properties properties, Project project, String folderId, CmisServiceFactory factory) 745 { 746 // check properties 747 checkNewProperties(properties, BaseTypeId.CMIS_FOLDER, factory); 748 749 // get parent File 750 AmetysObject ametysObject = factory.getResolver().resolveById(folderId); 751 if (!(ametysObject instanceof ModifiableResourceCollection)) 752 { 753 throw new CmisObjectNotFoundException("Parent is not a folder!"); 754 } 755 756 // create the folder 757 String name = CmisUtils.getStringProperty(properties, PropertyIds.NAME); 758 String description = CmisUtils.getStringProperty(properties, PropertyIds.DESCRIPTION, ""); 759 760 try 761 { 762 Map<String, Object> addFolder; 763 addFolder = factory.getWorkspaceExplorerResourceDAO().addFolder(folderId, name, description, true); 764 return (String) addFolder.get("id"); 765 } 766 catch (IllegalAccessException e) 767 { 768 throw new CmisStorageException("Could not create folder!"); 769 } 770 } 771 772 /** 773 * Create a new document in a folder 774 * @param context call context 775 * @param properties properties 776 * @param project Project 777 * @param folderId folder Id 778 * @param contentStream content Stream 779 * @param versioningState versionning State 780 * @param factory factory 781 * @return id of the created document 782 */ 783 public String createDocument(CallContext context, Properties properties, Project project, String folderId, 784 ContentStream contentStream, VersioningState versioningState, CmisServiceFactory factory) 785 { 786 // check versioning state 787 if (VersioningState.NONE != versioningState) 788 { 789 throw new CmisConstraintException("Versioning not supported!"); 790 } 791 792 // check properties 793 checkNewProperties(properties, BaseTypeId.CMIS_DOCUMENT, factory); 794 795 String name = CmisUtils.getStringProperty(properties, PropertyIds.NAME); 796 AmetysObject ametysObject = factory.getResolver().resolveById(folderId); 797 if (!(ametysObject instanceof ModifiableResourceCollection)) 798 { 799 throw new IllegalClassException(ModifiableResourceCollection.class, ametysObject.getClass()); 800 } 801 ResourceOperationResult resourceOperation = factory.getAddOrUpdateResourceHelper().performResourceOperation(contentStream.getStream(), name, (ModifiableResourceCollection) ametysObject, ResourceOperationMode.ADD_RENAME); 802 if (!resourceOperation.isSuccess()) 803 { 804 throw new CmisStorageException("Could not create file: " + resourceOperation.getErrorMessage()); 805 } 806 807 String id = resourceOperation.getResource().getId(); 808 return id; 809 } 810 811 /** 812 * CMIS deleteObject. 813 * @param context call context 814 * @param objectId object ID 815 * @param factory factory 816 */ 817 public void deleteObject(CallContext context, String objectId, CmisServiceFactory factory) 818 { 819 List<String> toDelete = new ArrayList<>(1); 820 toDelete.add(objectId); 821 Map deleted = factory.getWorkspaceExplorerResourceDAO().deleteObject(toDelete); 822 823 if (deleted.containsKey("message")) 824 { 825 throw new CmisStorageException("Deletion failed : " + deleted.get("message")); 826 } 827 } 828 829 /** 830 * CMIS getFolderParent. 831 * @param context call context 832 * @param project Project 833 * @param folderId folder Id 834 * @param filter filters 835 * @param objectInfos objectInfos 836 * @param factory factory 837 * @return ObjectData 838 */ 839 public ObjectData getFolderParent(CallContext context, Project project, String folderId, String filter, ObjectInfoHandler objectInfos, CmisServiceFactory factory) 840 { 841 boolean userReadOnly = false; 842 AmetysObject ametysObject = factory.getResolver().resolveById(folderId); 843 if (isRoot(ametysObject, project, factory)) 844 { 845 throw new CmisInvalidArgumentException("The root folder has no parent!"); 846 } 847 AmetysObject parent = ametysObject.getParent(); 848 849 Set<String> filterCollection = CmisUtils.splitFilter(filter); 850 ObjectData object = compileObjectData(context, parent, project, filterCollection, false, false, userReadOnly, objectInfos, factory); 851 852 return object; 853 } 854 855 /** 856 * CMIS deleteTree. 857 * @param context call context 858 * @param project Project 859 * @param folderId folder Id 860 * @param factory factory 861 * @return FailedToDeleteData 862 */ 863 public FailedToDeleteData deleteTree(CallContext context, Project project, String folderId, CmisServiceFactory factory) 864 { 865 AmetysObject ametysObject = factory.getResolver().resolveById(folderId); 866 if (ametysObject instanceof ModifiableResourceCollection) 867 { 868 ModifiableResourceCollection folder = (ModifiableResourceCollection) ametysObject; 869 AmetysObjectIterable<AmetysObject> children = folder.getChildren(); 870 List<String> toDelete = new ArrayList<>(); 871 for (AmetysObject child : children) 872 { 873 toDelete.add(child.getId()); 874 875 } 876 Map deletedMsg = factory.getWorkspaceExplorerResourceDAO().deleteObject(toDelete); 877 878 if (deletedMsg.containsKey("message")) 879 { 880 throw new CmisStorageException("Deletion failed : " + deletedMsg.get("message")); 881 } 882 } 883 else 884 { 885 throw new CmisConstraintException("Object is not a folder!"); 886 } 887 888 FailedToDeleteDataImpl result = new FailedToDeleteDataImpl(); 889 result.setIds(new ArrayList<String>()); 890 891 return result; 892 } 893 894 /** 895 * CMIS updateProperties. 896 * @param context call context 897 * @param project Project 898 * @param objectIdHolder objectId in a holder 899 * @param properties properties 900 * @param objectInfos object infos 901 * @param factory factory 902 * @return ObjectData 903 */ 904 public ObjectData updateProperties(CallContext context, Project project, Holder<String> objectIdHolder, Properties properties, 905 ObjectInfoHandler objectInfos, CmisServiceFactory factory) 906 { 907 // check object id 908 if (objectIdHolder == null || objectIdHolder.getValue() == null) 909 { 910 throw new CmisInvalidArgumentException("Id is not valid!"); 911 } 912 String objectId = objectIdHolder.getValue(); 913 boolean userReadOnly = false; 914 915 AmetysObject ametysObject = factory.getResolver().resolveById(objectId); 916 917 try 918 { 919 if (ametysObject != null && ametysObject instanceof ModifiableResource) 920 { 921 ModifiableResource resource = (ModifiableResource) ametysObject; 922 String inputName = CmisUtils.getStringProperty(properties, PropertyIds.NAME, resource.getName()); 923 String description = CmisUtils.getStringProperty(properties, PropertyIds.DESCRIPTION, resource.getDCDescription()); 924 Collection<String> tags = new ArrayList<>(Arrays.asList(resource.getKeywords())); 925 926 factory.getWorkspaceExplorerResourceDAO().editFile(objectId, inputName, description, tags); 927 928 } 929 else if (ametysObject != null && ametysObject instanceof ModifiableResourceCollection) 930 { 931 ModifiableResourceCollection folder = (ModifiableResourceCollection) ametysObject; 932 String inputName = CmisUtils.getStringProperty(properties, PropertyIds.NAME, folder.getName()); 933 String description = CmisUtils.getStringProperty(properties, PropertyIds.DESCRIPTION, folder.getDescription()); 934 if (description == null) 935 { 936 description = StringUtils.EMPTY; 937 } 938 factory.getWorkspaceExplorerResourceDAO().editFolder(objectId, inputName, description); 939 } 940 else 941 { 942 throw new CmisObjectNotFoundException("File not found!"); 943 } 944 } 945 catch (IllegalAccessException e) 946 { 947 throw new CmisRuntimeException(e.getMessage(), e); 948 } 949 950 AmetysObject modified = factory.getResolver().resolveById(objectId); 951 return compileObjectData(context, modified, project, null, false, false, userReadOnly, objectInfos, factory); 952 } 953 954 /** 955 * CMIS setContentStream, deleteContentStream, and appendContentStream. 956 * @param context call context 957 * @param project Project 958 * @param objectIdHolder object Id in a holder 959 * @param overwriteFlag overwrite 960 * @param contentStream inputStream 961 * @param append append 962 * @param factory factory 963 */ 964 public void changeContentStream(CallContext context, Project project, Holder<String> objectIdHolder, Boolean overwriteFlag, 965 ContentStream contentStream, boolean append, CmisServiceFactory factory) 966 { 967 if (objectIdHolder == null || objectIdHolder.getValue() == null) 968 { 969 throw new CmisInvalidArgumentException("Id is not valid!"); 970 } 971 String objectId = objectIdHolder.getValue(); 972 973 AmetysObject ametysObject = factory.getResolver().resolveById(objectId); 974 975 // check overwrite 976 boolean owf = CmisUtils.getBooleanParameter(overwriteFlag, true); 977 if (!owf && contentStream.getLength() > 0) 978 { 979 throw new CmisContentAlreadyExistsException("Content already exists!"); 980 } 981 982 if (ametysObject instanceof ModifiableResource) 983 { 984 String name = ametysObject.getName(); 985 ResourceOperationResult resourceOperation = factory.getAddOrUpdateResourceHelper().performResourceOperation(contentStream.getStream(), name, ametysObject.getParent(), ResourceOperationMode.UPDATE); 986 987 if (!resourceOperation.isSuccess()) 988 { 989 throw new CmisRuntimeException("Impossible to update file : " + resourceOperation.getErrorMessage()); 990 } 991 } 992 else 993 { 994 throw new CmisObjectNotFoundException("File not found!"); 995 } 996 } 997 /** 998 * CMIS moveObject. 999 * @param context call context 1000 * @param project Project 1001 * @param objectId objectId in a holder 1002 * @param targetFolderId folderId 1003 * @param objectInfos objectInfos 1004 * @param factory factory 1005 * @return ObjectData 1006 */ 1007 public ObjectData moveObject(CallContext context, Project project, Holder<String> objectId, String targetFolderId, 1008 ObjectInfoHandler objectInfos, CmisServiceFactory factory) 1009 { 1010 boolean userReadOnly = false; 1011 1012 if (objectId == null) 1013 { 1014 throw new CmisInvalidArgumentException("Id is not valid!"); 1015 } 1016 1017 List<String> documentIds = new ArrayList<>(1); 1018 documentIds.add(objectId.getValue()); 1019 1020 Map<String, Object> result; 1021 try 1022 { 1023 result = factory.getWorkspaceExplorerResourceDAO().moveDocuments(documentIds, targetFolderId); 1024 if (result.containsKey("message")) 1025 { 1026 throw new CmisStorageException((String) result.get("message")); 1027 } 1028 else 1029 { 1030 AmetysObject ametysObject = factory.getResolver().resolveById(objectId.getValue()); 1031 return compileObjectData(context, ametysObject, project, null, false, false, userReadOnly, objectInfos, factory); 1032 } 1033 } 1034 catch (RepositoryException e) 1035 { 1036 throw new CmisStorageException("Impossible to move file", e); 1037 } 1038 1039 1040 } 1041 1042 /* 1043 * private helpers 1044 * 1045 */ 1046 1047 /* 1048 * Checks a property set for a new object. 1049 */ 1050 private void checkNewProperties(Properties properties, BaseTypeId baseTypeId, CmisServiceFactory factory) 1051 { 1052 // check properties 1053 if (properties == null || properties.getProperties() == null) 1054 { 1055 throw new CmisInvalidArgumentException("Properties must be set!"); 1056 } 1057 1058 // check the name 1059 /* 1060 String name = CmisUtils.getStringProperty(properties, PropertyIds.NAME); 1061 if (!isValidName(name)) { 1062 throw new CmisNameConstraintViolationException("Name is not valid!"); 1063 }*/ 1064 1065 // check the type 1066 String typeId = CmisUtils.getObjectTypeId(properties); 1067 if (typeId == null) 1068 { 1069 throw new CmisInvalidArgumentException("Type Id is not set!"); 1070 } 1071 1072 TypeDefinition type = factory.getTypeManager().getInternalTypeDefinition(typeId); 1073 if (type == null) 1074 { 1075 throw new CmisObjectNotFoundException("Type '" + typeId + "' is unknown!"); 1076 } 1077 1078 if (type.getBaseTypeId() != baseTypeId) 1079 { 1080 if (baseTypeId == BaseTypeId.CMIS_DOCUMENT) 1081 { 1082 throw new CmisInvalidArgumentException("Type is not a document type!"); 1083 } 1084 else if (baseTypeId == BaseTypeId.CMIS_DOCUMENT) 1085 { 1086 throw new CmisInvalidArgumentException("Type is not a folder type!"); 1087 } 1088 else 1089 { 1090 throw new CmisRuntimeException("A file system does not support a " + baseTypeId.value() + " type!"); 1091 } 1092 } 1093 1094 // check type properties 1095 checkTypeProperties(properties, typeId, factory, true); 1096 1097 // check if required properties are missing 1098 for (PropertyDefinition<?> propDef : type.getPropertyDefinitions().values()) 1099 { 1100 if (propDef.isRequired() && !properties.getProperties().containsKey(propDef.getId()) 1101 && propDef.getUpdatability() != Updatability.READONLY) 1102 { 1103 throw new CmisConstraintException("Property '" + propDef.getId() + "' is required!"); 1104 } 1105 } 1106 } 1107 1108 /* 1109 * Checks if the property belong to the type and are settable. 1110 */ 1111 private void checkTypeProperties(Properties properties, String typeId, CmisServiceFactory factory, boolean isCreate) 1112 { 1113 // check type 1114 TypeDefinition type = factory.getTypeManager().getInternalTypeDefinition(typeId); 1115 if (type == null) 1116 { 1117 throw new CmisObjectNotFoundException("Type '" + typeId + "' is unknown!"); 1118 } 1119 1120 // check if all required properties are there 1121 for (PropertyData<?> prop : properties.getProperties().values()) 1122 { 1123 PropertyDefinition<?> propType = type.getPropertyDefinitions().get(prop.getId()); 1124 1125 // do we know that property? 1126 if (propType == null) 1127 { 1128 throw new CmisConstraintException("Property '" + prop.getId() + "' is unknown!"); 1129 } 1130 1131 // can it be set? 1132 if (propType.getUpdatability() == Updatability.READONLY) 1133 { 1134 throw new CmisConstraintException("Property '" + prop.getId() + "' is readonly!"); 1135 } 1136 1137 if (!isCreate) 1138 { 1139 // can it be set? 1140 if (propType.getUpdatability() == Updatability.ONCREATE) 1141 { 1142 throw new CmisConstraintException("Property '" + prop.getId() + "' cannot be updated!"); 1143 } 1144 } 1145 } 1146 } 1147 1148 private void addPropertyId(PropertiesImpl props, String typeId, Set<String> filter, String id, String value, CmisServiceFactory factory) 1149 { 1150 if (!checkAddProperty(props, typeId, filter, id, factory)) 1151 { 1152 return; 1153 } 1154 1155 props.addProperty(new PropertyIdImpl(id, value)); 1156 } 1157 1158 private void addPropertyIdList(PropertiesImpl props, String typeId, Set<String> filter, String id, 1159 List<String> value, CmisServiceFactory factory) 1160 { 1161 if (!checkAddProperty(props, typeId, filter, id, factory)) 1162 { 1163 return; 1164 } 1165 1166 props.addProperty(new PropertyIdImpl(id, value)); 1167 } 1168 1169 private void addPropertyString(PropertiesImpl props, String typeId, Set<String> filter, String id, String value, CmisServiceFactory factory) 1170 { 1171 if (!checkAddProperty(props, typeId, filter, id, factory)) 1172 { 1173 return; 1174 } 1175 1176 props.addProperty(new PropertyStringImpl(id, value)); 1177 } 1178 1179 private void addPropertyInteger(PropertiesImpl props, String typeId, Set<String> filter, String id, long value, CmisServiceFactory factory) 1180 { 1181 addPropertyBigInteger(props, typeId, filter, id, BigInteger.valueOf(value), factory); 1182 } 1183 1184 private void addPropertyBigInteger(PropertiesImpl props, String typeId, Set<String> filter, String id, 1185 BigInteger value, CmisServiceFactory factory) 1186 { 1187 if (!checkAddProperty(props, typeId, filter, id, factory)) 1188 { 1189 return; 1190 } 1191 1192 props.addProperty(new PropertyIntegerImpl(id, value)); 1193 } 1194 1195 private void addPropertyBoolean(PropertiesImpl props, String typeId, Set<String> filter, String id, boolean value, CmisServiceFactory factory) 1196 { 1197 if (!checkAddProperty(props, typeId, filter, id, factory)) 1198 { 1199 return; 1200 } 1201 1202 props.addProperty(new PropertyBooleanImpl(id, value)); 1203 } 1204 1205 private void addPropertyDateTime(PropertiesImpl props, String typeId, Set<String> filter, String id, 1206 GregorianCalendar value, CmisServiceFactory factory) 1207 { 1208 if (!checkAddProperty(props, typeId, filter, id, factory)) 1209 { 1210 return; 1211 } 1212 1213 props.addProperty(new PropertyDateTimeImpl(id, value)); 1214 } 1215 1216 private boolean checkAddProperty(Properties properties, String typeId, Set<String> filter, String id, CmisServiceFactory factory) 1217 { 1218 if ((properties == null) || (properties.getProperties() == null)) 1219 { 1220 throw new IllegalArgumentException("Properties must not be null!"); 1221 } 1222 1223 if (id == null) 1224 { 1225 throw new IllegalArgumentException("Id must not be null!"); 1226 } 1227 1228 TypeDefinition type = factory.getTypeManager().getInternalTypeDefinition(typeId); 1229 if (type == null) 1230 { 1231 throw new IllegalArgumentException("Unknown type: " + typeId); 1232 } 1233 if (!type.getPropertyDefinitions().containsKey(id)) 1234 { 1235 throw new IllegalArgumentException("Unknown property: " + id); 1236 } 1237 1238 String queryName = type.getPropertyDefinitions().get(id).getQueryName(); 1239 1240 if ((queryName != null) && (filter != null)) 1241 { 1242 if (!filter.contains(queryName)) 1243 { 1244 return false; 1245 } 1246 else 1247 { 1248 filter.remove(queryName); 1249 } 1250 } 1251 1252 return true; 1253 } 1254 1255 /* 1256 * Compiles the allowable actions for a file or folder. 1257 */ 1258 private AllowableActions compileAllowableActions(AmetysObject file, Project project, CmisServiceFactory factory, boolean userReadOnly) 1259 { 1260 if (file == null) 1261 { 1262 throw new IllegalArgumentException("File must not be null!"); 1263 } 1264 1265 boolean isReadOnly = false; 1266 boolean isRoot = isRoot(file, project, factory); 1267 1268 Set<Action> aas = EnumSet.noneOf(Action.class); 1269 1270 addAction(aas, Action.CAN_GET_OBJECT_PARENTS, !isRoot); 1271 addAction(aas, Action.CAN_GET_PROPERTIES, true); 1272 addAction(aas, Action.CAN_UPDATE_PROPERTIES, !userReadOnly && !isReadOnly); 1273 addAction(aas, Action.CAN_MOVE_OBJECT, !userReadOnly && !isRoot); 1274 addAction(aas, Action.CAN_DELETE_OBJECT, !userReadOnly && !isReadOnly && !isRoot); 1275 addAction(aas, Action.CAN_GET_ACL, true); 1276 1277 if (file instanceof ModifiableResourceCollection) 1278 { 1279 addAction(aas, Action.CAN_GET_DESCENDANTS, true); 1280 addAction(aas, Action.CAN_GET_CHILDREN, true); 1281 addAction(aas, Action.CAN_GET_FOLDER_PARENT, !isRoot); 1282 addAction(aas, Action.CAN_GET_FOLDER_TREE, true); 1283 addAction(aas, Action.CAN_CREATE_DOCUMENT, !userReadOnly); 1284 addAction(aas, Action.CAN_CREATE_FOLDER, !userReadOnly); 1285 addAction(aas, Action.CAN_DELETE_TREE, !userReadOnly && !isReadOnly); 1286 } 1287 else if (file instanceof ModifiableResource) 1288 { 1289 ModifiableResource res = (ModifiableResource) file; 1290 addAction(aas, Action.CAN_GET_CONTENT_STREAM, res.getLength() > 0); 1291 addAction(aas, Action.CAN_SET_CONTENT_STREAM, !userReadOnly && !isReadOnly); 1292 addAction(aas, Action.CAN_DELETE_CONTENT_STREAM, !userReadOnly && !isReadOnly); 1293 addAction(aas, Action.CAN_GET_ALL_VERSIONS, true); 1294 } 1295 1296 AllowableActionsImpl result = new AllowableActionsImpl(); 1297 result.setAllowableActions(aas); 1298 1299 return result; 1300 } 1301 private void addAction(Set<Action> aas, Action action, boolean condition) 1302 { 1303 if (condition) 1304 { 1305 aas.add(action); 1306 } 1307 } 1308 1309 private Boolean isRoot(ModifiableResourceCollection object, Project project, DocumentWorkspaceModule documentModule) 1310 { 1311 ModifiableResourceCollection documentRoot = documentModule.getModuleRoot(project, false); 1312 return documentRoot.getId().equals(object.getId()); 1313 } 1314 private Boolean isRoot(AmetysObject ametysObject, Project project, CmisServiceFactory factory) 1315 { 1316 if (ametysObject instanceof ModifiableResourceCollection) 1317 { 1318 return isRoot((ModifiableResourceCollection) ametysObject, project, factory.getDocumentModule()); 1319 } 1320 else 1321 { 1322 return false; 1323 } 1324 } 1325 1326 private ModifiableResourceCollection getRoot(Project project, CmisServiceFactory factory) 1327 { 1328 return factory.getDocumentModule().getModuleRoot(project, false); 1329 } 1330 1331 1332}