001/* 002 * Copyright 2017 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.workspaces.cmis; 017 018import java.io.InputStream; 019import java.math.BigInteger; 020import java.util.ArrayList; 021import java.util.Arrays; 022import java.util.Collection; 023import java.util.Collections; 024import java.util.Date; 025import java.util.EnumSet; 026import java.util.GregorianCalendar; 027import java.util.HashSet; 028import java.util.List; 029import java.util.Map; 030import java.util.Set; 031 032import javax.jcr.RepositoryException; 033 034import org.apache.chemistry.opencmis.commons.PropertyIds; 035import org.apache.chemistry.opencmis.commons.data.AllowableActions; 036import org.apache.chemistry.opencmis.commons.data.ContentStream; 037import org.apache.chemistry.opencmis.commons.data.FailedToDeleteData; 038import org.apache.chemistry.opencmis.commons.data.ObjectData; 039import org.apache.chemistry.opencmis.commons.data.ObjectInFolderData; 040import org.apache.chemistry.opencmis.commons.data.ObjectInFolderList; 041import org.apache.chemistry.opencmis.commons.data.ObjectParentData; 042import org.apache.chemistry.opencmis.commons.data.Properties; 043import org.apache.chemistry.opencmis.commons.data.PropertyData; 044import org.apache.chemistry.opencmis.commons.data.RepositoryInfo; 045import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition; 046import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition; 047import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionList; 048import org.apache.chemistry.opencmis.commons.enums.Action; 049import org.apache.chemistry.opencmis.commons.enums.BaseTypeId; 050import org.apache.chemistry.opencmis.commons.enums.CapabilityAcl; 051import org.apache.chemistry.opencmis.commons.enums.CapabilityChanges; 052import org.apache.chemistry.opencmis.commons.enums.CapabilityContentStreamUpdates; 053import org.apache.chemistry.opencmis.commons.enums.CapabilityJoin; 054import org.apache.chemistry.opencmis.commons.enums.CapabilityRenditions; 055import org.apache.chemistry.opencmis.commons.enums.CmisVersion; 056import org.apache.chemistry.opencmis.commons.enums.Updatability; 057import org.apache.chemistry.opencmis.commons.enums.VersioningState; 058import org.apache.chemistry.opencmis.commons.exceptions.CmisBaseException; 059import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException; 060import org.apache.chemistry.opencmis.commons.exceptions.CmisContentAlreadyExistsException; 061import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException; 062import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException; 063import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException; 064import org.apache.chemistry.opencmis.commons.exceptions.CmisStorageException; 065import org.apache.chemistry.opencmis.commons.exceptions.CmisStreamNotSupportedException; 066import org.apache.chemistry.opencmis.commons.impl.dataobjects.AllowableActionsImpl; 067import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl; 068import org.apache.chemistry.opencmis.commons.impl.dataobjects.FailedToDeleteDataImpl; 069import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectDataImpl; 070import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectInFolderDataImpl; 071import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectInFolderListImpl; 072import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectParentDataImpl; 073import org.apache.chemistry.opencmis.commons.impl.dataobjects.PartialContentStreamImpl; 074import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertiesImpl; 075import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyBooleanImpl; 076import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyDateTimeImpl; 077import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIdImpl; 078import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIntegerImpl; 079import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyStringImpl; 080import org.apache.chemistry.opencmis.commons.impl.dataobjects.RepositoryCapabilitiesImpl; 081import org.apache.chemistry.opencmis.commons.impl.dataobjects.RepositoryInfoImpl; 082import org.apache.chemistry.opencmis.commons.impl.server.ObjectInfoImpl; 083import org.apache.chemistry.opencmis.commons.server.CallContext; 084import org.apache.chemistry.opencmis.commons.server.ObjectInfoHandler; 085import org.apache.chemistry.opencmis.commons.spi.Holder; 086import org.apache.commons.lang.IllegalClassException; 087import org.apache.commons.lang3.StringUtils; 088 089import org.ametys.core.util.URIUtils; 090import org.ametys.plugins.explorer.resources.ModifiableResource; 091import org.ametys.plugins.explorer.resources.ModifiableResourceCollection; 092import org.ametys.plugins.explorer.resources.actions.AddOrUpdateResourceHelper.ResourceOperationMode; 093import org.ametys.plugins.explorer.resources.actions.AddOrUpdateResourceHelper.ResourceOperationResult; 094import org.ametys.plugins.repository.AmetysObject; 095import org.ametys.plugins.repository.AmetysObjectIterable; 096import org.ametys.plugins.workspaces.documents.DocumentWorkspaceModule; 097import org.ametys.plugins.workspaces.project.objects.Project; 098 099/** 100 * Helper class to retreive CMIS objects 101 * 102 */ 103public class CmisRepository 104{ 105 private static final String USER_UNKNOWN = "<unknown>"; 106 107 /** 108 * retreive informations for a repository 109 * @param context call context 110 * @param project project 111 * @param factory factory 112 * @return RepositoryInfo 113 */ 114 public RepositoryInfo getRepositoryInfo(CallContext context, Project project, CmisServiceFactory factory) 115 { 116 String id = project.getId(); 117 String name = project.getName(); 118 if (id == null || id.trim().length() == 0 || name == null || name.trim().length() == 0) 119 { 120 throw new CmisInvalidArgumentException("Invalid repository!"); 121 } 122 123 // set up repository infos 124 return createRepositoryInfo(project, factory, CmisVersion.CMIS_1_1); 125 } 126 127 private RepositoryInfo createRepositoryInfo(Project project, CmisServiceFactory factory, CmisVersion cmisVersion) 128 { 129 assert cmisVersion != null; 130 131 RepositoryInfoImpl repositoryInfo = new RepositoryInfoImpl(); 132 133 String id = project.getId(); 134 ModifiableResourceCollection documentRoot = getRoot(project, factory); 135 136 String root = ""; 137 if (documentRoot != null) 138 { 139 root = documentRoot.getId(); 140 } 141 142 id = URIUtils.encodeParameter(URIUtils.encodeParameter(id)); 143 root = URIUtils.encodeParameter(URIUtils.encodeParameter(root)); 144 145 repositoryInfo.setId(id); 146 repositoryInfo.setName(project.getName()); 147 repositoryInfo.setDescription(project.getDescription()); 148 149 repositoryInfo.setCmisVersionSupported(cmisVersion.value()); 150 151 repositoryInfo.setProductName("Ametys CMIS Server"); 152 repositoryInfo.setProductVersion("1.0"); 153 repositoryInfo.setVendorName("Ametys"); 154 155 repositoryInfo.setRootFolder(root); 156 157 repositoryInfo.setThinClientUri(""); 158 repositoryInfo.setChangesIncomplete(false); 159 RepositoryCapabilitiesImpl capabilities = new RepositoryCapabilitiesImpl(); 160 capabilities.setCapabilityAcl(CapabilityAcl.NONE); 161 capabilities.setAllVersionsSearchable(false); 162 capabilities.setCapabilityJoin(CapabilityJoin.NONE); 163 capabilities.setSupportsMultifiling(false); 164 capabilities.setSupportsUnfiling(false); 165 capabilities.setSupportsVersionSpecificFiling(false); 166 capabilities.setIsPwcSearchable(false); 167 capabilities.setIsPwcUpdatable(false); 168 //capabilities.setCapabilityQuery(CapabilityQuery.METADATAONLY); 169 capabilities.setCapabilityChanges(CapabilityChanges.NONE); 170 capabilities.setCapabilityContentStreamUpdates(CapabilityContentStreamUpdates.ANYTIME); 171 capabilities.setSupportsGetDescendants(false); 172 capabilities.setSupportsGetFolderTree(false); 173 capabilities.setCapabilityRendition(CapabilityRenditions.NONE); 174 175 repositoryInfo.setCapabilities(capabilities); 176 177 return repositoryInfo; 178 } 179 180 /** 181 * getTypeDefinition 182 * @param context call context 183 * @param typeId type ID 184 * @param factory factory 185 * @return the type definition 186 */ 187 public TypeDefinition getTypeDefinition(CallContext context, String typeId, CmisServiceFactory factory) 188 { 189 //checkUser(context, false); 190 191 return factory.getTypeManager().getTypeDefinition(context, typeId); 192 } 193 194 /** 195 * getTypeChildren 196 * @param context context 197 * @param typeId typeId 198 * @param includePropertyDefinitions includePropertyDefinitions 199 * @param maxItems maxItems 200 * @param skipCount skipCount 201 * @param factory factory 202 * @return the type definition list 203 */ 204 public TypeDefinitionList getTypeChildren(CallContext context, String typeId, Boolean includePropertyDefinitions, 205 BigInteger maxItems, BigInteger skipCount, CmisServiceFactory factory) 206 { 207 //checkUser(context, false); 208 209 return factory.getTypeManager().getTypeChildren(context, typeId, includePropertyDefinitions, maxItems, skipCount); 210 } 211 212 /** 213 * getObject 214 * @param context context 215 * @param project Project 216 * @param objectId objectId 217 * @param versionServicesId versionServicesId 218 * @param filter filter 219 * @param includeAllowableActions includeAllowableActions 220 * @param includeAcl includeAcl 221 * @param objectInfos objectInfos 222 * @param factory factory 223 * @return ObjectData ObjectData 224 */ 225 public ObjectData getObject(CallContext context, Project project, String objectId, String versionServicesId, String filter, 226 Boolean includeAllowableActions, Boolean includeAcl, ObjectInfoHandler objectInfos, 227 CmisServiceFactory factory) 228 { 229 // check id 230 if (objectId == null && versionServicesId == null) 231 { 232 throw new CmisInvalidArgumentException("Object Id must be set."); 233 } 234 235 AmetysObject ametysObject = factory.getResolver().resolveById(objectId); 236 237 boolean userReadOnly = false; 238 239 // set defaults if values not set 240 boolean iaa = CmisUtils.getBooleanParameter(includeAllowableActions, false); 241 boolean iacl = false; //CmisUtils.getBooleanParameter(includeAcl, false); 242 243 // split filter 244 Set<String> filterCollection = CmisUtils.splitFilter(filter); 245 246 // gather properties 247 248 return compileObjectData(context, ametysObject, project, filterCollection, iaa, iacl, userReadOnly, objectInfos, factory); 249 } 250 251 252 private ObjectData compileObjectData(CallContext context, AmetysObject ametysObject, Project project, Set<String> filter, 253 boolean includeAllowableActions, boolean includeAcl, boolean userReadOnly, ObjectInfoHandler objectInfos, 254 CmisServiceFactory factory) 255 { 256 ObjectDataImpl result = new ObjectDataImpl(); 257 ObjectInfoImpl objectInfo = new ObjectInfoImpl(); 258 259 result.setProperties(compileProperties(context, ametysObject, project, filter, objectInfo, factory)); 260 261 if (includeAllowableActions) 262 { 263 result.setAllowableActions(compileAllowableActions(ametysObject, project, factory, userReadOnly)); 264 } 265 266 if (includeAcl) 267 { 268 result.setIsExactAcl(true); 269 } 270 result.setIsExactAcl(true); 271 272 if (context.isObjectInfoRequired()) 273 { 274 objectInfo.setObject(result); 275 objectInfos.addObjectInfo(objectInfo); 276 } 277 278 return result; 279 } 280 281 private Properties compileProperties(CallContext context, AmetysObject ametysObject, Project project, Set<String> orgfilter, 282 ObjectInfoImpl objectInfo, CmisServiceFactory factory) 283 { 284 // copy filter 285 Set<String> filter = orgfilter == null ? null : new HashSet<>(orgfilter); 286 287 // find base type 288 String typeId = null; 289 Boolean isFolder = true; 290 291 if (ametysObject != null && ametysObject instanceof ModifiableResource) 292 { 293 isFolder = false; 294 typeId = BaseTypeId.CMIS_DOCUMENT.value(); 295 objectInfo.setBaseType(BaseTypeId.CMIS_DOCUMENT); 296 objectInfo.setTypeId(typeId); 297 objectInfo.setHasAcl(false); 298 objectInfo.setHasContent(true); 299 objectInfo.setHasParent(true); 300 objectInfo.setVersionSeriesId(null); 301 objectInfo.setIsCurrentVersion(true); 302 objectInfo.setRelationshipSourceIds(null); 303 objectInfo.setRelationshipTargetIds(null); 304 objectInfo.setRenditionInfos(null); 305 objectInfo.setSupportsDescendants(false); 306 objectInfo.setSupportsFolderTree(false); 307 objectInfo.setSupportsPolicies(false); 308 objectInfo.setSupportsRelationships(false); 309 objectInfo.setWorkingCopyId(null); 310 objectInfo.setWorkingCopyOriginalId(null); 311 } 312 else if (ametysObject != null && ametysObject instanceof ModifiableResourceCollection) 313 { 314 isFolder = true; 315 typeId = BaseTypeId.CMIS_FOLDER.value(); 316 objectInfo.setBaseType(BaseTypeId.CMIS_FOLDER); 317 objectInfo.setTypeId(typeId); 318 objectInfo.setContentType(null); 319 objectInfo.setFileName(null); 320 objectInfo.setHasAcl(false); 321 objectInfo.setHasContent(false); 322 objectInfo.setVersionSeriesId(null); 323 objectInfo.setIsCurrentVersion(true); 324 objectInfo.setRelationshipSourceIds(null); 325 objectInfo.setRelationshipTargetIds(null); 326 objectInfo.setRenditionInfos(null); 327 objectInfo.setSupportsDescendants(true); 328 objectInfo.setSupportsFolderTree(true); 329 objectInfo.setSupportsPolicies(false); 330 objectInfo.setSupportsRelationships(false); 331 objectInfo.setWorkingCopyId(null); 332 objectInfo.setWorkingCopyOriginalId(null); 333 } 334 else 335 { 336 throw new IllegalArgumentException("Resource not found"); 337 } 338 339 try 340 { 341 PropertiesImpl result = new PropertiesImpl(); 342 343 addPropertyId(result, typeId, filter, PropertyIds.OBJECT_ID, ametysObject.getId(), factory); 344 objectInfo.setId(ametysObject.getId()); 345 346 // name 347 String name = ametysObject.getName(); 348 addPropertyString(result, typeId, filter, PropertyIds.NAME, name, factory); 349 objectInfo.setName(name); 350 351 if (isFolder) 352 { 353 ModifiableResourceCollection folder = (ModifiableResourceCollection) ametysObject; 354 addPropertyString(result, typeId, filter, PropertyIds.CREATED_BY, USER_UNKNOWN, factory); 355 addPropertyString(result, typeId, filter, PropertyIds.LAST_MODIFIED_BY, USER_UNKNOWN, factory); 356 objectInfo.setCreatedBy(USER_UNKNOWN); 357 addPropertyString(result, typeId, filter, PropertyIds.DESCRIPTION, folder.getDescription(), factory); 358 359 // base type and type name 360 addPropertyId(result, typeId, filter, PropertyIds.BASE_TYPE_ID, BaseTypeId.CMIS_FOLDER.value(), factory); 361 addPropertyId(result, typeId, filter, PropertyIds.OBJECT_TYPE_ID, BaseTypeId.CMIS_FOLDER.value(), factory); 362 363 String path = ((ModifiableResourceCollection) ametysObject).getExplorerPath(); 364 ModifiableResourceCollection root = getRoot(project, factory); 365 path = path.substring(root.getExplorerPath().length()); 366 if (path.length() == 0) 367 { 368 path = "/"; 369 } 370 addPropertyString(result, typeId, filter, PropertyIds.PATH, path, factory); 371 372 // folder properties 373 374 //On évite d'appeler isRoot qui ferait un appel JCR de plus 375 if (ametysObject.equals(root)) 376 { 377 addPropertyId(result, typeId, filter, PropertyIds.PARENT_ID, null, factory); 378 objectInfo.setHasParent(false); 379 } 380 else 381 { 382 String parentId = ametysObject.getParent().getId(); 383 addPropertyId(result, typeId, filter, PropertyIds.PARENT_ID, parentId, factory); 384 objectInfo.setHasParent(true); 385 } 386 387 addPropertyIdList(result, typeId, filter, PropertyIds.ALLOWED_CHILD_OBJECT_TYPE_IDS, null, factory); 388 } 389 else 390 { 391 ModifiableResource modifiableResource = (ModifiableResource) ametysObject; 392 String author = modifiableResource.getCreator().getLogin(); 393 String contributor = modifiableResource.getLastContributor().getLogin(); 394 addPropertyString(result, typeId, filter, PropertyIds.CREATED_BY, author, factory); 395 addPropertyString(result, typeId, filter, PropertyIds.LAST_MODIFIED_BY, contributor, factory); 396 addPropertyString(result, typeId, filter, PropertyIds.DESCRIPTION, modifiableResource.getDCDescription(), factory); 397 objectInfo.setCreatedBy(author); 398 399 Date lastModifiedDate = modifiableResource.getLastModified(); 400 GregorianCalendar lastModified = new GregorianCalendar(); 401 lastModified.setTime(lastModifiedDate); 402 Date creationDate = modifiableResource.getCreationDate(); 403 GregorianCalendar creation = new GregorianCalendar(); 404 creation.setTime(creationDate); 405 addPropertyDateTime(result, typeId, filter, PropertyIds.CREATION_DATE, creation, factory); 406 addPropertyDateTime(result, typeId, filter, PropertyIds.LAST_MODIFICATION_DATE, lastModified, factory); 407 objectInfo.setCreationDate(creation); 408 objectInfo.setLastModificationDate(lastModified); 409 410 // base type and type name 411 addPropertyId(result, typeId, filter, PropertyIds.BASE_TYPE_ID, BaseTypeId.CMIS_DOCUMENT.value(), factory); 412 addPropertyId(result, typeId, filter, PropertyIds.OBJECT_TYPE_ID, BaseTypeId.CMIS_DOCUMENT.value(), factory); 413 414 // file properties 415 addPropertyBoolean(result, typeId, filter, PropertyIds.IS_IMMUTABLE, false, factory); 416 addPropertyBoolean(result, typeId, filter, PropertyIds.IS_LATEST_VERSION, true, factory); 417 addPropertyBoolean(result, typeId, filter, PropertyIds.IS_MAJOR_VERSION, true, factory); 418 addPropertyBoolean(result, typeId, filter, PropertyIds.IS_LATEST_MAJOR_VERSION, true, factory); 419 addPropertyString(result, typeId, filter, PropertyIds.VERSION_LABEL, modifiableResource.getName(), factory); 420 //addPropertyId(result, typeId, filter, PropertyIds.VERSION_SERIES_ID, fileToId(file), factory); 421 addPropertyBoolean(result, typeId, filter, PropertyIds.IS_VERSION_SERIES_CHECKED_OUT, false, factory); 422 addPropertyString(result, typeId, filter, PropertyIds.VERSION_SERIES_CHECKED_OUT_BY, null, factory); 423 addPropertyString(result, typeId, filter, PropertyIds.VERSION_SERIES_CHECKED_OUT_ID, null, factory); 424 addPropertyString(result, typeId, filter, PropertyIds.CHECKIN_COMMENT, "", factory); 425 if (context.getCmisVersion() != CmisVersion.CMIS_1_0) 426 { 427 addPropertyBoolean(result, typeId, filter, PropertyIds.IS_PRIVATE_WORKING_COPY, false, factory); 428 } 429 430 431 if (modifiableResource.getLength() == 0) 432 { 433 addPropertyBigInteger(result, typeId, filter, PropertyIds.CONTENT_STREAM_LENGTH, null, factory); 434 addPropertyString(result, typeId, filter, PropertyIds.CONTENT_STREAM_MIME_TYPE, null, factory); 435 addPropertyString(result, typeId, filter, PropertyIds.CONTENT_STREAM_FILE_NAME, null, factory); 436 437 objectInfo.setHasContent(false); 438 objectInfo.setContentType(null); 439 objectInfo.setFileName(null); 440 } 441 else 442 { 443 444 addPropertyInteger(result, typeId, filter, PropertyIds.CONTENT_STREAM_LENGTH, modifiableResource.getLength(), factory); 445 addPropertyString(result, typeId, filter, PropertyIds.CONTENT_STREAM_MIME_TYPE, 446 modifiableResource.getMimeType(), factory); 447 addPropertyString(result, typeId, filter, PropertyIds.CONTENT_STREAM_FILE_NAME, modifiableResource.getName(), factory); 448 449 objectInfo.setHasContent(true); 450 objectInfo.setContentType(modifiableResource.getMimeType()); 451 objectInfo.setFileName(modifiableResource.getName()); 452 } 453 454 addPropertyId(result, typeId, filter, PropertyIds.CONTENT_STREAM_ID, null, factory); 455 } 456 457 458 459 // change token - always null 460 addPropertyString(result, typeId, filter, PropertyIds.CHANGE_TOKEN, null, factory); 461 462 // CMIS 1.1 properties 463 if (context.getCmisVersion() != CmisVersion.CMIS_1_0) 464 { 465 addPropertyString(result, typeId, filter, PropertyIds.DESCRIPTION, null, factory); 466 addPropertyIdList(result, typeId, filter, PropertyIds.SECONDARY_OBJECT_TYPE_IDS, null, factory); 467 } 468 469 return result; 470 } 471 catch (CmisBaseException cbe) 472 { 473 throw cbe; 474 } 475 catch (Exception e) 476 { 477 throw new CmisRuntimeException(e.getMessage(), e); 478 } 479 } 480 481 /** 482 * get children of a folder 483 * @param context call context 484 * @param folderId folder Id 485 * @param project Project 486 * @param filter filters 487 * @param includeAllowableActions allowable actions 488 * @param includePathSegment include path segment 489 * @param maxItems max items 490 * @param skipCount skip count 491 * @param objectInfos object infos 492 * @param factory factory 493 * @return ObjectInFolderList 494 */ 495 public ObjectInFolderList getChildren(CallContext context, String folderId, Project project, String filter, 496 Boolean includeAllowableActions, Boolean includePathSegment, BigInteger maxItems, BigInteger skipCount, 497 ObjectInfoHandler objectInfos, CmisServiceFactory factory) 498 { 499 boolean userReadOnly = false; 500 501 // split filter 502 Set<String> filterCollection = CmisUtils.splitFilter(filter); 503 504 // set defaults if values not set 505 boolean iaa = CmisUtils.getBooleanParameter(includeAllowableActions, false); 506 boolean ips = CmisUtils.getBooleanParameter(includePathSegment, false); 507 508 // skip and max 509 int skip = skipCount == null ? 0 : skipCount.intValue(); 510 if (skip < 0) 511 { 512 skip = 0; 513 } 514 515 int max = maxItems == null ? Integer.MAX_VALUE : maxItems.intValue(); 516 if (max < 0) 517 { 518 max = Integer.MAX_VALUE; 519 } 520 521 // get the folder 522 AmetysObject ametysObject = factory.getResolver().resolveById(folderId); 523 if (!(ametysObject instanceof ModifiableResourceCollection)) 524 { 525 throw new CmisObjectNotFoundException("Not a folder!"); 526 } 527 ModifiableResourceCollection folder = (ModifiableResourceCollection) ametysObject; 528 529 // set object info of the the folder 530 if (context.isObjectInfoRequired()) 531 { 532 compileObjectData(context, ametysObject, project, null, false, false, userReadOnly, objectInfos, factory); 533 } 534 535 // prepare result 536 ObjectInFolderListImpl result = new ObjectInFolderListImpl(); 537 result.setObjects(new ArrayList<ObjectInFolderData>()); 538 result.setHasMoreItems(false); 539 int count = 0; 540 541 // iterate through children 542 AmetysObjectIterable<AmetysObject> children = folder.getChildren(); 543 for (AmetysObject child : children) 544 //for (File child : folder.listFiles()) 545 { 546 // skip nodes other than ModifiableResource or ModifiableResourceCollection 547 if (!(child instanceof ModifiableResource || child instanceof ModifiableResourceCollection)) 548 { 549 continue; 550 } 551 552 count++; 553 554 if (skip > 0) 555 { 556 skip--; 557 continue; 558 } 559 560 if (result.getObjects().size() >= max) 561 { 562 result.setHasMoreItems(true); 563 continue; 564 } 565 566 // build and add child object 567 ObjectInFolderDataImpl objectInFolder = new ObjectInFolderDataImpl(); 568 objectInFolder.setObject(compileObjectData(context, child, project, filterCollection, iaa, false, userReadOnly, 569 objectInfos, factory)); 570 if (ips) 571 { 572 objectInFolder.setPathSegment(child.getName()); 573 } 574 575 result.getObjects().add(objectInFolder); 576 } 577 578 result.setNumItems(BigInteger.valueOf(count)); 579 580 return result; 581 } 582 583 /** 584 * get the parents of an object 585 * @param context call context 586 * @param objectId Object Id 587 * @param project Project 588 * @param filter filters 589 * @param includeAllowableActions allowable actions 590 * @param includeRelativePathSegment relative path segment 591 * @param objectInfos object infos 592 * @param factory factory 593 * @return List of ObjectParentData 594 */ 595 public List<ObjectParentData> getObjectParents(CallContext context, String objectId, Project project, String filter, 596 Boolean includeAllowableActions, Boolean includeRelativePathSegment, ObjectInfoHandler objectInfos, CmisServiceFactory factory) 597 { 598 boolean userReadOnly = false; 599 600 // split filter 601 Set<String> filterCollection = CmisUtils.splitFilter(filter); 602 603 // set defaults if values not set 604 boolean iaa = CmisUtils.getBooleanParameter(includeAllowableActions, false); 605 boolean irps = CmisUtils.getBooleanParameter(includeRelativePathSegment, false); 606 607 // get the file or folder 608 //File file = getFile(objectId); 609 610 // don't climb above the root folder 611 AmetysObject ametysObject = factory.getResolver().resolveById(objectId); 612 if (isRoot(ametysObject, project, factory)) 613 { 614 return Collections.emptyList(); 615 } 616 617 // set object info of the the object 618 if (context.isObjectInfoRequired()) 619 { 620 compileObjectData(context, ametysObject, project, null, false, false, userReadOnly, objectInfos, factory); 621 } 622 623 // get parent folder 624 AmetysObject parent = ametysObject.getParent(); 625 //File parent = file.getParentFile(); 626 ObjectData object = compileObjectData(context, parent, project, filterCollection, iaa, false, userReadOnly, objectInfos, factory); 627 628 ObjectParentDataImpl result = new ObjectParentDataImpl(); 629 result.setObject(object); 630 if (irps) 631 { 632 result.setRelativePathSegment(ametysObject.getName()); 633 } 634 635 return Collections.<ObjectParentData> singletonList(result); 636 } 637 /** 638 * get the inputstream to read a file 639 * @param context call context 640 * @param objectId object Id 641 * @param offset offset 642 * @param length lenght 643 * @param factory factory 644 * @return ContentStream 645 */ 646 public ContentStream getContentStream(CallContext context, String objectId, BigInteger offset, BigInteger length, CmisServiceFactory factory) 647 { 648 // get the file 649 AmetysObject ametysObject = factory.getResolver().resolveById(objectId); 650 if (!(ametysObject instanceof ModifiableResource)) 651 { 652 throw new CmisStreamNotSupportedException("Not a file!"); 653 } 654 ModifiableResource res = (ModifiableResource) ametysObject; 655 656 if (res.getLength() == 0) 657 { 658 throw new CmisConstraintException("Document has no content!"); 659 } 660 661 InputStream stream = null; 662 stream = res.getInputStream(); 663 if (offset != null || length != null) 664 { 665 stream = new CmisContentRangeInputStream(stream, offset, length); 666 } 667 668 // compile data 669 ContentStreamImpl result; 670 if (offset != null && offset.longValue() > 0 671 || length != null) 672 { 673 result = new PartialContentStreamImpl(); 674 } 675 else 676 { 677 result = new ContentStreamImpl(); 678 } 679 680 result.setFileName(res.getName()); 681 result.setLength(BigInteger.valueOf(res.getLength())); 682 result.setMimeType(res.getMimeType()); 683 result.setStream(stream); 684 685 return result; 686 } 687 688 /** 689 * get an object by it's path 690 * @param context call context 691 * @param project Project 692 * @param folderPath path of the object/folder 693 * @param filter filters for metadata 694 * @param includeAllowableActions allowable actions 695 * @param includeACL ACL 696 * @param objectInfos infos 697 * @param factory factory 698 * @return datas of the object 699 */ 700 public ObjectData getObjectByPath(CallContext context, Project project, String folderPath, String filter, 701 boolean includeAllowableActions, boolean includeACL, ObjectInfoHandler objectInfos, CmisServiceFactory factory) 702 { 703 boolean userReadOnly = false; 704 705 // split filter 706 Set<String> filterCollection = CmisUtils.splitFilter(filter); 707 708 // check path 709 if (folderPath == null || folderPath.length() == 0 || folderPath.charAt(0) != '/') 710 { 711 throw new CmisInvalidArgumentException("Invalid folder path!"); 712 } 713 714 // get the file or folder 715 AmetysObject root = getRoot(project, factory); 716 AmetysObject file = null; 717 if (folderPath.length() == 1) 718 { 719 file = root; 720 } 721 else 722 { 723 file = factory.getResolver().resolveByPath(root.getPath() + folderPath); 724 //String path = folderPath.replace('/', File.separatorChar).substring(1); 725 //file = new File(root, path); 726 } 727 728 if (file == null) 729 { 730 throw new CmisObjectNotFoundException("Path doesn't exist."); 731 } 732 return compileObjectData(context, file, project, filterCollection, includeAllowableActions, includeACL, userReadOnly, 733 objectInfos, factory); 734 } 735 736 /** 737 * Create a new folder in another one 738 * @param context call context 739 * @param properties properties 740 * @param project Project 741 * @param folderId folder Id 742 * @param factory factory 743 * @return id of the created folder 744 */ 745 public String createFolder(CallContext context, Properties properties, Project project, String folderId, CmisServiceFactory factory) 746 { 747 // check properties 748 checkNewProperties(properties, BaseTypeId.CMIS_FOLDER, factory); 749 750 // get parent File 751 AmetysObject ametysObject = factory.getResolver().resolveById(folderId); 752 if (!(ametysObject instanceof ModifiableResourceCollection)) 753 { 754 throw new CmisObjectNotFoundException("Parent is not a folder!"); 755 } 756 757 // create the folder 758 String name = CmisUtils.getStringProperty(properties, PropertyIds.NAME); 759 String description = CmisUtils.getStringProperty(properties, PropertyIds.DESCRIPTION, ""); 760 761 Map<String, Object> addFolder; 762 addFolder = factory.getWorkspaceExplorerResourceDAO().addFolder(folderId, name, description, true); 763 return (String) addFolder.get("id"); 764 } 765 766 /** 767 * Create a new document in a folder 768 * @param context call context 769 * @param properties properties 770 * @param project Project 771 * @param folderId folder Id 772 * @param contentStream content Stream 773 * @param versioningState versionning State 774 * @param factory factory 775 * @return id of the created document 776 */ 777 public String createDocument(CallContext context, Properties properties, Project project, String folderId, 778 ContentStream contentStream, VersioningState versioningState, CmisServiceFactory factory) 779 { 780 // check versioning state 781 if (VersioningState.NONE != versioningState) 782 { 783 throw new CmisConstraintException("Versioning not supported!"); 784 } 785 786 // check properties 787 checkNewProperties(properties, BaseTypeId.CMIS_DOCUMENT, factory); 788 789 String name = CmisUtils.getStringProperty(properties, PropertyIds.NAME); 790 AmetysObject ametysObject = factory.getResolver().resolveById(folderId); 791 if (!(ametysObject instanceof ModifiableResourceCollection)) 792 { 793 throw new IllegalClassException(ModifiableResourceCollection.class, ametysObject.getClass()); 794 } 795 796 factory.getAddOrUpdateResourceHelper().checkAddResourceRight((ModifiableResourceCollection) ametysObject); 797 ResourceOperationResult resourceOperation = factory.getAddOrUpdateResourceHelper().performResourceOperation(contentStream.getStream(), name, (ModifiableResourceCollection) ametysObject, 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<String>()); 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}