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.CmsResourceTranslator; 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.repository.I_CmsRepository#getTranslation() 1115 */ 1116 public CmsResourceTranslator getTranslation() { 1117 1118 // TODO Auto-generated method stub 1119 return null; 1120 } 1121 1122 /** 1123 * @see org.opencms.cmis.I_CmsCmisRepository#getTypeChildren(org.opencms.cmis.CmsCmisCallContext, java.lang.String, boolean, java.math.BigInteger, java.math.BigInteger) 1124 */ 1125 public synchronized TypeDefinitionList getTypeChildren( 1126 CmsCmisCallContext context, 1127 String typeId, 1128 boolean includePropertyDefinitions, 1129 BigInteger maxItems, 1130 BigInteger skipCount) { 1131 1132 return m_typeManager.getTypeChildren(typeId, includePropertyDefinitions, maxItems, skipCount); 1133 } 1134 1135 /** 1136 * @see org.opencms.cmis.I_CmsCmisRepository#getTypeDefinition(org.opencms.cmis.CmsCmisCallContext, java.lang.String) 1137 */ 1138 public synchronized TypeDefinition getTypeDefinition(CmsCmisCallContext context, String typeId) { 1139 1140 return m_typeManager.getTypeDefinition(typeId); 1141 } 1142 1143 /** 1144 * @see org.opencms.cmis.I_CmsCmisRepository#getTypeDescendants(org.opencms.cmis.CmsCmisCallContext, java.lang.String, java.math.BigInteger, boolean) 1145 */ 1146 public synchronized List<TypeDefinitionContainer> getTypeDescendants( 1147 CmsCmisCallContext context, 1148 String typeId, 1149 BigInteger depth, 1150 boolean includePropertyDefinitions) { 1151 1152 return m_typeManager.getTypeDescendants(typeId, depth, includePropertyDefinitions); 1153 } 1154 1155 /** 1156 * @see org.opencms.cmis.I_CmsCmisRepository#initConfiguration() 1157 */ 1158 public void initConfiguration() throws CmsConfigurationException { 1159 1160 if (m_filter != null) { 1161 m_filter.initConfiguration(); 1162 } 1163 m_description = m_parameterConfiguration.getString(PARAM_DESCRIPTION, null); 1164 List<String> renditionProviderClasses = m_parameterConfiguration.getList( 1165 PARAM_RENDITION, 1166 Collections.<String> emptyList()); 1167 for (String className : renditionProviderClasses) { 1168 try { 1169 I_CmsCmisRenditionProvider provider = (I_CmsCmisRenditionProvider)(Class.forName( 1170 className).newInstance()); 1171 String id = provider.getId(); 1172 m_renditionProviders.put(id, provider); 1173 } catch (Throwable e) { 1174 LOG.error(e.getLocalizedMessage(), e); 1175 } 1176 } 1177 List<String> propertyProviderClasses = m_parameterConfiguration.getList( 1178 PARAM_PROPERTY, 1179 Collections.<String> emptyList()); 1180 for (String className : propertyProviderClasses) { 1181 try { 1182 I_CmsPropertyProvider provider = (I_CmsPropertyProvider)(Class.forName(className).newInstance()); 1183 m_propertyProviders.add(provider); 1184 } catch (Throwable e) { 1185 LOG.error(e.getLocalizedMessage(), e); 1186 } 1187 } 1188 m_indexName = m_parameterConfiguration.getString(PARAM_INDEX, null); 1189 } 1190 1191 /** 1192 * @see org.opencms.cmis.I_CmsCmisRepository#initializeCms(org.opencms.file.CmsObject) 1193 */ 1194 public void initializeCms(CmsObject cms) throws CmsException { 1195 1196 m_adminCms = cms; 1197 m_typeManager = new CmsCmisTypeManager(cms, m_propertyProviders); 1198 String projectName = m_parameterConfiguration.getString(PARAM_PROJECT, CmsProject.ONLINE_PROJECT_NAME); 1199 CmsResource root = m_adminCms.readResource("/"); 1200 CmsObject offlineCms = OpenCms.initCmsObject(m_adminCms); 1201 CmsProject project = m_adminCms.readProject(projectName); 1202 m_project = project; 1203 offlineCms.getRequestContext().setCurrentProject(project); 1204 m_adminCms = offlineCms; 1205 m_root = root; 1206 m_isReadOnly = project.isOnlineProject(); 1207 } 1208 1209 /** 1210 * @see org.opencms.repository.I_CmsRepository#isTranslationEnabled() 1211 */ 1212 public boolean isTranslationEnabled() { 1213 1214 // TODO Auto-generated method stub 1215 return false; 1216 } 1217 1218 /** 1219 * @see org.opencms.cmis.I_CmsCmisRepository#moveObject(org.opencms.cmis.CmsCmisCallContext, org.apache.chemistry.opencmis.commons.spi.Holder, java.lang.String, java.lang.String) 1220 */ 1221 public synchronized void moveObject( 1222 CmsCmisCallContext context, 1223 Holder<String> objectId, 1224 String targetFolderId, 1225 String sourceFolderId) { 1226 1227 checkWriteAccess(); 1228 1229 try { 1230 CmsObject cms = getCmsObject(context); 1231 CmsUUID structureId = new CmsUUID(objectId.getValue()); 1232 CmsUUID targetStructureId = new CmsUUID(targetFolderId); 1233 CmsResource targetFolder = cms.readResource(targetStructureId); 1234 CmsResource resourceToMove = cms.readResource(structureId); 1235 String name = CmsResource.getName(resourceToMove.getRootPath()); 1236 String newPath = CmsStringUtil.joinPaths(targetFolder.getRootPath(), name); 1237 boolean wasLocked = ensureLock(cms, resourceToMove); 1238 try { 1239 cms.moveResource(resourceToMove.getRootPath(), newPath); 1240 } finally { 1241 if (wasLocked) { 1242 CmsResource movedResource = cms.readResource(resourceToMove.getStructureId()); 1243 cms.unlockResource(movedResource); 1244 } 1245 } 1246 } catch (CmsException e) { 1247 handleCmsException(e); 1248 } 1249 } 1250 1251 /** 1252 * @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) 1253 */ 1254 @Override 1255 public synchronized ObjectList query( 1256 CmsCmisCallContext context, 1257 String statement, 1258 boolean searchAllVersions, 1259 boolean includeAllowableActions, 1260 IncludeRelationships includeRelationships, 1261 String renditionFilter, 1262 BigInteger maxItems, 1263 BigInteger skipCount) { 1264 1265 try { 1266 CmsObject cms = getCmsObject(context); 1267 CmsSolrIndex index = getIndex(); 1268 CmsCmisResourceHelper helper = getResourceHelper(); 1269 1270 // split filter 1271 Set<String> filterCollection = null; 1272 // skip and max 1273 int skip = (skipCount == null ? 0 : skipCount.intValue()); 1274 if (skip < 0) { 1275 skip = 0; 1276 } 1277 1278 int max = (maxItems == null ? Integer.MAX_VALUE : maxItems.intValue()); 1279 if (max < 0) { 1280 max = Integer.MAX_VALUE; 1281 } 1282 CmsSolrResultList results = solrSearch(cms, index, statement, skip, max); 1283 ObjectListImpl resultObjectList = new ObjectListImpl(); 1284 List<ObjectData> objectDataList = new ArrayList<ObjectData>(); 1285 resultObjectList.setObjects(objectDataList); 1286 for (CmsResource resource : results) { 1287 // build and add child object 1288 objectDataList.add( 1289 helper.collectObjectData( 1290 context, 1291 cms, 1292 resource, 1293 filterCollection, 1294 renditionFilter, 1295 includeAllowableActions, 1296 false, 1297 includeRelationships)); 1298 } 1299 resultObjectList.setHasMoreItems(Boolean.valueOf(!results.isEmpty())); 1300 resultObjectList.setNumItems(BigInteger.valueOf(results.getVisibleHitCount())); 1301 return resultObjectList; 1302 } catch (CmsException e) { 1303 handleCmsException(e); 1304 return null; 1305 } 1306 1307 } 1308 1309 /** 1310 * @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) 1311 */ 1312 public synchronized void setContentStream( 1313 CmsCmisCallContext context, 1314 Holder<String> objectId, 1315 boolean overwriteFlag, 1316 Holder<String> changeToken, 1317 ContentStream contentStream) { 1318 1319 checkWriteAccess(); 1320 1321 try { 1322 CmsObject cms = getCmsObject(context); 1323 CmsUUID structureId = new CmsUUID(objectId.getValue()); 1324 if (!overwriteFlag) { 1325 throw new CmisContentAlreadyExistsException(); 1326 } 1327 CmsResource resource = cms.readResource(structureId); 1328 if (resource.isFolder()) { 1329 throw new CmisStreamNotSupportedException("Folders may not have content streams."); 1330 } 1331 CmsFile file = cms.readFile(resource); 1332 InputStream contentInput = contentStream.getStream(); 1333 byte[] newContent = CmsFileUtil.readFully(contentInput); 1334 file.setContents(newContent); 1335 boolean wasLocked = ensureLock(cms, resource); 1336 CmsFile newFile = cms.writeFile(file); 1337 if (wasLocked) { 1338 cms.unlockResource(newFile); 1339 } 1340 } catch (CmsException e) { 1341 handleCmsException(e); 1342 } catch (IOException e) { 1343 throw new CmisRuntimeException(e.getLocalizedMessage(), e); 1344 } 1345 } 1346 1347 /** 1348 * @see org.opencms.cmis.I_CmsCmisRepository#setFilter(org.opencms.repository.CmsRepositoryFilter) 1349 */ 1350 public void setFilter(CmsRepositoryFilter filter) { 1351 1352 m_filter = filter; 1353 LOG.warn("Filters not supported by CMIS repositories, ignoring configuration..."); 1354 } 1355 1356 /** 1357 * @see org.opencms.cmis.I_CmsCmisRepository#setName(java.lang.String) 1358 */ 1359 public void setName(String name) { 1360 1361 m_id = name; 1362 } 1363 1364 /** 1365 * @see org.opencms.repository.I_CmsRepository#setTranslation(org.opencms.util.CmsResourceTranslator, boolean) 1366 */ 1367 public void setTranslation(CmsResourceTranslator translator, boolean enabled) { 1368 1369 throw new UnsupportedOperationException("File translations not supported by CMIS repository."); 1370 } 1371 1372 /** 1373 * @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) 1374 */ 1375 public synchronized void updateProperties( 1376 CmsCmisCallContext context, 1377 Holder<String> objectId, 1378 Holder<String> changeToken, 1379 Properties properties) { 1380 1381 checkWriteAccess(); 1382 1383 try { 1384 1385 CmsObject cms = getCmsObject(context); 1386 CmsUUID structureId = new CmsUUID(objectId.getValue()); 1387 CmsResource resource = cms.readResource(structureId); 1388 Map<String, PropertyData<?>> propertyMap = properties.getProperties(); 1389 List<CmsProperty> cmsProperties = getOpenCmsProperties(propertyMap); 1390 boolean wasLocked = ensureLock(cms, resource); 1391 try { 1392 cms.writePropertyObjects(resource, cmsProperties); 1393 @SuppressWarnings("unchecked") 1394 PropertyData<String> nameProperty = (PropertyData<String>)propertyMap.get(PropertyIds.NAME); 1395 if (nameProperty != null) { 1396 String newName = nameProperty.getFirstValue(); 1397 checkResourceName(newName); 1398 String parentFolder = CmsResource.getParentFolder(resource.getRootPath()); 1399 String newPath = CmsStringUtil.joinPaths(parentFolder, newName); 1400 cms.moveResource(resource.getRootPath(), newPath); 1401 resource = cms.readResource(resource.getStructureId()); 1402 } 1403 1404 for (String key : properties.getProperties().keySet()) { 1405 if (key.startsWith(CmsCmisTypeManager.PROPERTY_PREFIX_DYNAMIC)) { 1406 I_CmsPropertyProvider provider = getTypeManager().getPropertyProvider(key); 1407 try { 1408 String value = (String)(properties.getProperties().get(key).getFirstValue()); 1409 provider.setPropertyValue(cms, resource, value); 1410 } catch (CmsException e) { 1411 LOG.error(e.getLocalizedMessage(), e); 1412 } 1413 } 1414 } 1415 } finally { 1416 if (wasLocked) { 1417 cms.unlockResource(resource); 1418 } 1419 } 1420 } catch (CmsException e) { 1421 handleCmsException(e); 1422 } 1423 } 1424 1425 /** 1426 * Checks whether we have write access to this repository and throws an exception otherwise.<p> 1427 */ 1428 protected void checkWriteAccess() { 1429 1430 if (m_isReadOnly) { 1431 throw new CmisNotSupportedException("Readonly repository '" + m_id + "' does not allow write operations."); 1432 } 1433 } 1434 1435 /** 1436 * Initializes a CMS context for the authentication data contained in a call context.<p> 1437 * 1438 * @param context the call context 1439 * @return the initialized CMS context 1440 */ 1441 protected CmsObject getCmsObject(CmsCmisCallContext context) { 1442 1443 try { 1444 if (context.getUsername() == null) { 1445 // user name can be null 1446 CmsObject cms = OpenCms.initCmsObject(OpenCms.getDefaultUsers().getUserGuest()); 1447 cms.getRequestContext().setCurrentProject(m_adminCms.getRequestContext().getCurrentProject()); 1448 return cms; 1449 } else { 1450 CmsObject cms = OpenCms.initCmsObject(m_adminCms); 1451 CmsProject projectBeforeLogin = cms.getRequestContext().getCurrentProject(); 1452 cms.loginUser(context.getUsername(), context.getPassword()); 1453 cms.getRequestContext().setCurrentProject(projectBeforeLogin); 1454 return cms; 1455 } 1456 } catch (CmsException e) { 1457 throw new CmisPermissionDeniedException(e.getLocalizedMessage(), e); 1458 1459 } 1460 } 1461 1462 /** 1463 * Gets the relationship data for a given resource.<p> 1464 * 1465 * @param context the call context 1466 * @param cms the CMS context 1467 * @param resource the resource 1468 * @param relationshipDirection the relationship direction 1469 * @param filterSet the property filter 1470 * @param includeAllowableActions true if allowable actions should be included 1471 * @return the list of relationship data 1472 * 1473 * @throws CmsException if something goes wrong 1474 */ 1475 protected List<ObjectData> getRelationshipObjectData( 1476 CmsCmisCallContext context, 1477 CmsObject cms, 1478 CmsResource resource, 1479 RelationshipDirection relationshipDirection, 1480 Set<String> filterSet, 1481 boolean includeAllowableActions) 1482 throws CmsException { 1483 1484 List<ObjectData> resultObjects = new ArrayList<ObjectData>(); 1485 CmsRelationFilter relationFilter; 1486 if (relationshipDirection == RelationshipDirection.SOURCE) { 1487 relationFilter = CmsRelationFilter.TARGETS; 1488 } else if (relationshipDirection == RelationshipDirection.TARGET) { 1489 relationFilter = CmsRelationFilter.SOURCES; 1490 } else { 1491 relationFilter = CmsRelationFilter.ALL; 1492 } 1493 1494 List<CmsRelation> unfilteredRelations = cms.getRelationsForResource(resource.getRootPath(), relationFilter); 1495 List<CmsRelation> relations = new ArrayList<CmsRelation>(); 1496 for (CmsRelation relation : unfilteredRelations) { 1497 if (relation.getTargetId().isNullUUID() || relation.getSourceId().isNullUUID()) { 1498 continue; 1499 } 1500 relations.add(relation); 1501 } 1502 CmsCmisRelationHelper helper = getRelationHelper(); 1503 for (CmsRelation relation : relations) { 1504 ObjectData objData = helper.collectObjectData( 1505 context, 1506 cms, 1507 resource, 1508 relation, 1509 filterSet, 1510 includeAllowableActions, 1511 false); 1512 resultObjects.add(objData); 1513 } 1514 return resultObjects; 1515 } 1516 1517 /** 1518 * Gets the rendition providers matching the given filter.<p> 1519 * 1520 * @param filter the rendition filter 1521 * 1522 * @return the rendition providers matching the filter 1523 */ 1524 protected List<I_CmsCmisRenditionProvider> getRenditionProviders(CmsCmisRenditionFilter filter) { 1525 1526 List<I_CmsCmisRenditionProvider> result = new ArrayList<I_CmsCmisRenditionProvider>(); 1527 for (I_CmsCmisRenditionProvider provider : m_renditionProviders.values()) { 1528 String mimetype = provider.getMimeType(); 1529 String kind = provider.getKind(); 1530 if (filter.accept(kind, mimetype)) { 1531 result.add(provider); 1532 } 1533 } 1534 return result; 1535 } 1536 1537 /** 1538 * Extracts the resource type from a set of CMIS properties.<p> 1539 * 1540 * @param properties the CMIS properties 1541 * @param defaultValue the default value 1542 * 1543 * @return the resource type property, or the default value if the property was not found 1544 */ 1545 protected String getResourceTypeFromProperties(Map<String, PropertyData<?>> properties, String defaultValue) { 1546 1547 PropertyData<?> typeProp = properties.get(CmsCmisTypeManager.PROPERTY_RESOURCE_TYPE); 1548 String resTypeName = defaultValue; 1549 if (typeProp != null) { 1550 resTypeName = (String)typeProp.getFirstValue(); 1551 } 1552 return resTypeName; 1553 } 1554 1555 /** 1556 * Gets the type manager instance.<p> 1557 * 1558 * @return the type manager instance 1559 */ 1560 protected CmsCmisTypeManager getTypeManager() { 1561 1562 return m_typeManager; 1563 } 1564 1565 /** 1566 * Gets the correct helper object for a given object id to perform operations on the corresponding object.<p> 1567 * 1568 * @param objectId the object id 1569 * 1570 * @return the helper object to use for the given object id 1571 */ 1572 I_CmsCmisObjectHelper getHelper(String objectId) { 1573 1574 if (CmsUUID.isValidUUID(objectId)) { 1575 return getResourceHelper(); 1576 } else if (CmsCmisRelationHelper.RELATION_PATTERN.matcher(objectId).matches()) { 1577 return getRelationHelper(); 1578 } else { 1579 return null; 1580 } 1581 } 1582 1583 /** 1584 * Helper method for executing a query.<p> 1585 * 1586 * @param cms the CMS context to use 1587 * @param index the index to use for the query 1588 * @param query the query to perform 1589 * @param start the start offset 1590 * @param rows the number of results to return 1591 * 1592 * @return the list of search results 1593 * @throws CmsSearchException if something goes wrong 1594 */ 1595 CmsSolrResultList solrSearch(CmsObject cms, CmsSolrIndex index, String query, int start, int rows) 1596 throws CmsSearchException { 1597 1598 Map<String, String[]> params = new HashMap<>(); 1599 CmsSolrQuery q = new CmsSolrQuery(null, params); 1600 q.setText(query); 1601 q.setStart(Integer.valueOf(start)); 1602 q.setRows(Integer.valueOf(rows)); 1603 CmsSolrResultList resultPage = index.search(cms, q, true); 1604 return resultPage; 1605 } 1606 1607 /** 1608 * Helper method to collect the descendants of a given folder.<p> 1609 * 1610 * @param context the call context 1611 * @param cms the CMS context 1612 * @param folder the parent folder 1613 * @param list the list to which the descendants should be added 1614 * @param foldersOnly flag to exclude files from the result 1615 * @param depth the maximum depth 1616 * @param filter the property filter 1617 * @param includeAllowableActions flag to include allowable actions 1618 * @param includePathSegments flag to include path segments 1619 */ 1620 private void gatherDescendants( 1621 CmsCmisCallContext context, 1622 CmsObject cms, 1623 CmsResource folder, 1624 List<ObjectInFolderContainer> list, 1625 boolean foldersOnly, 1626 int depth, 1627 Set<String> filter, 1628 boolean includeAllowableActions, 1629 boolean includePathSegments) { 1630 1631 try { 1632 CmsCmisResourceHelper helper = getResourceHelper(); 1633 List<CmsResource> children = cms.getResourcesInFolder(cms.getSitePath(folder), CmsResourceFilter.DEFAULT); 1634 Collections.sort(children, new Comparator<CmsResource>() { 1635 1636 public int compare(CmsResource a, CmsResource b) { 1637 1638 return a.getName().compareTo(b.getName()); 1639 } 1640 }); 1641 // iterate through children 1642 for (CmsResource child : children) { 1643 1644 // folders only? 1645 if (foldersOnly && !child.isFolder()) { 1646 continue; 1647 } 1648 1649 // add to list 1650 ObjectInFolderDataImpl objectInFolder = new ObjectInFolderDataImpl(); 1651 objectInFolder.setObject( 1652 helper.collectObjectData( 1653 context, 1654 cms, 1655 child, 1656 filter, 1657 "cmis:none", 1658 includeAllowableActions, 1659 false, 1660 IncludeRelationships.NONE)); 1661 if (includePathSegments) { 1662 objectInFolder.setPathSegment(child.getName()); 1663 } 1664 1665 ObjectInFolderContainerImpl container = new ObjectInFolderContainerImpl(); 1666 container.setObject(objectInFolder); 1667 1668 list.add(container); 1669 1670 // move to next level 1671 if ((depth != 1) && child.isFolder()) { 1672 container.setChildren(new ArrayList<ObjectInFolderContainer>()); 1673 gatherDescendants( 1674 context, 1675 cms, 1676 child, 1677 container.getChildren(), 1678 foldersOnly, 1679 depth - 1, 1680 filter, 1681 includeAllowableActions, 1682 includePathSegments); 1683 } 1684 } 1685 } catch (CmsException e) { 1686 handleCmsException(e); 1687 } 1688 } 1689 1690 /** 1691 * Gets the index to use for queries.<p> 1692 * 1693 * @return the index to use for queries 1694 */ 1695 private CmsSolrIndex getIndex() { 1696 1697 String indexName = m_indexName; 1698 if (indexName == null) { 1699 return null; 1700 } 1701 return OpenCms.getSearchManager().getIndexSolr(indexName); 1702 } 1703 1704 /** 1705 * Gets the relation object helper.<p> 1706 * 1707 * @return the relation object helper 1708 */ 1709 private CmsCmisRelationHelper getRelationHelper() { 1710 1711 return m_relationHelper; 1712 } 1713 1714 /** 1715 * Gets the resource object helper.<p> 1716 * 1717 * @return the resource object helper 1718 */ 1719 private CmsCmisResourceHelper getResourceHelper() { 1720 1721 return m_resourceHelper; 1722 } 1723 1724}