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.lang3.StringUtils; 086 087import org.ametys.core.util.URIUtils; 088import org.ametys.plugins.explorer.resources.ModifiableResource; 089import org.ametys.plugins.explorer.resources.ModifiableResourceCollection; 090import org.ametys.plugins.explorer.resources.ResourceCollection; 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 ResourceCollection collection = factory.getResolver().resolveById(folderId); 790 if (!(collection instanceof ModifiableResourceCollection)) 791 { 792 throw new IllegalArgumentException("Cannot create file on a non modifiable folder '" + folderId + "'"); 793 } 794 795 ModifiableResourceCollection mCollection = (ModifiableResourceCollection) collection; 796 factory.getAddOrUpdateResourceHelper().checkAddResourceRight(mCollection); 797 ResourceOperationResult resourceOperation = factory.getAddOrUpdateResourceHelper().performResourceOperation(contentStream.getStream(), name, mCollection, ResourceOperationMode.ADD_RENAME); 798 if (!resourceOperation.isSuccess()) 799 { 800 throw new CmisStorageException("Could not create file: " + resourceOperation.getErrorMessage()); 801 } 802 803 String id = resourceOperation.getResource().getId(); 804 return id; 805 } 806 807 /** 808 * CMIS deleteObject. 809 * @param context call context 810 * @param objectId object ID 811 * @param factory factory 812 */ 813 public void deleteObject(CallContext context, String objectId, CmisServiceFactory factory) 814 { 815 List<String> toDelete = new ArrayList<>(1); 816 toDelete.add(objectId); 817 Map deleted = factory.getWorkspaceExplorerResourceDAO().deleteObject(toDelete); 818 819 if (deleted.containsKey("message")) 820 { 821 throw new CmisStorageException("Deletion failed : " + deleted.get("message")); 822 } 823 } 824 825 /** 826 * CMIS getFolderParent. 827 * @param context call context 828 * @param project Project 829 * @param folderId folder Id 830 * @param filter filters 831 * @param objectInfos objectInfos 832 * @param factory factory 833 * @return ObjectData 834 */ 835 public ObjectData getFolderParent(CallContext context, Project project, String folderId, String filter, ObjectInfoHandler objectInfos, CmisServiceFactory factory) 836 { 837 boolean userReadOnly = false; 838 AmetysObject ametysObject = factory.getResolver().resolveById(folderId); 839 if (isRoot(ametysObject, project, factory)) 840 { 841 throw new CmisInvalidArgumentException("The root folder has no parent!"); 842 } 843 AmetysObject parent = ametysObject.getParent(); 844 845 Set<String> filterCollection = CmisUtils.splitFilter(filter); 846 ObjectData object = compileObjectData(context, parent, project, filterCollection, false, false, userReadOnly, objectInfos, factory); 847 848 return object; 849 } 850 851 /** 852 * CMIS deleteTree. 853 * @param context call context 854 * @param project Project 855 * @param folderId folder Id 856 * @param factory factory 857 * @return FailedToDeleteData 858 */ 859 public FailedToDeleteData deleteTree(CallContext context, Project project, String folderId, CmisServiceFactory factory) 860 { 861 AmetysObject ametysObject = factory.getResolver().resolveById(folderId); 862 if (ametysObject instanceof ModifiableResourceCollection) 863 { 864 ModifiableResourceCollection folder = (ModifiableResourceCollection) ametysObject; 865 AmetysObjectIterable<AmetysObject> children = folder.getChildren(); 866 List<String> toDelete = new ArrayList<>(); 867 for (AmetysObject child : children) 868 { 869 toDelete.add(child.getId()); 870 871 } 872 Map deletedMsg = factory.getWorkspaceExplorerResourceDAO().deleteObject(toDelete); 873 874 if (deletedMsg.containsKey("message")) 875 { 876 throw new CmisStorageException("Deletion failed : " + deletedMsg.get("message")); 877 } 878 } 879 else 880 { 881 throw new CmisConstraintException("Object is not a folder!"); 882 } 883 884 FailedToDeleteDataImpl result = new FailedToDeleteDataImpl(); 885 result.setIds(new ArrayList<>()); 886 887 return result; 888 } 889 890 /** 891 * CMIS updateProperties. 892 * @param context call context 893 * @param project Project 894 * @param objectIdHolder objectId in a holder 895 * @param properties properties 896 * @param objectInfos object infos 897 * @param factory factory 898 * @return ObjectData 899 */ 900 public ObjectData updateProperties(CallContext context, Project project, Holder<String> objectIdHolder, Properties properties, 901 ObjectInfoHandler objectInfos, CmisServiceFactory factory) 902 { 903 // check object id 904 if (objectIdHolder == null || objectIdHolder.getValue() == null) 905 { 906 throw new CmisInvalidArgumentException("Id is not valid!"); 907 } 908 String objectId = objectIdHolder.getValue(); 909 boolean userReadOnly = false; 910 911 AmetysObject ametysObject = factory.getResolver().resolveById(objectId); 912 913 if (ametysObject != null && ametysObject instanceof ModifiableResource) 914 { 915 ModifiableResource resource = (ModifiableResource) ametysObject; 916 String inputName = CmisUtils.getStringProperty(properties, PropertyIds.NAME, resource.getName()); 917 String description = CmisUtils.getStringProperty(properties, PropertyIds.DESCRIPTION, resource.getDCDescription()); 918 Collection<String> tags = new ArrayList<>(Arrays.asList(resource.getKeywords())); 919 920 factory.getWorkspaceExplorerResourceDAO().editFile(objectId, inputName, description, tags); 921 922 } 923 else if (ametysObject != null && ametysObject instanceof ModifiableResourceCollection) 924 { 925 ModifiableResourceCollection folder = (ModifiableResourceCollection) ametysObject; 926 String inputName = CmisUtils.getStringProperty(properties, PropertyIds.NAME, folder.getName()); 927 String description = CmisUtils.getStringProperty(properties, PropertyIds.DESCRIPTION, folder.getDescription()); 928 if (description == null) 929 { 930 description = StringUtils.EMPTY; 931 } 932 factory.getWorkspaceExplorerResourceDAO().editFolder(objectId, inputName, description); 933 } 934 else 935 { 936 throw new CmisObjectNotFoundException("File not found!"); 937 } 938 939 AmetysObject modified = factory.getResolver().resolveById(objectId); 940 return compileObjectData(context, modified, project, null, false, false, userReadOnly, objectInfos, factory); 941 } 942 943 /** 944 * CMIS setContentStream, deleteContentStream, and appendContentStream. 945 * @param context call context 946 * @param project Project 947 * @param objectIdHolder object Id in a holder 948 * @param overwriteFlag overwrite 949 * @param contentStream inputStream 950 * @param append append 951 * @param factory factory 952 */ 953 public void changeContentStream(CallContext context, Project project, Holder<String> objectIdHolder, Boolean overwriteFlag, 954 ContentStream contentStream, boolean append, CmisServiceFactory factory) 955 { 956 if (objectIdHolder == null || objectIdHolder.getValue() == null) 957 { 958 throw new CmisInvalidArgumentException("Id is not valid!"); 959 } 960 String objectId = objectIdHolder.getValue(); 961 962 AmetysObject ametysObject = factory.getResolver().resolveById(objectId); 963 964 // check overwrite 965 boolean owf = CmisUtils.getBooleanParameter(overwriteFlag, true); 966 if (!owf && contentStream.getLength() > 0) 967 { 968 throw new CmisContentAlreadyExistsException("Content already exists!"); 969 } 970 971 if (ametysObject instanceof ModifiableResource) 972 { 973 factory.getAddOrUpdateResourceHelper().checkAddResourceRight((ModifiableResourceCollection) ametysObject); 974 975 String name = ametysObject.getName(); 976 ResourceOperationResult resourceOperation = factory.getAddOrUpdateResourceHelper().performResourceOperation(contentStream.getStream(), name, ametysObject.getParent(), ResourceOperationMode.UPDATE); 977 978 if (!resourceOperation.isSuccess()) 979 { 980 throw new CmisRuntimeException("Impossible to update file : " + resourceOperation.getErrorMessage()); 981 } 982 } 983 else 984 { 985 throw new CmisObjectNotFoundException("File not found!"); 986 } 987 } 988 /** 989 * CMIS moveObject. 990 * @param context call context 991 * @param project Project 992 * @param objectId objectId in a holder 993 * @param targetFolderId folderId 994 * @param objectInfos objectInfos 995 * @param factory factory 996 * @return ObjectData 997 */ 998 public ObjectData moveObject(CallContext context, Project project, Holder<String> objectId, String targetFolderId, 999 ObjectInfoHandler objectInfos, CmisServiceFactory factory) 1000 { 1001 boolean userReadOnly = false; 1002 1003 if (objectId == null) 1004 { 1005 throw new CmisInvalidArgumentException("Id is not valid!"); 1006 } 1007 1008 List<String> documentIds = new ArrayList<>(1); 1009 documentIds.add(objectId.getValue()); 1010 1011 Map<String, Object> result; 1012 try 1013 { 1014 result = factory.getWorkspaceExplorerResourceDAO().moveDocuments(documentIds, targetFolderId); 1015 if (result.containsKey("message")) 1016 { 1017 throw new CmisStorageException((String) result.get("message")); 1018 } 1019 else 1020 { 1021 AmetysObject ametysObject = factory.getResolver().resolveById(objectId.getValue()); 1022 return compileObjectData(context, ametysObject, project, null, false, false, userReadOnly, objectInfos, factory); 1023 } 1024 } 1025 catch (RepositoryException e) 1026 { 1027 throw new CmisStorageException("Impossible to move file", e); 1028 } 1029 1030 1031 } 1032 1033 /* 1034 * private helpers 1035 * 1036 */ 1037 1038 /* 1039 * Checks a property set for a new object. 1040 */ 1041 private void checkNewProperties(Properties properties, BaseTypeId baseTypeId, CmisServiceFactory factory) 1042 { 1043 // check properties 1044 if (properties == null || properties.getProperties() == null) 1045 { 1046 throw new CmisInvalidArgumentException("Properties must be set!"); 1047 } 1048 1049 // check the name 1050 /* 1051 String name = CmisUtils.getStringProperty(properties, PropertyIds.NAME); 1052 if (!isValidName(name)) { 1053 throw new CmisNameConstraintViolationException("Name is not valid!"); 1054 }*/ 1055 1056 // check the type 1057 String typeId = CmisUtils.getObjectTypeId(properties); 1058 if (typeId == null) 1059 { 1060 throw new CmisInvalidArgumentException("Type Id is not set!"); 1061 } 1062 1063 TypeDefinition type = factory.getTypeManager().getInternalTypeDefinition(typeId); 1064 if (type == null) 1065 { 1066 throw new CmisObjectNotFoundException("Type '" + typeId + "' is unknown!"); 1067 } 1068 1069 if (type.getBaseTypeId() != baseTypeId) 1070 { 1071 if (baseTypeId == BaseTypeId.CMIS_DOCUMENT) 1072 { 1073 throw new CmisInvalidArgumentException("Type is not a document type!"); 1074 } 1075 else if (baseTypeId == BaseTypeId.CMIS_DOCUMENT) 1076 { 1077 throw new CmisInvalidArgumentException("Type is not a folder type!"); 1078 } 1079 else 1080 { 1081 throw new CmisRuntimeException("A file system does not support a " + baseTypeId.value() + " type!"); 1082 } 1083 } 1084 1085 // check type properties 1086 checkTypeProperties(properties, typeId, factory, true); 1087 1088 // check if required properties are missing 1089 for (PropertyDefinition<?> propDef : type.getPropertyDefinitions().values()) 1090 { 1091 if (propDef.isRequired() && !properties.getProperties().containsKey(propDef.getId()) 1092 && propDef.getUpdatability() != Updatability.READONLY) 1093 { 1094 throw new CmisConstraintException("Property '" + propDef.getId() + "' is required!"); 1095 } 1096 } 1097 } 1098 1099 /* 1100 * Checks if the property belong to the type and are settable. 1101 */ 1102 private void checkTypeProperties(Properties properties, String typeId, CmisServiceFactory factory, boolean isCreate) 1103 { 1104 // check type 1105 TypeDefinition type = factory.getTypeManager().getInternalTypeDefinition(typeId); 1106 if (type == null) 1107 { 1108 throw new CmisObjectNotFoundException("Type '" + typeId + "' is unknown!"); 1109 } 1110 1111 // check if all required properties are there 1112 for (PropertyData<?> prop : properties.getProperties().values()) 1113 { 1114 PropertyDefinition<?> propType = type.getPropertyDefinitions().get(prop.getId()); 1115 1116 // do we know that property? 1117 if (propType == null) 1118 { 1119 throw new CmisConstraintException("Property '" + prop.getId() + "' is unknown!"); 1120 } 1121 1122 // can it be set? 1123 if (propType.getUpdatability() == Updatability.READONLY) 1124 { 1125 throw new CmisConstraintException("Property '" + prop.getId() + "' is readonly!"); 1126 } 1127 1128 if (!isCreate) 1129 { 1130 // can it be set? 1131 if (propType.getUpdatability() == Updatability.ONCREATE) 1132 { 1133 throw new CmisConstraintException("Property '" + prop.getId() + "' cannot be updated!"); 1134 } 1135 } 1136 } 1137 } 1138 1139 private void addPropertyId(PropertiesImpl props, String typeId, Set<String> filter, String id, String value, CmisServiceFactory factory) 1140 { 1141 if (!checkAddProperty(props, typeId, filter, id, factory)) 1142 { 1143 return; 1144 } 1145 1146 props.addProperty(new PropertyIdImpl(id, value)); 1147 } 1148 1149 private void addPropertyIdList(PropertiesImpl props, String typeId, Set<String> filter, String id, 1150 List<String> value, CmisServiceFactory factory) 1151 { 1152 if (!checkAddProperty(props, typeId, filter, id, factory)) 1153 { 1154 return; 1155 } 1156 1157 props.addProperty(new PropertyIdImpl(id, value)); 1158 } 1159 1160 private void addPropertyString(PropertiesImpl props, String typeId, Set<String> filter, String id, String value, CmisServiceFactory factory) 1161 { 1162 if (!checkAddProperty(props, typeId, filter, id, factory)) 1163 { 1164 return; 1165 } 1166 1167 props.addProperty(new PropertyStringImpl(id, value)); 1168 } 1169 1170 private void addPropertyInteger(PropertiesImpl props, String typeId, Set<String> filter, String id, long value, CmisServiceFactory factory) 1171 { 1172 addPropertyBigInteger(props, typeId, filter, id, BigInteger.valueOf(value), factory); 1173 } 1174 1175 private void addPropertyBigInteger(PropertiesImpl props, String typeId, Set<String> filter, String id, 1176 BigInteger value, CmisServiceFactory factory) 1177 { 1178 if (!checkAddProperty(props, typeId, filter, id, factory)) 1179 { 1180 return; 1181 } 1182 1183 props.addProperty(new PropertyIntegerImpl(id, value)); 1184 } 1185 1186 private void addPropertyBoolean(PropertiesImpl props, String typeId, Set<String> filter, String id, boolean value, CmisServiceFactory factory) 1187 { 1188 if (!checkAddProperty(props, typeId, filter, id, factory)) 1189 { 1190 return; 1191 } 1192 1193 props.addProperty(new PropertyBooleanImpl(id, value)); 1194 } 1195 1196 private void addPropertyDateTime(PropertiesImpl props, String typeId, Set<String> filter, String id, 1197 GregorianCalendar value, CmisServiceFactory factory) 1198 { 1199 if (!checkAddProperty(props, typeId, filter, id, factory)) 1200 { 1201 return; 1202 } 1203 1204 props.addProperty(new PropertyDateTimeImpl(id, value)); 1205 } 1206 1207 private boolean checkAddProperty(Properties properties, String typeId, Set<String> filter, String id, CmisServiceFactory factory) 1208 { 1209 if (properties == null || properties.getProperties() == null) 1210 { 1211 throw new IllegalArgumentException("Properties must not be null!"); 1212 } 1213 1214 if (id == null) 1215 { 1216 throw new IllegalArgumentException("Id must not be null!"); 1217 } 1218 1219 TypeDefinition type = factory.getTypeManager().getInternalTypeDefinition(typeId); 1220 if (type == null) 1221 { 1222 throw new IllegalArgumentException("Unknown type: " + typeId); 1223 } 1224 if (!type.getPropertyDefinitions().containsKey(id)) 1225 { 1226 throw new IllegalArgumentException("Unknown property: " + id); 1227 } 1228 1229 String queryName = type.getPropertyDefinitions().get(id).getQueryName(); 1230 1231 if (queryName != null && filter != null) 1232 { 1233 if (!filter.contains(queryName)) 1234 { 1235 return false; 1236 } 1237 else 1238 { 1239 filter.remove(queryName); 1240 } 1241 } 1242 1243 return true; 1244 } 1245 1246 /* 1247 * Compiles the allowable actions for a file or folder. 1248 */ 1249 private AllowableActions compileAllowableActions(AmetysObject file, Project project, CmisServiceFactory factory, boolean userReadOnly) 1250 { 1251 if (file == null) 1252 { 1253 throw new IllegalArgumentException("File must not be null!"); 1254 } 1255 1256 boolean isReadOnly = false; 1257 boolean isRoot = isRoot(file, project, factory); 1258 1259 Set<Action> aas = EnumSet.noneOf(Action.class); 1260 1261 addAction(aas, Action.CAN_GET_OBJECT_PARENTS, !isRoot); 1262 addAction(aas, Action.CAN_GET_PROPERTIES, true); 1263 addAction(aas, Action.CAN_UPDATE_PROPERTIES, !userReadOnly && !isReadOnly); 1264 addAction(aas, Action.CAN_MOVE_OBJECT, !userReadOnly && !isRoot); 1265 addAction(aas, Action.CAN_DELETE_OBJECT, !userReadOnly && !isReadOnly && !isRoot); 1266 addAction(aas, Action.CAN_GET_ACL, true); 1267 1268 if (file instanceof ModifiableResourceCollection) 1269 { 1270 addAction(aas, Action.CAN_GET_DESCENDANTS, true); 1271 addAction(aas, Action.CAN_GET_CHILDREN, true); 1272 addAction(aas, Action.CAN_GET_FOLDER_PARENT, !isRoot); 1273 addAction(aas, Action.CAN_GET_FOLDER_TREE, true); 1274 addAction(aas, Action.CAN_CREATE_DOCUMENT, !userReadOnly); 1275 addAction(aas, Action.CAN_CREATE_FOLDER, !userReadOnly); 1276 addAction(aas, Action.CAN_DELETE_TREE, !userReadOnly && !isReadOnly); 1277 } 1278 else if (file instanceof ModifiableResource) 1279 { 1280 ModifiableResource res = (ModifiableResource) file; 1281 addAction(aas, Action.CAN_GET_CONTENT_STREAM, res.getLength() > 0); 1282 addAction(aas, Action.CAN_SET_CONTENT_STREAM, !userReadOnly && !isReadOnly); 1283 addAction(aas, Action.CAN_DELETE_CONTENT_STREAM, !userReadOnly && !isReadOnly); 1284 addAction(aas, Action.CAN_GET_ALL_VERSIONS, true); 1285 } 1286 1287 AllowableActionsImpl result = new AllowableActionsImpl(); 1288 result.setAllowableActions(aas); 1289 1290 return result; 1291 } 1292 private void addAction(Set<Action> aas, Action action, boolean condition) 1293 { 1294 if (condition) 1295 { 1296 aas.add(action); 1297 } 1298 } 1299 1300 private Boolean isRoot(ModifiableResourceCollection object, Project project, DocumentWorkspaceModule documentModule) 1301 { 1302 ModifiableResourceCollection documentRoot = documentModule.getModuleRoot(project, false); 1303 return documentRoot.getId().equals(object.getId()); 1304 } 1305 private Boolean isRoot(AmetysObject ametysObject, Project project, CmisServiceFactory factory) 1306 { 1307 if (ametysObject instanceof ModifiableResourceCollection) 1308 { 1309 return isRoot((ModifiableResourceCollection) ametysObject, project, factory.getDocumentModule()); 1310 } 1311 else 1312 { 1313 return false; 1314 } 1315 } 1316 1317 private ModifiableResourceCollection getRoot(Project project, CmisServiceFactory factory) 1318 { 1319 return factory.getDocumentModule().getModuleRoot(project, false); 1320 } 1321 1322 1323}