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