001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (C) Alkacon Software (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.cmis; 029 030import static org.opencms.cmis.CmsCmisUtil.checkResourceName; 031import static org.opencms.cmis.CmsCmisUtil.ensureLock; 032import static org.opencms.cmis.CmsCmisUtil.handleCmsException; 033import static org.opencms.cmis.CmsCmisUtil.splitFilter; 034 035import org.opencms.configuration.CmsConfigurationException; 036import org.opencms.configuration.CmsParameterConfiguration; 037import org.opencms.file.CmsFile; 038import org.opencms.file.CmsObject; 039import org.opencms.file.CmsProject; 040import org.opencms.file.CmsProperty; 041import org.opencms.file.CmsResource; 042import org.opencms.file.CmsResourceFilter; 043import org.opencms.file.CmsVfsResourceAlreadyExistsException; 044import org.opencms.file.types.CmsResourceTypeFolder; 045import org.opencms.file.types.I_CmsResourceType; 046import org.opencms.main.CmsException; 047import org.opencms.main.CmsLog; 048import org.opencms.main.OpenCms; 049import org.opencms.relations.CmsRelation; 050import org.opencms.relations.CmsRelationFilter; 051import org.opencms.repository.CmsRepositoryFilter; 052import org.opencms.search.CmsSearchException; 053import org.opencms.search.solr.CmsSolrIndex; 054import org.opencms.search.solr.CmsSolrQuery; 055import org.opencms.search.solr.CmsSolrResultList; 056import org.opencms.util.CmsFileUtil; 057import org.opencms.util.CmsRequestUtil; 058import org.opencms.util.CmsStringUtil; 059import org.opencms.util.CmsUUID; 060 061import java.io.ByteArrayInputStream; 062import java.io.IOException; 063import java.io.InputStream; 064import java.math.BigInteger; 065import java.util.ArrayList; 066import java.util.Collections; 067import java.util.Comparator; 068import java.util.HashMap; 069import java.util.List; 070import java.util.Map; 071import java.util.Set; 072 073import org.apache.chemistry.opencmis.commons.PropertyIds; 074import org.apache.chemistry.opencmis.commons.data.Acl; 075import org.apache.chemistry.opencmis.commons.data.AllowableActions; 076import org.apache.chemistry.opencmis.commons.data.ContentStream; 077import org.apache.chemistry.opencmis.commons.data.FailedToDeleteData; 078import org.apache.chemistry.opencmis.commons.data.ObjectData; 079import org.apache.chemistry.opencmis.commons.data.ObjectInFolderContainer; 080import org.apache.chemistry.opencmis.commons.data.ObjectInFolderData; 081import org.apache.chemistry.opencmis.commons.data.ObjectInFolderList; 082import org.apache.chemistry.opencmis.commons.data.ObjectList; 083import org.apache.chemistry.opencmis.commons.data.ObjectParentData; 084import org.apache.chemistry.opencmis.commons.data.PermissionMapping; 085import org.apache.chemistry.opencmis.commons.data.Properties; 086import org.apache.chemistry.opencmis.commons.data.PropertyData; 087import org.apache.chemistry.opencmis.commons.data.RenditionData; 088import org.apache.chemistry.opencmis.commons.data.RepositoryInfo; 089import org.apache.chemistry.opencmis.commons.definitions.PermissionDefinition; 090import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition; 091import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionContainer; 092import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionList; 093import org.apache.chemistry.opencmis.commons.enums.AclPropagation; 094import org.apache.chemistry.opencmis.commons.enums.CapabilityAcl; 095import org.apache.chemistry.opencmis.commons.enums.CapabilityChanges; 096import org.apache.chemistry.opencmis.commons.enums.CapabilityContentStreamUpdates; 097import org.apache.chemistry.opencmis.commons.enums.CapabilityJoin; 098import org.apache.chemistry.opencmis.commons.enums.CapabilityQuery; 099import org.apache.chemistry.opencmis.commons.enums.CapabilityRenditions; 100import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships; 101import org.apache.chemistry.opencmis.commons.enums.RelationshipDirection; 102import org.apache.chemistry.opencmis.commons.enums.SupportedPermissions; 103import org.apache.chemistry.opencmis.commons.enums.UnfileObject; 104import org.apache.chemistry.opencmis.commons.enums.VersioningState; 105import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException; 106import org.apache.chemistry.opencmis.commons.exceptions.CmisContentAlreadyExistsException; 107import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException; 108import org.apache.chemistry.opencmis.commons.exceptions.CmisNameConstraintViolationException; 109import org.apache.chemistry.opencmis.commons.exceptions.CmisNotSupportedException; 110import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException; 111import org.apache.chemistry.opencmis.commons.exceptions.CmisPermissionDeniedException; 112import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException; 113import org.apache.chemistry.opencmis.commons.exceptions.CmisStreamNotSupportedException; 114import org.apache.chemistry.opencmis.commons.impl.dataobjects.AclCapabilitiesDataImpl; 115import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl; 116import org.apache.chemistry.opencmis.commons.impl.dataobjects.FailedToDeleteDataImpl; 117import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectInFolderContainerImpl; 118import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectInFolderDataImpl; 119import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectInFolderListImpl; 120import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectListImpl; 121import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectParentDataImpl; 122import org.apache.chemistry.opencmis.commons.impl.dataobjects.PermissionDefinitionDataImpl; 123import org.apache.chemistry.opencmis.commons.impl.dataobjects.PermissionMappingDataImpl; 124import org.apache.chemistry.opencmis.commons.impl.dataobjects.RepositoryCapabilitiesImpl; 125import org.apache.chemistry.opencmis.commons.impl.dataobjects.RepositoryInfoImpl; 126import org.apache.chemistry.opencmis.commons.spi.Holder; 127import org.apache.commons.logging.Log; 128 129/** 130 * Repository instance for CMIS repositories.<p> 131 */ 132public class CmsCmisRepository extends A_CmsCmisRepository { 133 134 /** 135 * Simple helper class to simplify creating a permission mapping.<p> 136 */ 137 @SuppressWarnings("serial") 138 private static class PermissionMappings extends HashMap<String, PermissionMapping> { 139 140 /** Default constructor.<p> */ 141 public PermissionMappings() { 142 143 } 144 145 /** 146 * Creates a single mapping entry.<p> 147 * 148 * @param key the mapping key 149 * @param permission the permission 150 * 151 * @return the mapping entry 152 */ 153 private static PermissionMapping createMapping(String key, String permission) { 154 155 PermissionMappingDataImpl pm = new PermissionMappingDataImpl(); 156 pm.setKey(key); 157 pm.setPermissions(Collections.singletonList(permission)); 158 159 return pm; 160 } 161 162 /** 163 * Adds a permission mapping.<p> 164 * 165 * @param key the key 166 * @param permission the permissions 167 * 168 * @return the instance itself 169 */ 170 public PermissionMappings add(String key, String permission) { 171 172 put(key, createMapping(key, permission)); 173 return this; 174 } 175 176 } 177 178 /** The description parameter name. */ 179 public static final String PARAM_DESCRIPTION = "description"; 180 181 /** The project parameter name. */ 182 public static final String PARAM_PROJECT = "project"; 183 184 /** The property parameter name. */ 185 public static final String PARAM_PROPERTY = "property"; 186 187 /** The rendition parameter name. */ 188 public static final String PARAM_RENDITION = "rendition"; 189 190 /** The logger instance for this class. */ 191 protected static final Log LOG = CmsLog.getLog(CmsCmisRepository.class); 192 193 /** The index parameter name. */ 194 private static final String PARAM_INDEX = "index"; 195 196 /** The internal admin CMS context. */ 197 private CmsObject m_adminCms; 198 199 /** The repository description. */ 200 private String m_description; 201 202 /** The repository filter. */ 203 private CmsRepositoryFilter m_filter; 204 205 /** The repository id. */ 206 private String m_id; 207 208 /** The name of the SOLR index to use for querying. */ 209 private String m_indexName; 210 211 /** 212 * Readonly flag to prevent write operations on the repository.<p> 213 */ 214 private boolean m_isReadOnly; 215 216 /** The parameter configuration map. */ 217 private CmsParameterConfiguration m_parameterConfiguration = new CmsParameterConfiguration(); 218 219 /** The project of the repository. */ 220 private CmsProject m_project; 221 222 /** List of dynamic property providers. */ 223 private List<I_CmsPropertyProvider> m_propertyProviders = new ArrayList<I_CmsPropertyProvider>(); 224 225 /** The relation object helper. */ 226 private CmsCmisRelationHelper m_relationHelper = new CmsCmisRelationHelper(this); 227 228 /** The map of rendition providers by stream ids. */ 229 private Map<String, I_CmsCmisRenditionProvider> m_renditionProviders = new HashMap<String, I_CmsCmisRenditionProvider>(); 230 231 /** The resource object helper. */ 232 private CmsCmisResourceHelper m_resourceHelper = new CmsCmisResourceHelper(this); 233 234 /** The root folder. */ 235 private CmsResource m_root; 236 237 /** 238 * Creates a permission definition.<p> 239 * 240 * @param permission the permission name 241 * @param description the permission description 242 * 243 * @return the new permission definition 244 */ 245 private static PermissionDefinition createPermission(String permission, String description) { 246 247 PermissionDefinitionDataImpl pd = new PermissionDefinitionDataImpl(); 248 pd.setId(permission); 249 pd.setDescription(description); 250 251 return pd; 252 } 253 254 /** 255 * @see org.opencms.cmis.I_CmsCmisRepository#addConfigurationParameter(java.lang.String, java.lang.String) 256 */ 257 public void addConfigurationParameter(String paramName, String paramValue) { 258 259 m_parameterConfiguration.add(paramName, paramValue); 260 261 } 262 263 /** 264 * @see org.opencms.cmis.I_CmsCmisRepository#createDocument(org.opencms.cmis.CmsCmisCallContext, org.apache.chemistry.opencmis.commons.data.Properties, java.lang.String, org.apache.chemistry.opencmis.commons.data.ContentStream, org.apache.chemistry.opencmis.commons.enums.VersioningState, java.util.List, org.apache.chemistry.opencmis.commons.data.Acl, org.apache.chemistry.opencmis.commons.data.Acl) 265 */ 266 public synchronized String createDocument( 267 CmsCmisCallContext context, 268 Properties propertiesObj, 269 String folderId, 270 ContentStream contentStream, 271 VersioningState versioningState, 272 List<String> policies, 273 Acl addAces, 274 Acl removeAces) { 275 276 checkWriteAccess(); 277 278 if ((addAces != null) || (removeAces != null)) { 279 throw new CmisConstraintException("createDocument: ACEs not allowed"); 280 } 281 282 if (contentStream == null) { 283 throw new CmisConstraintException("createDocument: no content stream given"); 284 } 285 286 try { 287 CmsObject cms = getCmsObject(context); 288 Map<String, PropertyData<?>> properties = propertiesObj.getProperties(); 289 String newDocName = (String)properties.get(PropertyIds.NAME).getFirstValue(); 290 String defaultType = OpenCms.getResourceManager().getDefaultTypeForName(newDocName).getTypeName(); 291 String resTypeName = getResourceTypeFromProperties(properties, defaultType); 292 I_CmsResourceType cmsResourceType = OpenCms.getResourceManager().getResourceType(resTypeName); 293 if (cmsResourceType.isFolder()) { 294 throw new CmisConstraintException("Not a document type: " + resTypeName); 295 } 296 List<CmsProperty> cmsProperties = getOpenCmsProperties(properties); 297 checkResourceName(newDocName); 298 InputStream stream = contentStream.getStream(); 299 byte[] content = CmsFileUtil.readFully(stream); 300 CmsUUID parentFolderId = new CmsUUID(folderId); 301 CmsResource parentFolder = cms.readResource(parentFolderId); 302 String newFolderPath = CmsStringUtil.joinPaths(parentFolder.getRootPath(), newDocName); 303 try { 304 CmsResource newDocument = cms.createResource( 305 newFolderPath, 306 cmsResourceType.getTypeId(), 307 content, 308 cmsProperties); 309 cms.unlockResource(newDocument.getRootPath()); 310 return newDocument.getStructureId().toString(); 311 } catch (CmsVfsResourceAlreadyExistsException e) { 312 throw new CmisNameConstraintViolationException(e.getLocalizedMessage(), e); 313 } 314 } catch (CmsException e) { 315 handleCmsException(e); 316 return null; 317 } catch (IOException e) { 318 throw new CmisRuntimeException(e.getLocalizedMessage(), e); 319 } 320 } 321 322 /** 323 * @see org.opencms.cmis.I_CmsCmisRepository#createDocumentFromSource(org.opencms.cmis.CmsCmisCallContext, java.lang.String, org.apache.chemistry.opencmis.commons.data.Properties, java.lang.String, org.apache.chemistry.opencmis.commons.enums.VersioningState, java.util.List, org.apache.chemistry.opencmis.commons.data.Acl, org.apache.chemistry.opencmis.commons.data.Acl) 324 */ 325 public synchronized String createDocumentFromSource( 326 CmsCmisCallContext context, 327 String sourceId, 328 Properties propertiesObj, 329 String folderId, 330 VersioningState versioningState, 331 List<String> policies, 332 Acl addAces, 333 Acl removeAces) { 334 335 checkWriteAccess(); 336 337 if ((addAces != null) || (removeAces != null)) { 338 throw new CmisConstraintException("createDocument: ACEs not allowed"); 339 } 340 341 try { 342 CmsObject cms = getCmsObject(context); 343 Map<String, PropertyData<?>> properties = new HashMap<String, PropertyData<?>>(); 344 if (propertiesObj != null) { 345 properties = propertiesObj.getProperties(); 346 } 347 List<CmsProperty> cmsProperties = getOpenCmsProperties(properties); 348 CmsUUID parentFolderId = new CmsUUID(folderId); 349 CmsResource parentFolder = cms.readResource(parentFolderId); 350 CmsUUID sourceUuid = new CmsUUID(sourceId); 351 CmsResource source = cms.readResource(sourceUuid); 352 String sourcePath = source.getRootPath(); 353 354 PropertyData<?> nameProp = properties.get(PropertyIds.NAME); 355 String newDocName; 356 if (nameProp != null) { 357 newDocName = (String)nameProp.getFirstValue(); 358 checkResourceName(newDocName); 359 } else { 360 newDocName = CmsResource.getName(source.getRootPath()); 361 } 362 String targetPath = CmsStringUtil.joinPaths(parentFolder.getRootPath(), newDocName); 363 364 try { 365 cms.copyResource(sourcePath, targetPath); 366 } catch (CmsVfsResourceAlreadyExistsException e) { 367 throw new CmisNameConstraintViolationException(e.getLocalizedMessage(), e); 368 } 369 370 CmsResource targetResource = cms.readResource(targetPath); 371 cms.setDateLastModified(targetResource.getRootPath(), targetResource.getDateCreated(), false); 372 cms.unlockResource(targetResource); 373 boolean wasLocked = ensureLock(cms, targetResource); 374 cms.writePropertyObjects(targetResource, cmsProperties); 375 for (String key : properties.keySet()) { 376 if (key.startsWith(CmsCmisTypeManager.PROPERTY_PREFIX_DYNAMIC)) { 377 I_CmsPropertyProvider provider = getTypeManager().getPropertyProvider(key); 378 try { 379 String value = (String)(properties.get(key).getFirstValue()); 380 provider.setPropertyValue(cms, targetResource, value); 381 } catch (CmsException e) { 382 LOG.error(e.getLocalizedMessage(), e); 383 } 384 } 385 } 386 387 if (wasLocked) { 388 cms.unlockResource(targetResource); 389 } 390 return targetResource.getStructureId().toString(); 391 } catch (CmsException e) { 392 handleCmsException(e); 393 return null; 394 } 395 } 396 397 /** 398 * @see org.opencms.cmis.I_CmsCmisRepository#createFolder(org.opencms.cmis.CmsCmisCallContext, org.apache.chemistry.opencmis.commons.data.Properties, java.lang.String, java.util.List, org.apache.chemistry.opencmis.commons.data.Acl, org.apache.chemistry.opencmis.commons.data.Acl) 399 */ 400 public synchronized String createFolder( 401 CmsCmisCallContext context, 402 Properties propertiesObj, 403 String folderId, 404 List<String> policies, 405 Acl addAces, 406 Acl removeAces) { 407 408 checkWriteAccess(); 409 410 if ((addAces != null) || (removeAces != null)) { 411 throw new CmisConstraintException("createFolder: ACEs not allowed"); 412 } 413 414 try { 415 CmsObject cms = getCmsObject(context); 416 Map<String, PropertyData<?>> properties = propertiesObj.getProperties(); 417 String resTypeName = getResourceTypeFromProperties(properties, CmsResourceTypeFolder.getStaticTypeName()); 418 I_CmsResourceType cmsResourceType = OpenCms.getResourceManager().getResourceType(resTypeName); 419 if (!cmsResourceType.isFolder()) { 420 throw new CmisConstraintException("Invalid folder type: " + resTypeName); 421 } 422 List<CmsProperty> cmsProperties = getOpenCmsProperties(properties); 423 String newFolderName = (String)properties.get(PropertyIds.NAME).getFirstValue(); 424 checkResourceName(newFolderName); 425 CmsUUID parentFolderId = new CmsUUID(folderId); 426 CmsResource parentFolder = cms.readResource(parentFolderId); 427 String newFolderPath = CmsStringUtil.joinPaths(parentFolder.getRootPath(), newFolderName); 428 try { 429 CmsResource newFolder = cms.createResource( 430 newFolderPath, 431 cmsResourceType.getTypeId(), 432 null, 433 cmsProperties); 434 cms.unlockResource(newFolder); 435 return newFolder.getStructureId().toString(); 436 } catch (CmsVfsResourceAlreadyExistsException e) { 437 throw new CmisNameConstraintViolationException(e.getLocalizedMessage(), e); 438 } 439 } catch (CmsException e) { 440 handleCmsException(e); 441 return null; 442 } 443 } 444 445 /** 446 * @see org.opencms.cmis.I_CmsCmisRepository#createRelationship(org.opencms.cmis.CmsCmisCallContext, org.apache.chemistry.opencmis.commons.data.Properties, java.util.List, org.apache.chemistry.opencmis.commons.data.Acl, org.apache.chemistry.opencmis.commons.data.Acl) 447 */ 448 public synchronized String createRelationship( 449 CmsCmisCallContext context, 450 Properties properties, 451 List<String> policies, 452 Acl addAces, 453 Acl removeAces) { 454 455 try { 456 CmsObject cms = getCmsObject(context); 457 Map<String, PropertyData<?>> propertyMap = properties.getProperties(); 458 String sourceProp = (String)(propertyMap.get(PropertyIds.SOURCE_ID).getFirstValue()); 459 String targetProp = (String)(propertyMap.get(PropertyIds.TARGET_ID).getFirstValue()); 460 String typeId = (String)(propertyMap.get(PropertyIds.OBJECT_TYPE_ID).getFirstValue()); 461 if (!typeId.startsWith("opencms:")) { 462 throw new CmisConstraintException("Can't create this relationship type."); 463 } 464 String cmsTypeName = typeId.substring("opencms:".length()); 465 CmsUUID sourceId = new CmsUUID(sourceProp); 466 CmsUUID targetId = new CmsUUID(targetProp); 467 CmsResource sourceRes = cms.readResource(sourceId); 468 boolean wasLocked = ensureLock(cms, sourceRes); 469 try { 470 CmsResource targetRes = cms.readResource(targetId); 471 cms.addRelationToResource(sourceRes.getRootPath(), targetRes.getRootPath(), cmsTypeName); 472 return "REL_" + sourceRes.getStructureId() + "_" + targetRes.getStructureId() + "_" + cmsTypeName; 473 } finally { 474 if (wasLocked) { 475 cms.unlockResource(sourceRes); 476 } 477 } 478 } catch (CmsException e) { 479 CmsCmisUtil.handleCmsException(e); 480 return null; 481 } 482 } 483 484 /** 485 * @see org.opencms.cmis.I_CmsCmisRepository#deleteContentStream(org.opencms.cmis.CmsCmisCallContext, org.apache.chemistry.opencmis.commons.spi.Holder, org.apache.chemistry.opencmis.commons.spi.Holder) 486 */ 487 public synchronized void deleteContentStream( 488 CmsCmisCallContext context, 489 Holder<String> objectId, 490 Holder<String> changeToken) { 491 492 throw new CmisConstraintException("Content streams may not be deleted."); 493 494 } 495 496 /** 497 * @see org.opencms.cmis.I_CmsCmisRepository#deleteObject(org.opencms.cmis.CmsCmisCallContext, java.lang.String, boolean) 498 */ 499 public synchronized void deleteObject(CmsCmisCallContext context, String objectId, boolean allVersions) { 500 501 checkWriteAccess(); 502 getHelper(objectId).deleteObject(context, objectId, allVersions); 503 } 504 505 /** 506 * @see org.opencms.cmis.I_CmsCmisRepository#deleteTree(org.opencms.cmis.CmsCmisCallContext, java.lang.String, boolean, org.apache.chemistry.opencmis.commons.enums.UnfileObject, boolean) 507 */ 508 public synchronized FailedToDeleteData deleteTree( 509 CmsCmisCallContext context, 510 String folderId, 511 boolean allVersions, 512 UnfileObject unfileObjects, 513 boolean continueOnFailure) { 514 515 checkWriteAccess(); 516 517 try { 518 519 FailedToDeleteDataImpl result = new FailedToDeleteDataImpl(); 520 result.setIds(new ArrayList<String>()); 521 CmsObject cms = getCmsObject(context); 522 CmsUUID structureId = new CmsUUID(folderId); 523 CmsResource folder = cms.readResource(structureId); 524 if (!folder.isFolder()) { 525 throw new CmisConstraintException("deleteTree can only be used on folders."); 526 } 527 ensureLock(cms, folder); 528 cms.deleteResource(folder.getRootPath(), CmsResource.DELETE_PRESERVE_SIBLINGS); 529 return result; 530 } catch (CmsException e) { 531 handleCmsException(e); 532 return null; 533 } 534 } 535 536 /** 537 * @see org.opencms.cmis.I_CmsCmisRepository#getAcl(org.opencms.cmis.CmsCmisCallContext, java.lang.String, boolean) 538 */ 539 public synchronized Acl getAcl(CmsCmisCallContext context, String objectId, boolean onlyBasicPermissions) { 540 541 return getHelper(objectId).getAcl(context, objectId, onlyBasicPermissions); 542 } 543 544 /** 545 * @see org.opencms.cmis.I_CmsCmisRepository#getAllowableActions(org.opencms.cmis.CmsCmisCallContext, java.lang.String) 546 */ 547 public synchronized AllowableActions getAllowableActions(CmsCmisCallContext context, String objectId) { 548 549 return getHelper(objectId).getAllowableActions(context, objectId); 550 } 551 552 /** 553 * @see org.opencms.cmis.I_CmsCmisRepository#getCheckedOutDocs(org.opencms.cmis.CmsCmisCallContext, java.lang.String, java.lang.String, java.lang.String, boolean, org.apache.chemistry.opencmis.commons.enums.IncludeRelationships, java.lang.String, java.math.BigInteger, java.math.BigInteger) 554 */ 555 public synchronized ObjectList getCheckedOutDocs( 556 CmsCmisCallContext context, 557 String folderId, 558 String filter, 559 String orderBy, 560 boolean includeAllowableActions, 561 IncludeRelationships includeRelationships, 562 String renditionFilter, 563 BigInteger maxItems, 564 BigInteger skipCount) { 565 566 ObjectListImpl result = new ObjectListImpl(); 567 result.setObjects(new ArrayList<ObjectData>()); 568 return result; 569 } 570 571 /** 572 * @see org.opencms.cmis.I_CmsCmisRepository#getChildren(org.opencms.cmis.CmsCmisCallContext, java.lang.String, java.lang.String, java.lang.String, boolean, org.apache.chemistry.opencmis.commons.enums.IncludeRelationships, java.lang.String, boolean, java.math.BigInteger, java.math.BigInteger) 573 */ 574 public synchronized ObjectInFolderList getChildren( 575 CmsCmisCallContext context, 576 String folderId, 577 String filter, 578 String orderBy, 579 boolean includeAllowableActions, 580 IncludeRelationships includeRelationships, 581 String renditionFilter, 582 boolean includePathSegment, 583 BigInteger maxItems, 584 BigInteger skipCount) { 585 586 try { 587 CmsCmisResourceHelper helper = getResourceHelper(); 588 589 // split filter 590 Set<String> filterCollection = splitFilter(filter); 591 // skip and max 592 int skip = (skipCount == null ? 0 : skipCount.intValue()); 593 if (skip < 0) { 594 skip = 0; 595 } 596 597 int max = (maxItems == null ? Integer.MAX_VALUE : maxItems.intValue()); 598 if (max < 0) { 599 max = Integer.MAX_VALUE; 600 } 601 602 CmsObject cms = getCmsObject(context); 603 CmsUUID structureId = new CmsUUID(folderId); 604 CmsResource folder = cms.readResource(structureId); 605 if (!folder.isFolder()) { 606 throw new CmisObjectNotFoundException("Not a folder!"); 607 } 608 609 // set object info of the the folder 610 if (context.isObjectInfoRequired()) { 611 helper.collectObjectData( 612 context, 613 cms, 614 folder, 615 null, 616 renditionFilter, 617 false, 618 false, 619 includeRelationships); 620 } 621 622 // prepare result 623 ObjectInFolderListImpl result = new ObjectInFolderListImpl(); 624 String folderSitePath = cms.getRequestContext().getSitePath(folder); 625 List<CmsResource> children = cms.getResourcesInFolder(folderSitePath, CmsResourceFilter.DEFAULT); 626 CmsObjectListLimiter<CmsResource> limiter = new CmsObjectListLimiter<CmsResource>( 627 children, 628 maxItems, 629 skipCount); 630 List<ObjectInFolderData> resultObjects = new ArrayList<ObjectInFolderData>(); 631 for (CmsResource child : limiter) { 632 // build and add child object 633 ObjectInFolderDataImpl objectInFolder = new ObjectInFolderDataImpl(); 634 objectInFolder.setObject( 635 helper.collectObjectData( 636 context, 637 cms, 638 child, 639 filterCollection, 640 renditionFilter, 641 includeAllowableActions, 642 false, 643 includeRelationships)); 644 if (includePathSegment) { 645 objectInFolder.setPathSegment(child.getName()); 646 } 647 resultObjects.add(objectInFolder); 648 } 649 result.setObjects(resultObjects); 650 result.setNumItems(BigInteger.valueOf(children.size())); 651 result.setHasMoreItems(Boolean.valueOf(limiter.hasMore())); 652 return result; 653 } catch (CmsException e) { 654 handleCmsException(e); 655 return null; 656 } 657 658 } 659 660 /** 661 * @see org.opencms.cmis.I_CmsCmisRepository#getConfiguration() 662 */ 663 public CmsParameterConfiguration getConfiguration() { 664 665 return m_parameterConfiguration; 666 } 667 668 /** 669 * @see org.opencms.cmis.I_CmsCmisRepository#getContentStream(org.opencms.cmis.CmsCmisCallContext, java.lang.String, java.lang.String, java.math.BigInteger, java.math.BigInteger) 670 */ 671 public synchronized ContentStream getContentStream( 672 CmsCmisCallContext context, 673 String objectId, 674 String streamId, 675 BigInteger offset, 676 BigInteger length) { 677 678 try { 679 CmsObject cms = getCmsObject(context); 680 CmsResource resource = cms.readResource(new CmsUUID(objectId)); 681 byte[] contents = null; 682 if (streamId != null) { 683 I_CmsCmisRenditionProvider renditionProvider = m_renditionProviders.get(streamId); 684 if (renditionProvider == null) { 685 throw new CmisRuntimeException("Invalid stream id " + streamId); 686 } 687 contents = renditionProvider.getContent(cms, resource); 688 } else if (resource.isFolder()) { 689 throw new CmisStreamNotSupportedException("Not a file!"); 690 } else { 691 CmsFile file = cms.readFile(resource); 692 contents = file.getContents(); 693 } 694 contents = extractRange(contents, offset, length); 695 InputStream stream = new ByteArrayInputStream(contents); 696 ContentStreamImpl result = new ContentStreamImpl(); 697 result.setFileName(resource.getName()); 698 result.setLength(BigInteger.valueOf(contents.length)); 699 result.setMimeType(OpenCms.getResourceManager().getMimeType(resource.getRootPath(), null, "text/plain")); 700 result.setStream(stream); 701 702 return result; 703 } catch (CmsException e) { 704 handleCmsException(e); 705 return null; 706 } 707 } 708 709 /** 710 * @see org.opencms.cmis.I_CmsCmisRepository#getDescendants(org.opencms.cmis.CmsCmisCallContext, java.lang.String, java.math.BigInteger, java.lang.String, boolean, boolean, boolean) 711 */ 712 public synchronized List<ObjectInFolderContainer> getDescendants( 713 CmsCmisCallContext context, 714 String folderId, 715 BigInteger depth, 716 String filter, 717 boolean includeAllowableActions, 718 boolean includePathSegment, 719 boolean foldersOnly) { 720 721 try { 722 CmsCmisResourceHelper helper = getResourceHelper(); 723 724 // check depth 725 int d = (depth == null ? 2 : depth.intValue()); 726 if (d == 0) { 727 throw new CmisInvalidArgumentException("Depth must not be 0!"); 728 } 729 if (d < -1) { 730 d = -1; 731 } 732 733 // split filter 734 Set<String> filterCollection = splitFilter(filter); 735 736 CmsObject cms = getCmsObject(context); 737 CmsUUID folderStructureId = new CmsUUID(folderId); 738 CmsResource folder = cms.readResource(folderStructureId); 739 if (!folder.isFolder()) { 740 throw new CmisObjectNotFoundException("Not a folder!"); 741 } 742 743 // set object info of the the folder 744 if (context.isObjectInfoRequired()) { 745 helper.collectObjectData( 746 context, 747 cms, 748 folder, 749 null, 750 "cmis:none", 751 false, 752 false, 753 IncludeRelationships.NONE); 754 } 755 756 // get the tree 757 List<ObjectInFolderContainer> result = new ArrayList<ObjectInFolderContainer>(); 758 gatherDescendants( 759 context, 760 cms, 761 folder, 762 result, 763 foldersOnly, 764 d, 765 filterCollection, 766 includeAllowableActions, 767 includePathSegment); 768 769 return result; 770 } catch (CmsException e) { 771 handleCmsException(e); 772 return null; 773 } 774 } 775 776 /** 777 * @see org.opencms.cmis.I_CmsCmisRepository#getDescription() 778 */ 779 public String getDescription() { 780 781 if (m_description != null) { 782 return m_description; 783 } 784 if (m_project != null) { 785 return m_project.getDescription(); 786 } 787 return m_id; 788 } 789 790 /** 791 * @see org.opencms.cmis.I_CmsCmisRepository#getFilter() 792 */ 793 public CmsRepositoryFilter getFilter() { 794 795 return m_filter; 796 } 797 798 /** 799 * @see org.opencms.cmis.I_CmsCmisRepository#getFolderParent(org.opencms.cmis.CmsCmisCallContext, java.lang.String, java.lang.String) 800 */ 801 public synchronized ObjectData getFolderParent(CmsCmisCallContext context, String folderId, String filter) { 802 803 List<ObjectParentData> parents = getObjectParents(context, folderId, filter, false, false); 804 if (parents.size() == 0) { 805 throw new CmisInvalidArgumentException("The root folder has no parent!"); 806 } 807 return parents.get(0).getObject(); 808 } 809 810 /** 811 * @see org.opencms.cmis.I_CmsCmisRepository#getId() 812 */ 813 public String getId() { 814 815 return m_id; 816 } 817 818 /** 819 * @see org.opencms.cmis.I_CmsCmisRepository#getName() 820 */ 821 public String getName() { 822 823 return m_id; 824 } 825 826 /** 827 * @see org.opencms.cmis.I_CmsCmisRepository#getObject(org.opencms.cmis.CmsCmisCallContext, java.lang.String, java.lang.String, boolean, org.apache.chemistry.opencmis.commons.enums.IncludeRelationships, java.lang.String, boolean, boolean) 828 */ 829 public synchronized ObjectData getObject( 830 CmsCmisCallContext context, 831 String objectId, 832 String filter, 833 boolean includeAllowableActions, 834 IncludeRelationships includeRelationships, 835 String renditionFilter, 836 boolean includePolicyIds, 837 boolean includeAcl) { 838 839 return getHelper(objectId).getObject( 840 context, 841 objectId, 842 filter, 843 includeAllowableActions, 844 includeRelationships, 845 renditionFilter, 846 includePolicyIds, 847 includeAcl); 848 } 849 850 /** 851 * @see org.opencms.cmis.I_CmsCmisRepository#getObjectByPath(org.opencms.cmis.CmsCmisCallContext, java.lang.String, java.lang.String, boolean, org.apache.chemistry.opencmis.commons.enums.IncludeRelationships, java.lang.String, boolean, boolean) 852 */ 853 public synchronized ObjectData getObjectByPath( 854 CmsCmisCallContext context, 855 String path, 856 String filter, 857 boolean includeAllowableActions, 858 IncludeRelationships includeRelationships, 859 String renditionFilter, 860 boolean includePolicyIds, 861 boolean includeAcl 862 863 ) { 864 865 try { 866 CmsCmisResourceHelper helper = getResourceHelper(); 867 868 // split filter 869 Set<String> filterCollection = splitFilter(filter); 870 871 // check path 872 if (CmsStringUtil.isEmptyOrWhitespaceOnly(path)) { 873 throw new CmisInvalidArgumentException("Invalid folder path!"); 874 } 875 CmsObject cms = getCmsObject(context); 876 CmsResource file = cms.readResource(path); 877 878 return helper.collectObjectData( 879 context, 880 cms, 881 file, 882 filterCollection, 883 renditionFilter, 884 includeAllowableActions, 885 includeAcl, 886 IncludeRelationships.NONE); 887 888 } catch (CmsException e) { 889 handleCmsException(e); 890 return null; 891 } 892 } 893 894 /** 895 * @see org.opencms.cmis.I_CmsCmisRepository#getObjectParents(org.opencms.cmis.CmsCmisCallContext, java.lang.String, java.lang.String, boolean, boolean) 896 */ 897 public synchronized List<ObjectParentData> getObjectParents( 898 CmsCmisCallContext context, 899 String objectId, 900 String filter, 901 boolean includeAllowableActions, 902 boolean includeRelativePathSegment) { 903 904 try { 905 CmsCmisResourceHelper helper = getResourceHelper(); 906 907 // split filter 908 Set<String> filterCollection = splitFilter(filter); 909 CmsObject cms = getCmsObject(context); 910 CmsUUID structureId = new CmsUUID(objectId); 911 CmsResource file = cms.readResource(structureId); 912 // don't climb above the root folder 913 914 if (m_root.equals(file)) { 915 return Collections.emptyList(); 916 } 917 918 // set object info of the the object 919 if (context.isObjectInfoRequired()) { 920 helper.collectObjectData( 921 context, 922 cms, 923 file, 924 null, 925 "cmis:none", 926 false, 927 false, 928 IncludeRelationships.NONE); 929 } 930 931 // get parent folder 932 CmsResource parent = cms.readParentFolder(file.getStructureId()); 933 ObjectData object = helper.collectObjectData( 934 context, 935 cms, 936 parent, 937 filterCollection, 938 "cmis:none", 939 includeAllowableActions, 940 false, 941 IncludeRelationships.NONE); 942 943 ObjectParentDataImpl result = new ObjectParentDataImpl(); 944 result.setObject(object); 945 if (includeRelativePathSegment) { 946 result.setRelativePathSegment(file.getName()); 947 } 948 949 return Collections.singletonList((ObjectParentData)result); 950 } catch (CmsException e) { 951 handleCmsException(e); 952 return null; 953 } 954 955 } 956 957 /** 958 * @see org.opencms.cmis.I_CmsCmisRepository#getObjectRelationships(org.opencms.cmis.CmsCmisCallContext, java.lang.String, boolean, org.apache.chemistry.opencmis.commons.enums.RelationshipDirection, java.lang.String, java.lang.String, boolean, java.math.BigInteger, java.math.BigInteger) 959 */ 960 public synchronized ObjectList getObjectRelationships( 961 CmsCmisCallContext context, 962 String objectId, 963 boolean includeSubRelationshipTypes, 964 RelationshipDirection relationshipDirection, 965 String typeId, 966 String filter, 967 boolean includeAllowableActions, 968 BigInteger maxItems, 969 BigInteger skipCount) { 970 971 try { 972 CmsObject cms = getCmsObject(context); 973 ObjectListImpl result = new ObjectListImpl(); 974 CmsUUID structureId = new CmsUUID(objectId); 975 CmsResource resource = cms.readResource(structureId); 976 977 List<ObjectData> resultObjects = getRelationshipObjectData( 978 context, 979 cms, 980 resource, 981 relationshipDirection, 982 CmsCmisUtil.splitFilter(filter), 983 includeAllowableActions); 984 CmsObjectListLimiter<ObjectData> limiter = new CmsObjectListLimiter<ObjectData>( 985 resultObjects, 986 maxItems, 987 skipCount); 988 List<ObjectData> limitedResults = new ArrayList<ObjectData>(); 989 for (ObjectData objectData : limiter) { 990 limitedResults.add(objectData); 991 } 992 result.setNumItems(BigInteger.valueOf(resultObjects.size())); 993 result.setHasMoreItems(Boolean.valueOf(limiter.hasMore())); 994 result.setObjects(limitedResults); 995 return result; 996 } catch (CmsException e) { 997 CmsCmisUtil.handleCmsException(e); 998 return null; 999 } 1000 } 1001 1002 /** 1003 * @see org.opencms.cmis.I_CmsCmisRepository#getProperties(org.opencms.cmis.CmsCmisCallContext, java.lang.String, java.lang.String) 1004 */ 1005 public synchronized Properties getProperties(CmsCmisCallContext context, String objectId, String filter) { 1006 1007 ObjectData object = getObject(context, objectId, null, false, null, null, false, false); 1008 return object.getProperties(); 1009 } 1010 1011 /** 1012 * @see org.opencms.cmis.I_CmsCmisRepository#getRenditions(org.opencms.cmis.CmsCmisCallContext, java.lang.String, java.lang.String, java.math.BigInteger, java.math.BigInteger) 1013 */ 1014 public synchronized List<RenditionData> getRenditions( 1015 CmsCmisCallContext context, 1016 String objectId, 1017 String renditionFilter, 1018 BigInteger maxItems, 1019 BigInteger skipCount) { 1020 1021 try { 1022 CmsObject cms = getCmsObject(context); 1023 CmsResource resource = cms.readResource(new CmsUUID(objectId)); 1024 return getResourceHelper().collectObjectData( 1025 context, 1026 cms, 1027 resource, 1028 null, 1029 renditionFilter, 1030 false, 1031 false, 1032 IncludeRelationships.NONE).getRenditions(); 1033 } catch (CmsException e) { 1034 handleCmsException(e); 1035 return null; 1036 } 1037 } 1038 1039 /** 1040 * @see org.opencms.cmis.I_CmsCmisRepository#getRepositoryInfo() 1041 */ 1042 public synchronized RepositoryInfo getRepositoryInfo() { 1043 1044 // compile repository info 1045 RepositoryInfoImpl repositoryInfo = new RepositoryInfoImpl(); 1046 1047 repositoryInfo.setId(m_id); 1048 repositoryInfo.setName(getName()); 1049 repositoryInfo.setDescription(getDescription()); 1050 1051 repositoryInfo.setCmisVersionSupported("1.0"); 1052 1053 repositoryInfo.setProductName("OpenCms"); 1054 repositoryInfo.setProductVersion(OpenCms.getSystemInfo().getVersion()); 1055 repositoryInfo.setVendorName("Alkacon Software GmbH & Co. KG"); 1056 repositoryInfo.setRootFolder(m_root.getStructureId().toString()); 1057 repositoryInfo.setThinClientUri(""); 1058 repositoryInfo.setPrincipalAnonymous(OpenCms.getDefaultUsers().getUserGuest()); 1059 repositoryInfo.setChangesIncomplete(Boolean.TRUE); 1060 RepositoryCapabilitiesImpl capabilities = new RepositoryCapabilitiesImpl(); 1061 capabilities.setCapabilityAcl(CapabilityAcl.DISCOVER); 1062 capabilities.setAllVersionsSearchable(Boolean.FALSE); 1063 capabilities.setCapabilityJoin(CapabilityJoin.NONE); 1064 capabilities.setSupportsMultifiling(Boolean.FALSE); 1065 capabilities.setSupportsUnfiling(Boolean.FALSE); 1066 capabilities.setSupportsVersionSpecificFiling(Boolean.FALSE); 1067 capabilities.setIsPwcSearchable(Boolean.FALSE); 1068 capabilities.setIsPwcUpdatable(Boolean.FALSE); 1069 capabilities.setCapabilityQuery(getIndex() != null ? CapabilityQuery.FULLTEXTONLY : CapabilityQuery.NONE); 1070 capabilities.setCapabilityChanges(CapabilityChanges.NONE); 1071 capabilities.setCapabilityContentStreamUpdates(CapabilityContentStreamUpdates.ANYTIME); 1072 capabilities.setSupportsGetDescendants(Boolean.TRUE); 1073 capabilities.setSupportsGetFolderTree(Boolean.TRUE); 1074 capabilities.setCapabilityRendition(CapabilityRenditions.READ); 1075 repositoryInfo.setCapabilities(capabilities); 1076 1077 AclCapabilitiesDataImpl aclCapability = new AclCapabilitiesDataImpl(); 1078 aclCapability.setSupportedPermissions(SupportedPermissions.BOTH); 1079 aclCapability.setAclPropagation(AclPropagation.REPOSITORYDETERMINED); 1080 1081 // permissions 1082 List<PermissionDefinition> permissions = new ArrayList<PermissionDefinition>(); 1083 permissions.add(createPermission(CMIS_READ, "Read")); 1084 permissions.add(createPermission(CMIS_WRITE, "Write")); 1085 permissions.add(createPermission(CMIS_ALL, "All")); 1086 aclCapability.setPermissionDefinitionData(permissions); 1087 1088 // mappings 1089 PermissionMappings m = new PermissionMappings(); 1090 m.add(PermissionMapping.CAN_CREATE_DOCUMENT_FOLDER, CMIS_WRITE); 1091 m.add(PermissionMapping.CAN_CREATE_FOLDER_FOLDER, CMIS_WRITE); 1092 m.add(PermissionMapping.CAN_DELETE_CONTENT_DOCUMENT, CMIS_WRITE); 1093 m.add(PermissionMapping.CAN_DELETE_OBJECT, CMIS_WRITE); 1094 m.add(PermissionMapping.CAN_DELETE_TREE_FOLDER, CMIS_WRITE); 1095 m.add(PermissionMapping.CAN_GET_ACL_OBJECT, CMIS_READ); 1096 m.add(PermissionMapping.CAN_GET_ALL_VERSIONS_VERSION_SERIES, CMIS_READ); 1097 m.add(PermissionMapping.CAN_GET_CHILDREN_FOLDER, CMIS_READ); 1098 m.add(PermissionMapping.CAN_GET_DESCENDENTS_FOLDER, CMIS_READ); 1099 m.add(PermissionMapping.CAN_GET_FOLDER_PARENT_OBJECT, CMIS_READ); 1100 m.add(PermissionMapping.CAN_GET_PARENTS_FOLDER, CMIS_READ); 1101 m.add(PermissionMapping.CAN_GET_PROPERTIES_OBJECT, CMIS_READ); 1102 m.add(PermissionMapping.CAN_MOVE_OBJECT, CMIS_WRITE); 1103 m.add(PermissionMapping.CAN_MOVE_SOURCE, CMIS_WRITE); 1104 m.add(PermissionMapping.CAN_MOVE_TARGET, CMIS_WRITE); 1105 m.add(PermissionMapping.CAN_SET_CONTENT_DOCUMENT, CMIS_WRITE); 1106 m.add(PermissionMapping.CAN_UPDATE_PROPERTIES_OBJECT, CMIS_WRITE); 1107 m.add(PermissionMapping.CAN_VIEW_CONTENT_OBJECT, CMIS_READ); 1108 aclCapability.setPermissionMappingData(m); 1109 repositoryInfo.setAclCapabilities(aclCapability); 1110 return repositoryInfo; 1111 } 1112 1113 /** 1114 * @see org.opencms.cmis.I_CmsCmisRepository#getTypeChildren(org.opencms.cmis.CmsCmisCallContext, java.lang.String, boolean, java.math.BigInteger, java.math.BigInteger) 1115 */ 1116 public synchronized TypeDefinitionList getTypeChildren( 1117 CmsCmisCallContext context, 1118 String typeId, 1119 boolean includePropertyDefinitions, 1120 BigInteger maxItems, 1121 BigInteger skipCount) { 1122 1123 return m_typeManager.getTypeChildren(typeId, includePropertyDefinitions, maxItems, skipCount); 1124 } 1125 1126 /** 1127 * @see org.opencms.cmis.I_CmsCmisRepository#getTypeDefinition(org.opencms.cmis.CmsCmisCallContext, java.lang.String) 1128 */ 1129 public synchronized TypeDefinition getTypeDefinition(CmsCmisCallContext context, String typeId) { 1130 1131 return m_typeManager.getTypeDefinition(typeId); 1132 } 1133 1134 /** 1135 * @see org.opencms.cmis.I_CmsCmisRepository#getTypeDescendants(org.opencms.cmis.CmsCmisCallContext, java.lang.String, java.math.BigInteger, boolean) 1136 */ 1137 public synchronized List<TypeDefinitionContainer> getTypeDescendants( 1138 CmsCmisCallContext context, 1139 String typeId, 1140 BigInteger depth, 1141 boolean includePropertyDefinitions) { 1142 1143 return m_typeManager.getTypeDescendants(typeId, depth, includePropertyDefinitions); 1144 } 1145 1146 /** 1147 * @see org.opencms.cmis.I_CmsCmisRepository#initConfiguration() 1148 */ 1149 public void initConfiguration() throws CmsConfigurationException { 1150 1151 if (m_filter != null) { 1152 m_filter.initConfiguration(); 1153 } 1154 m_description = m_parameterConfiguration.getString(PARAM_DESCRIPTION, null); 1155 List<String> renditionProviderClasses = m_parameterConfiguration.getList( 1156 PARAM_RENDITION, 1157 Collections.<String> emptyList()); 1158 for (String className : renditionProviderClasses) { 1159 try { 1160 I_CmsCmisRenditionProvider provider = (I_CmsCmisRenditionProvider)(Class.forName( 1161 className).newInstance()); 1162 String id = provider.getId(); 1163 m_renditionProviders.put(id, provider); 1164 } catch (Throwable e) { 1165 LOG.error(e.getLocalizedMessage(), e); 1166 } 1167 } 1168 List<String> propertyProviderClasses = m_parameterConfiguration.getList( 1169 PARAM_PROPERTY, 1170 Collections.<String> emptyList()); 1171 for (String className : propertyProviderClasses) { 1172 try { 1173 I_CmsPropertyProvider provider = (I_CmsPropertyProvider)(Class.forName(className).newInstance()); 1174 m_propertyProviders.add(provider); 1175 } catch (Throwable e) { 1176 LOG.error(e.getLocalizedMessage(), e); 1177 } 1178 } 1179 m_indexName = m_parameterConfiguration.getString(PARAM_INDEX, null); 1180 } 1181 1182 /** 1183 * @see org.opencms.cmis.I_CmsCmisRepository#initializeCms(org.opencms.file.CmsObject) 1184 */ 1185 public void initializeCms(CmsObject cms) throws CmsException { 1186 1187 m_adminCms = cms; 1188 m_typeManager = new CmsCmisTypeManager(cms, m_propertyProviders); 1189 String projectName = m_parameterConfiguration.getString(PARAM_PROJECT, CmsProject.ONLINE_PROJECT_NAME); 1190 CmsResource root = m_adminCms.readResource("/"); 1191 CmsObject offlineCms = OpenCms.initCmsObject(m_adminCms); 1192 CmsProject project = m_adminCms.readProject(projectName); 1193 m_project = project; 1194 offlineCms.getRequestContext().setCurrentProject(project); 1195 m_adminCms = offlineCms; 1196 m_root = root; 1197 m_isReadOnly = project.isOnlineProject(); 1198 } 1199 1200 /** 1201 * @see org.opencms.cmis.I_CmsCmisRepository#moveObject(org.opencms.cmis.CmsCmisCallContext, org.apache.chemistry.opencmis.commons.spi.Holder, java.lang.String, java.lang.String) 1202 */ 1203 public synchronized void moveObject( 1204 CmsCmisCallContext context, 1205 Holder<String> objectId, 1206 String targetFolderId, 1207 String sourceFolderId) { 1208 1209 checkWriteAccess(); 1210 1211 try { 1212 CmsObject cms = getCmsObject(context); 1213 CmsUUID structureId = new CmsUUID(objectId.getValue()); 1214 CmsUUID targetStructureId = new CmsUUID(targetFolderId); 1215 CmsResource targetFolder = cms.readResource(targetStructureId); 1216 CmsResource resourceToMove = cms.readResource(structureId); 1217 String name = CmsResource.getName(resourceToMove.getRootPath()); 1218 String newPath = CmsStringUtil.joinPaths(targetFolder.getRootPath(), name); 1219 boolean wasLocked = ensureLock(cms, resourceToMove); 1220 try { 1221 cms.moveResource(resourceToMove.getRootPath(), newPath); 1222 } finally { 1223 if (wasLocked) { 1224 CmsResource movedResource = cms.readResource(resourceToMove.getStructureId()); 1225 cms.unlockResource(movedResource); 1226 } 1227 } 1228 } catch (CmsException e) { 1229 handleCmsException(e); 1230 } 1231 } 1232 1233 /** 1234 * @see org.opencms.cmis.I_CmsCmisRepository#query(org.opencms.cmis.CmsCmisCallContext, java.lang.String, boolean, boolean, org.apache.chemistry.opencmis.commons.enums.IncludeRelationships, java.lang.String, java.math.BigInteger, java.math.BigInteger) 1235 */ 1236 @Override 1237 public synchronized ObjectList query( 1238 CmsCmisCallContext context, 1239 String statement, 1240 boolean searchAllVersions, 1241 boolean includeAllowableActions, 1242 IncludeRelationships includeRelationships, 1243 String renditionFilter, 1244 BigInteger maxItems, 1245 BigInteger skipCount) { 1246 1247 try { 1248 CmsObject cms = getCmsObject(context); 1249 CmsSolrIndex index = getIndex(); 1250 CmsCmisResourceHelper helper = getResourceHelper(); 1251 1252 // split filter 1253 Set<String> filterCollection = null; 1254 // skip and max 1255 int skip = (skipCount == null ? 0 : skipCount.intValue()); 1256 if (skip < 0) { 1257 skip = 0; 1258 } 1259 1260 int max = (maxItems == null ? Integer.MAX_VALUE : maxItems.intValue()); 1261 if (max < 0) { 1262 max = Integer.MAX_VALUE; 1263 } 1264 CmsSolrResultList results = solrSearch(cms, index, statement, skip, max); 1265 ObjectListImpl resultObjectList = new ObjectListImpl(); 1266 List<ObjectData> objectDataList = new ArrayList<ObjectData>(); 1267 resultObjectList.setObjects(objectDataList); 1268 for (CmsResource resource : results) { 1269 // build and add child object 1270 objectDataList.add( 1271 helper.collectObjectData( 1272 context, 1273 cms, 1274 resource, 1275 filterCollection, 1276 renditionFilter, 1277 includeAllowableActions, 1278 false, 1279 includeRelationships)); 1280 } 1281 resultObjectList.setHasMoreItems(Boolean.valueOf(!results.isEmpty())); 1282 resultObjectList.setNumItems(BigInteger.valueOf(results.getVisibleHitCount())); 1283 return resultObjectList; 1284 } catch (CmsException e) { 1285 handleCmsException(e); 1286 return null; 1287 } 1288 1289 } 1290 1291 /** 1292 * @see org.opencms.cmis.I_CmsCmisRepository#setContentStream(org.opencms.cmis.CmsCmisCallContext, org.apache.chemistry.opencmis.commons.spi.Holder, boolean, org.apache.chemistry.opencmis.commons.spi.Holder, org.apache.chemistry.opencmis.commons.data.ContentStream) 1293 */ 1294 public synchronized void setContentStream( 1295 CmsCmisCallContext context, 1296 Holder<String> objectId, 1297 boolean overwriteFlag, 1298 Holder<String> changeToken, 1299 ContentStream contentStream) { 1300 1301 checkWriteAccess(); 1302 1303 try { 1304 CmsObject cms = getCmsObject(context); 1305 CmsUUID structureId = new CmsUUID(objectId.getValue()); 1306 if (!overwriteFlag) { 1307 throw new CmisContentAlreadyExistsException(); 1308 } 1309 CmsResource resource = cms.readResource(structureId); 1310 if (resource.isFolder()) { 1311 throw new CmisStreamNotSupportedException("Folders may not have content streams."); 1312 } 1313 CmsFile file = cms.readFile(resource); 1314 InputStream contentInput = contentStream.getStream(); 1315 byte[] newContent = CmsFileUtil.readFully(contentInput); 1316 file.setContents(newContent); 1317 boolean wasLocked = ensureLock(cms, resource); 1318 CmsFile newFile = cms.writeFile(file); 1319 if (wasLocked) { 1320 cms.unlockResource(newFile); 1321 } 1322 } catch (CmsException e) { 1323 handleCmsException(e); 1324 } catch (IOException e) { 1325 throw new CmisRuntimeException(e.getLocalizedMessage(), e); 1326 } 1327 } 1328 1329 /** 1330 * @see org.opencms.cmis.I_CmsCmisRepository#setFilter(org.opencms.repository.CmsRepositoryFilter) 1331 */ 1332 public void setFilter(CmsRepositoryFilter filter) { 1333 1334 m_filter = filter; 1335 LOG.warn("Filters not supported by CMIS repositories, ignoring configuration..."); 1336 } 1337 1338 /** 1339 * @see org.opencms.cmis.I_CmsCmisRepository#setName(java.lang.String) 1340 */ 1341 public void setName(String name) { 1342 1343 m_id = name; 1344 } 1345 1346 /** 1347 * @see org.opencms.cmis.I_CmsCmisRepository#updateProperties(org.opencms.cmis.CmsCmisCallContext, org.apache.chemistry.opencmis.commons.spi.Holder, org.apache.chemistry.opencmis.commons.spi.Holder, org.apache.chemistry.opencmis.commons.data.Properties) 1348 */ 1349 public synchronized void updateProperties( 1350 CmsCmisCallContext context, 1351 Holder<String> objectId, 1352 Holder<String> changeToken, 1353 Properties properties) { 1354 1355 checkWriteAccess(); 1356 1357 try { 1358 1359 CmsObject cms = getCmsObject(context); 1360 CmsUUID structureId = new CmsUUID(objectId.getValue()); 1361 CmsResource resource = cms.readResource(structureId); 1362 Map<String, PropertyData<?>> propertyMap = properties.getProperties(); 1363 List<CmsProperty> cmsProperties = getOpenCmsProperties(propertyMap); 1364 boolean wasLocked = ensureLock(cms, resource); 1365 try { 1366 cms.writePropertyObjects(resource, cmsProperties); 1367 @SuppressWarnings("unchecked") 1368 PropertyData<String> nameProperty = (PropertyData<String>)propertyMap.get(PropertyIds.NAME); 1369 if (nameProperty != null) { 1370 String newName = nameProperty.getFirstValue(); 1371 checkResourceName(newName); 1372 String parentFolder = CmsResource.getParentFolder(resource.getRootPath()); 1373 String newPath = CmsStringUtil.joinPaths(parentFolder, newName); 1374 cms.moveResource(resource.getRootPath(), newPath); 1375 resource = cms.readResource(resource.getStructureId()); 1376 } 1377 1378 for (String key : properties.getProperties().keySet()) { 1379 if (key.startsWith(CmsCmisTypeManager.PROPERTY_PREFIX_DYNAMIC)) { 1380 I_CmsPropertyProvider provider = getTypeManager().getPropertyProvider(key); 1381 try { 1382 String value = (String)(properties.getProperties().get(key).getFirstValue()); 1383 provider.setPropertyValue(cms, resource, value); 1384 } catch (CmsException e) { 1385 LOG.error(e.getLocalizedMessage(), e); 1386 } 1387 } 1388 } 1389 } finally { 1390 if (wasLocked) { 1391 cms.unlockResource(resource); 1392 } 1393 } 1394 } catch (CmsException e) { 1395 handleCmsException(e); 1396 } 1397 } 1398 1399 /** 1400 * Checks whether we have write access to this repository and throws an exception otherwise.<p> 1401 */ 1402 protected void checkWriteAccess() { 1403 1404 if (m_isReadOnly) { 1405 throw new CmisNotSupportedException("Readonly repository '" + m_id + "' does not allow write operations."); 1406 } 1407 } 1408 1409 /** 1410 * Initializes a CMS context for the authentication data contained in a call context.<p> 1411 * 1412 * @param context the call context 1413 * @return the initialized CMS context 1414 */ 1415 protected CmsObject getCmsObject(CmsCmisCallContext context) { 1416 1417 try { 1418 if (context.getUsername() == null) { 1419 // user name can be null 1420 CmsObject cms = OpenCms.initCmsObject(OpenCms.getDefaultUsers().getUserGuest()); 1421 cms.getRequestContext().setCurrentProject(m_adminCms.getRequestContext().getCurrentProject()); 1422 return cms; 1423 } else { 1424 CmsObject cms = OpenCms.initCmsObject(m_adminCms); 1425 CmsProject projectBeforeLogin = cms.getRequestContext().getCurrentProject(); 1426 cms.loginUser(context.getUsername(), context.getPassword()); 1427 cms.getRequestContext().setCurrentProject(projectBeforeLogin); 1428 return cms; 1429 } 1430 } catch (CmsException e) { 1431 throw new CmisPermissionDeniedException(e.getLocalizedMessage(), e); 1432 1433 } 1434 } 1435 1436 /** 1437 * Gets the relationship data for a given resource.<p> 1438 * 1439 * @param context the call context 1440 * @param cms the CMS context 1441 * @param resource the resource 1442 * @param relationshipDirection the relationship direction 1443 * @param filterSet the property filter 1444 * @param includeAllowableActions true if allowable actions should be included 1445 * @return the list of relationship data 1446 * 1447 * @throws CmsException if something goes wrong 1448 */ 1449 protected List<ObjectData> getRelationshipObjectData( 1450 CmsCmisCallContext context, 1451 CmsObject cms, 1452 CmsResource resource, 1453 RelationshipDirection relationshipDirection, 1454 Set<String> filterSet, 1455 boolean includeAllowableActions) 1456 throws CmsException { 1457 1458 List<ObjectData> resultObjects = new ArrayList<ObjectData>(); 1459 CmsRelationFilter relationFilter; 1460 if (relationshipDirection == RelationshipDirection.SOURCE) { 1461 relationFilter = CmsRelationFilter.TARGETS; 1462 } else if (relationshipDirection == RelationshipDirection.TARGET) { 1463 relationFilter = CmsRelationFilter.SOURCES; 1464 } else { 1465 relationFilter = CmsRelationFilter.ALL; 1466 } 1467 1468 List<CmsRelation> unfilteredRelations = cms.getRelationsForResource(resource.getRootPath(), relationFilter); 1469 List<CmsRelation> relations = new ArrayList<CmsRelation>(); 1470 for (CmsRelation relation : unfilteredRelations) { 1471 if (relation.getTargetId().isNullUUID() || relation.getSourceId().isNullUUID()) { 1472 continue; 1473 } 1474 relations.add(relation); 1475 } 1476 CmsCmisRelationHelper helper = getRelationHelper(); 1477 for (CmsRelation relation : relations) { 1478 ObjectData objData = helper.collectObjectData( 1479 context, 1480 cms, 1481 resource, 1482 relation, 1483 filterSet, 1484 includeAllowableActions, 1485 false); 1486 resultObjects.add(objData); 1487 } 1488 return resultObjects; 1489 } 1490 1491 /** 1492 * Gets the rendition providers matching the given filter.<p> 1493 * 1494 * @param filter the rendition filter 1495 * 1496 * @return the rendition providers matching the filter 1497 */ 1498 protected List<I_CmsCmisRenditionProvider> getRenditionProviders(CmsCmisRenditionFilter filter) { 1499 1500 List<I_CmsCmisRenditionProvider> result = new ArrayList<I_CmsCmisRenditionProvider>(); 1501 for (I_CmsCmisRenditionProvider provider : m_renditionProviders.values()) { 1502 String mimetype = provider.getMimeType(); 1503 String kind = provider.getKind(); 1504 if (filter.accept(kind, mimetype)) { 1505 result.add(provider); 1506 } 1507 } 1508 return result; 1509 } 1510 1511 /** 1512 * Extracts the resource type from a set of CMIS properties.<p> 1513 * 1514 * @param properties the CMIS properties 1515 * @param defaultValue the default value 1516 * 1517 * @return the resource type property, or the default value if the property was not found 1518 */ 1519 protected String getResourceTypeFromProperties(Map<String, PropertyData<?>> properties, String defaultValue) { 1520 1521 PropertyData<?> typeProp = properties.get(CmsCmisTypeManager.PROPERTY_RESOURCE_TYPE); 1522 String resTypeName = defaultValue; 1523 if (typeProp != null) { 1524 resTypeName = (String)typeProp.getFirstValue(); 1525 } 1526 return resTypeName; 1527 } 1528 1529 /** 1530 * Gets the type manager instance.<p> 1531 * 1532 * @return the type manager instance 1533 */ 1534 protected CmsCmisTypeManager getTypeManager() { 1535 1536 return m_typeManager; 1537 } 1538 1539 /** 1540 * Gets the correct helper object for a given object id to perform operations on the corresponding object.<p> 1541 * 1542 * @param objectId the object id 1543 * 1544 * @return the helper object to use for the given object id 1545 */ 1546 I_CmsCmisObjectHelper getHelper(String objectId) { 1547 1548 if (CmsUUID.isValidUUID(objectId)) { 1549 return getResourceHelper(); 1550 } else if (CmsCmisRelationHelper.RELATION_PATTERN.matcher(objectId).matches()) { 1551 return getRelationHelper(); 1552 } else { 1553 return null; 1554 } 1555 } 1556 1557 /** 1558 * Helper method for executing a query.<p> 1559 * 1560 * @param cms the CMS context to use 1561 * @param index the index to use for the query 1562 * @param query the query to perform 1563 * @param start the start offset 1564 * @param rows the number of results to return 1565 * 1566 * @return the list of search results 1567 * @throws CmsSearchException if something goes wrong 1568 */ 1569 CmsSolrResultList solrSearch(CmsObject cms, CmsSolrIndex index, String query, int start, int rows) 1570 throws CmsSearchException { 1571 1572 CmsSolrQuery q = new CmsSolrQuery(null, CmsRequestUtil.createParameterMap(query)); 1573 q.setStart(new Integer(start)); 1574 q.setRows(new Integer(rows)); 1575 CmsSolrResultList resultPage = index.search(cms, q, true); 1576 return resultPage; 1577 } 1578 1579 /** 1580 * Helper method to collect the descendants of a given folder.<p> 1581 * 1582 * @param context the call context 1583 * @param cms the CMS context 1584 * @param folder the parent folder 1585 * @param list the list to which the descendants should be added 1586 * @param foldersOnly flag to exclude files from the result 1587 * @param depth the maximum depth 1588 * @param filter the property filter 1589 * @param includeAllowableActions flag to include allowable actions 1590 * @param includePathSegments flag to include path segments 1591 */ 1592 private void gatherDescendants( 1593 CmsCmisCallContext context, 1594 CmsObject cms, 1595 CmsResource folder, 1596 List<ObjectInFolderContainer> list, 1597 boolean foldersOnly, 1598 int depth, 1599 Set<String> filter, 1600 boolean includeAllowableActions, 1601 boolean includePathSegments) { 1602 1603 try { 1604 CmsCmisResourceHelper helper = getResourceHelper(); 1605 List<CmsResource> children = cms.getResourcesInFolder(cms.getSitePath(folder), CmsResourceFilter.DEFAULT); 1606 Collections.sort(children, new Comparator<CmsResource>() { 1607 1608 public int compare(CmsResource a, CmsResource b) { 1609 1610 return a.getName().compareTo(b.getName()); 1611 } 1612 }); 1613 // iterate through children 1614 for (CmsResource child : children) { 1615 1616 // folders only? 1617 if (foldersOnly && !child.isFolder()) { 1618 continue; 1619 } 1620 1621 // add to list 1622 ObjectInFolderDataImpl objectInFolder = new ObjectInFolderDataImpl(); 1623 objectInFolder.setObject( 1624 helper.collectObjectData( 1625 context, 1626 cms, 1627 child, 1628 filter, 1629 "cmis:none", 1630 includeAllowableActions, 1631 false, 1632 IncludeRelationships.NONE)); 1633 if (includePathSegments) { 1634 objectInFolder.setPathSegment(child.getName()); 1635 } 1636 1637 ObjectInFolderContainerImpl container = new ObjectInFolderContainerImpl(); 1638 container.setObject(objectInFolder); 1639 1640 list.add(container); 1641 1642 // move to next level 1643 if ((depth != 1) && child.isFolder()) { 1644 container.setChildren(new ArrayList<ObjectInFolderContainer>()); 1645 gatherDescendants( 1646 context, 1647 cms, 1648 child, 1649 container.getChildren(), 1650 foldersOnly, 1651 depth - 1, 1652 filter, 1653 includeAllowableActions, 1654 includePathSegments); 1655 } 1656 } 1657 } catch (CmsException e) { 1658 handleCmsException(e); 1659 } 1660 } 1661 1662 /** 1663 * Gets the index to use for queries.<p> 1664 * 1665 * @return the index to use for queries 1666 */ 1667 private CmsSolrIndex getIndex() { 1668 1669 String indexName = m_indexName; 1670 if (indexName == null) { 1671 return null; 1672 } 1673 return OpenCms.getSearchManager().getIndexSolr(indexName); 1674 } 1675 1676 /** 1677 * Gets the relation object helper.<p> 1678 * 1679 * @return the relation object helper 1680 */ 1681 private CmsCmisRelationHelper getRelationHelper() { 1682 1683 return m_relationHelper; 1684 } 1685 1686 /** 1687 * Gets the resource object helper.<p> 1688 * 1689 * @return the resource object helper 1690 */ 1691 private CmsCmisResourceHelper getResourceHelper() { 1692 1693 return m_resourceHelper; 1694 } 1695 1696}