All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opencms.cmis.CmsCmisResourceHelper Maven / Gradle / Ivy

Go to download

OpenCms is an enterprise-ready, easy to use website content management system based on Java and XML technology. Offering a complete set of features, OpenCms helps content managers worldwide to create and maintain beautiful websites fast and efficiently.

There is a newer version: 17.0
Show newest version
/*
 * This library is part of OpenCms -
 * the Open Source Content Management System
 *
 * Copyright (C) Alkacon Software (http://www.alkacon.com)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * For further information about Alkacon Software, please see the
 * company website: http://www.alkacon.com
 *
 * For further information about OpenCms, please see the
 * project website: http://www.opencms.org
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package org.opencms.cmis;

import static org.opencms.cmis.CmsCmisUtil.addAction;
import static org.opencms.cmis.CmsCmisUtil.addPropertyBoolean;
import static org.opencms.cmis.CmsCmisUtil.addPropertyDateTime;
import static org.opencms.cmis.CmsCmisUtil.addPropertyId;
import static org.opencms.cmis.CmsCmisUtil.addPropertyIdList;
import static org.opencms.cmis.CmsCmisUtil.addPropertyInteger;
import static org.opencms.cmis.CmsCmisUtil.addPropertyString;
import static org.opencms.cmis.CmsCmisUtil.ensureLock;
import static org.opencms.cmis.CmsCmisUtil.getAcePrincipalName;
import static org.opencms.cmis.CmsCmisUtil.getCmisPermissions;
import static org.opencms.cmis.CmsCmisUtil.getNativePermissions;
import static org.opencms.cmis.CmsCmisUtil.handleCmsException;
import static org.opencms.cmis.CmsCmisUtil.hasChildren;
import static org.opencms.cmis.CmsCmisUtil.millisToCalendar;
import static org.opencms.cmis.CmsCmisUtil.splitFilter;

import org.opencms.file.CmsObject;
import org.opencms.file.CmsProperty;
import org.opencms.file.CmsResource;
import org.opencms.file.CmsResourceFilter;
import org.opencms.file.CmsUser;
import org.opencms.file.types.I_CmsResourceType;
import org.opencms.loader.CmsResourceManager;
import org.opencms.lock.CmsLock;
import org.opencms.main.CmsException;
import org.opencms.main.OpenCms;
import org.opencms.relations.CmsRelation;
import org.opencms.relations.CmsRelationFilter;
import org.opencms.security.CmsAccessControlEntry;
import org.opencms.security.CmsPermissionSet;
import org.opencms.util.CmsUUID;

import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.data.Ace;
import org.apache.chemistry.opencmis.commons.data.Acl;
import org.apache.chemistry.opencmis.commons.data.AllowableActions;
import org.apache.chemistry.opencmis.commons.data.ObjectData;
import org.apache.chemistry.opencmis.commons.data.Properties;
import org.apache.chemistry.opencmis.commons.data.RenditionData;
import org.apache.chemistry.opencmis.commons.enums.Action;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
import org.apache.chemistry.opencmis.commons.enums.RelationshipDirection;
import org.apache.chemistry.opencmis.commons.exceptions.CmisBaseException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisStorageException;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.AccessControlEntryImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.AccessControlListImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.AccessControlPrincipalDataImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.AllowableActionsImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectDataImpl;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertiesImpl;
import org.apache.chemistry.opencmis.commons.impl.server.ObjectInfoImpl;
import org.apache.chemistry.opencmis.commons.impl.server.RenditionInfoImpl;
import org.apache.chemistry.opencmis.commons.server.RenditionInfo;

/**
 * Helper class for CRUD operations on resources.

*/ public class CmsCmisResourceHelper implements I_CmsCmisObjectHelper { /** The underlying repository. */ private CmsCmisRepository m_repository; /** * Creates a new instance.

* * @param repository the underlying repository */ public CmsCmisResourceHelper(CmsCmisRepository repository) { m_repository = repository; } /** * Deletes a CMIS object.

* * @param context the call context * @param objectId the id of the object to delete * @param allVersions flag to delete all version */ public synchronized void deleteObject(CmsCmisCallContext context, String objectId, boolean allVersions) { try { CmsObject cms = m_repository.getCmsObject(context); CmsUUID structureId = new CmsUUID(objectId); CmsResource resource = cms.readResource(structureId); if (resource.isFolder()) { boolean isLeaf = !hasChildren(cms, resource); if (!isLeaf) { throw new CmisConstraintException("Only leaf resources can be deleted."); } } ensureLock(cms, resource); cms.deleteResource(resource.getRootPath(), CmsResource.DELETE_PRESERVE_SIBLINGS); } catch (CmsException e) { handleCmsException(e); } } /** * Gets the ACL for an object.

* * @param context the call context * @param objectId the object id * @param onlyBasicPermissions flag to only get basic permissions * * @return the ACL for the object */ public synchronized Acl getAcl(CmsCmisCallContext context, String objectId, boolean onlyBasicPermissions) { try { CmsObject cms = m_repository.getCmsObject(context); CmsUUID structureId = new CmsUUID(objectId); CmsResource resource = cms.readResource(structureId); return collectAcl(cms, resource, onlyBasicPermissions); } catch (CmsException e) { handleCmsException(e); return null; } } /** * Gets the allowable actions for an object.

* * @param context the call context * @param objectId the object id * @return the allowable actions */ public synchronized AllowableActions getAllowableActions(CmsCmisCallContext context, String objectId) { try { CmsObject cms = m_repository.getCmsObject(context); CmsUUID structureId = new CmsUUID(objectId); CmsResource file = cms.readResource(structureId); return collectAllowableActions(cms, file); } catch (CmsException e) { handleCmsException(e); return null; } } /** * Gets the data for a CMIS object.

* * @param context the CMIS call context * @param objectId the id of the object * @param filter the property filter * @param includeAllowableActions flag to include allowable actions * @param includeRelationships flag to include relationships * @param renditionFilter the rendition filter string * @param includePolicyIds flag to include policy ids * @param includeAcl flag to include ACLs * * @return the CMIS object data */ public synchronized ObjectData getObject( CmsCmisCallContext context, String objectId, String filter, boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter, boolean includePolicyIds, boolean includeAcl) { try { // if (renditionFilter.equals("cmis:none") && context.isObjectInfoRequired()) { // renditionFilter = "*"; // } // check id if (objectId == null) { throw new CmisInvalidArgumentException("Object Id must be set."); } CmsObject cms = m_repository.getCmsObject(context); // get the file or folder CmsResource file = cms.readResource(new CmsUUID(objectId)); // split filter Set filterCollection = splitFilter(filter); // gather properties return collectObjectData( context, cms, file, filterCollection, renditionFilter, includeAllowableActions, includeAcl, includeRelationships); } catch (CmsException e) { handleCmsException(e); return null; } } /** * Compiles the ACL for a file or folder. * @param cms the CMS context * @param resource the resource for which to collect the ACLs * @param onlyBasic flag to only include basic ACEs * * @return the ACL for the resource * @throws CmsException if something goes wrong */ protected Acl collectAcl(CmsObject cms, CmsResource resource, boolean onlyBasic) throws CmsException { AccessControlListImpl cmisAcl = new AccessControlListImpl(); List cmisAces = new ArrayList(); List aces = cms.getAccessControlEntries(resource.getRootPath(), true); for (CmsAccessControlEntry ace : aces) { boolean isDirect = ace.getResource().equals(resource.getResourceId()); CmsUUID principalId = ace.getPrincipal(); String principalName = getAcePrincipalName(cms, principalId); AccessControlEntryImpl cmisAce = new AccessControlEntryImpl(); AccessControlPrincipalDataImpl cmisPrincipal = new AccessControlPrincipalDataImpl(); cmisPrincipal.setId(principalName); cmisAce.setPrincipal(cmisPrincipal); cmisAce.setPermissions(onlyBasic ? getCmisPermissions(ace) : getNativePermissions(ace)); cmisAce.setDirect(isDirect); cmisAces.add(cmisAce); } cmisAcl.setAces(cmisAces); cmisAcl.setExact(Boolean.FALSE); return cmisAcl; } /** * Compiles the allowable actions for a file or folder. * * @param cms the current CMS context * @param file the resource for which we want the allowable actions * * @return the allowable actions for the given resource */ protected AllowableActions collectAllowableActions(CmsObject cms, CmsResource file) { try { if (file == null) { throw new IllegalArgumentException("File must not be null!"); } CmsLock lock = cms.getLock(file); CmsUser user = cms.getRequestContext().getCurrentUser(); boolean canWrite = !cms.getRequestContext().getCurrentProject().isOnlineProject() && (lock.isOwnedBy(user) || lock.isLockableBy(user)) && cms.hasPermissions(file, CmsPermissionSet.ACCESS_WRITE, false, CmsResourceFilter.DEFAULT); boolean isReadOnly = !canWrite; boolean isFolder = file.isFolder(); boolean isRoot = file.getRootPath().length() <= 1; Set aas = new LinkedHashSet(); addAction(aas, Action.CAN_GET_OBJECT_PARENTS, !isRoot); addAction(aas, Action.CAN_GET_PROPERTIES, true); addAction(aas, Action.CAN_UPDATE_PROPERTIES, !isReadOnly); addAction(aas, Action.CAN_MOVE_OBJECT, !isReadOnly && !isRoot); addAction(aas, Action.CAN_DELETE_OBJECT, !isReadOnly && !isRoot); if (isFolder) { addAction(aas, Action.CAN_GET_DESCENDANTS, true); addAction(aas, Action.CAN_GET_CHILDREN, true); addAction(aas, Action.CAN_GET_FOLDER_PARENT, !isRoot); addAction(aas, Action.CAN_GET_FOLDER_TREE, true); addAction(aas, Action.CAN_CREATE_DOCUMENT, !isReadOnly); addAction(aas, Action.CAN_CREATE_FOLDER, !isReadOnly); addAction(aas, Action.CAN_DELETE_TREE, !isReadOnly); } else { addAction(aas, Action.CAN_GET_CONTENT_STREAM, true); addAction(aas, Action.CAN_SET_CONTENT_STREAM, !isReadOnly); addAction(aas, Action.CAN_GET_ALL_VERSIONS, true); } AllowableActionsImpl result = new AllowableActionsImpl(); result.setAllowableActions(aas); return result; } catch (CmsException e) { handleCmsException(e); return null; } } /** * Fills in an ObjectData record.

* * @param context the call context * @param cms the CMS context * @param resource the resource for which we want the ObjectData * @param filter the property filter * @param renditionFilter the rendition filter string * @param includeAllowableActions true if the allowable actions should be included * @param includeAcl true if the ACL entries should be included * @param includeRelationships true if relationships should be included * * @return the object data * @throws CmsException if something goes wrong */ protected ObjectData collectObjectData( CmsCmisCallContext context, CmsObject cms, CmsResource resource, Set filter, String renditionFilter, boolean includeAllowableActions, boolean includeAcl, IncludeRelationships includeRelationships) throws CmsException { ObjectDataImpl result = new ObjectDataImpl(); ObjectInfoImpl objectInfo = new ObjectInfoImpl(); result.setProperties(collectProperties(cms, resource, filter, objectInfo)); if (includeAllowableActions) { result.setAllowableActions(collectAllowableActions(cms, resource)); } if (includeAcl) { result.setAcl(collectAcl(cms, resource, true)); result.setIsExactAcl(Boolean.FALSE); } if ((includeRelationships != null) && (includeRelationships != IncludeRelationships.NONE)) { RelationshipDirection direction; if (includeRelationships == IncludeRelationships.SOURCE) { direction = RelationshipDirection.SOURCE; } else if (includeRelationships == IncludeRelationships.TARGET) { direction = RelationshipDirection.TARGET; } else { direction = RelationshipDirection.EITHER; } List relationData = m_repository.getRelationshipObjectData( context, cms, resource, direction, CmsCmisUtil.splitFilter("*"), false); result.setRelationships(relationData); } result.setRenditions(collectRenditions(cms, resource, renditionFilter, objectInfo)); if (context.isObjectInfoRequired()) { objectInfo.setObject(result); context.getObjectInfoHandler().addObjectInfo(objectInfo); } return result; } /** * Gathers all base properties of a file or folder. * * @param cms the current CMS context * @param resource the file for which we want the properties * @param orgfilter the property filter * @param objectInfo the object info handler * * @return the properties for the given resource */ protected Properties collectProperties( CmsObject cms, CmsResource resource, Set orgfilter, ObjectInfoImpl objectInfo) { CmsCmisTypeManager tm = m_repository.getTypeManager(); if (resource == null) { throw new IllegalArgumentException("Resource may not be null."); } // copy filter Set filter = (orgfilter == null ? null : new LinkedHashSet(orgfilter)); // find base type String typeId = null; List relationSourceIds = new ArrayList(); List relationTargetIds = new ArrayList(); try { List relations = cms.getRelationsForResource(resource, CmsRelationFilter.ALL); for (CmsRelation relation : relations) { if (resource.getStructureId().equals(relation.getSourceId())) { relationTargetIds.add(relation.getTargetId().toString()); } if (resource.getStructureId().equals(relation.getTargetId())) { relationSourceIds.add(relation.getSourceId().toString()); } } } catch (CmsException e) { throw new CmisStorageException(e.getLocalizedMessage(), e); } if (resource.isFolder()) { typeId = CmsCmisTypeManager.FOLDER_TYPE_ID; objectInfo.setBaseType(BaseTypeId.CMIS_FOLDER); objectInfo.setTypeId(typeId); objectInfo.setContentType(null); objectInfo.setFileName(null); objectInfo.setHasAcl(true); objectInfo.setHasContent(false); objectInfo.setVersionSeriesId(null); objectInfo.setIsCurrentVersion(true); objectInfo.setRelationshipSourceIds(relationSourceIds); objectInfo.setRelationshipTargetIds(relationTargetIds); objectInfo.setSupportsDescendants(true); objectInfo.setSupportsFolderTree(true); objectInfo.setSupportsPolicies(false); objectInfo.setSupportsRelationships(true); objectInfo.setWorkingCopyId(null); objectInfo.setWorkingCopyOriginalId(null); } else { typeId = CmsCmisTypeManager.DOCUMENT_TYPE_ID; objectInfo.setBaseType(BaseTypeId.CMIS_DOCUMENT); objectInfo.setTypeId(typeId); objectInfo.setHasAcl(true); objectInfo.setHasContent(true); objectInfo.setHasParent(true); objectInfo.setVersionSeriesId(null); objectInfo.setIsCurrentVersion(true); objectInfo.setRelationshipSourceIds(relationSourceIds); objectInfo.setRelationshipTargetIds(relationTargetIds); objectInfo.setSupportsDescendants(false); objectInfo.setSupportsFolderTree(false); objectInfo.setSupportsPolicies(false); objectInfo.setSupportsRelationships(true); objectInfo.setWorkingCopyId(null); objectInfo.setWorkingCopyOriginalId(null); } try { PropertiesImpl result = new PropertiesImpl(); String id = resource.getStructureId().toString(); addPropertyId(tm, result, typeId, filter, PropertyIds.OBJECT_ID, id); objectInfo.setId(id); String name = resource.getName(); if ("".equals(name)) { name = "/"; } addPropertyString(tm, result, typeId, filter, PropertyIds.NAME, name); objectInfo.setName(name); // created and modified by CmsUUID creatorId = resource.getUserCreated(); CmsUUID modifierId = resource.getUserLastModified(); String creatorName = creatorId.toString(); String modifierName = modifierId.toString(); try { CmsUser user = cms.readUser(creatorId); creatorName = user.getName(); } catch (CmsException e) { // ignore, use id as name } try { CmsUser user = cms.readUser(modifierId); modifierName = user.getName(); } catch (CmsException e) { // ignore, use id as name } addPropertyString(tm, result, typeId, filter, PropertyIds.CREATED_BY, creatorName); addPropertyString(tm, result, typeId, filter, PropertyIds.LAST_MODIFIED_BY, modifierName); objectInfo.setCreatedBy(creatorName); // creation and modification date GregorianCalendar lastModified = millisToCalendar(resource.getDateLastModified()); GregorianCalendar created = millisToCalendar(resource.getDateCreated()); addPropertyDateTime(tm, result, typeId, filter, PropertyIds.CREATION_DATE, created); addPropertyDateTime(tm, result, typeId, filter, PropertyIds.LAST_MODIFICATION_DATE, lastModified); objectInfo.setCreationDate(created); objectInfo.setLastModificationDate(lastModified); // change token - always null addPropertyString(tm, result, typeId, filter, PropertyIds.CHANGE_TOKEN, null); // directory or file if (resource.isFolder()) { // base type and type name addPropertyId(tm, result, typeId, filter, PropertyIds.BASE_TYPE_ID, BaseTypeId.CMIS_FOLDER.value()); addPropertyId( tm, result, typeId, filter, PropertyIds.OBJECT_TYPE_ID, CmsCmisTypeManager.FOLDER_TYPE_ID); String path = resource.getRootPath(); addPropertyString(tm, result, typeId, filter, PropertyIds.PATH, (path.length() == 0 ? "/" : path)); // folder properties if (resource.getRootPath().length() > 1) { CmsResource parent = cms.readParentFolder(resource.getStructureId()); addPropertyId(tm, result, typeId, filter, PropertyIds.PARENT_ID, ( parent.getStructureId().toString())); objectInfo.setHasParent(true); } else { addPropertyId(tm, result, typeId, filter, PropertyIds.PARENT_ID, null); objectInfo.setHasParent(false); } addPropertyIdList(tm, result, typeId, filter, PropertyIds.ALLOWED_CHILD_OBJECT_TYPE_IDS, null); } else { // base type and type name addPropertyId(tm, result, typeId, filter, PropertyIds.BASE_TYPE_ID, BaseTypeId.CMIS_DOCUMENT.value()); addPropertyId( tm, result, typeId, filter, PropertyIds.OBJECT_TYPE_ID, CmsCmisTypeManager.DOCUMENT_TYPE_ID); // file properties addPropertyBoolean(tm, result, typeId, filter, PropertyIds.IS_IMMUTABLE, false); addPropertyBoolean(tm, result, typeId, filter, PropertyIds.IS_LATEST_VERSION, true); addPropertyBoolean(tm, result, typeId, filter, PropertyIds.IS_MAJOR_VERSION, true); addPropertyBoolean(tm, result, typeId, filter, PropertyIds.IS_LATEST_MAJOR_VERSION, true); addPropertyString(tm, result, typeId, filter, PropertyIds.VERSION_LABEL, resource.getName()); addPropertyId( tm, result, typeId, filter, PropertyIds.VERSION_SERIES_ID, resource.getStructureId().toString()); addPropertyBoolean(tm, result, typeId, filter, PropertyIds.IS_VERSION_SERIES_CHECKED_OUT, false); addPropertyString(tm, result, typeId, filter, PropertyIds.VERSION_SERIES_CHECKED_OUT_BY, null); addPropertyString(tm, result, typeId, filter, PropertyIds.VERSION_SERIES_CHECKED_OUT_ID, null); addPropertyString(tm, result, typeId, filter, PropertyIds.CHECKIN_COMMENT, ""); addPropertyInteger(tm, result, typeId, filter, PropertyIds.CONTENT_STREAM_LENGTH, resource.getLength()); addPropertyString( tm, result, typeId, filter, PropertyIds.CONTENT_STREAM_MIME_TYPE, OpenCms.getResourceManager().getMimeType( resource.getRootPath(), null, CmsResourceManager.MIMETYPE_TEXT)); addPropertyString(tm, result, typeId, filter, PropertyIds.CONTENT_STREAM_FILE_NAME, resource.getName()); objectInfo.setHasContent(true); objectInfo.setContentType( OpenCms.getResourceManager().getMimeType( resource.getRootPath(), null, CmsResourceManager.MIMETYPE_TEXT)); objectInfo.setFileName(resource.getName()); addPropertyId(tm, result, typeId, filter, PropertyIds.CONTENT_STREAM_ID, null); } // normal OpenCms properties List props = cms.readPropertyObjects(resource, false); Set propertiesToAdd = new LinkedHashSet( m_repository.getTypeManager().getCmsPropertyNames()); for (CmsProperty prop : props) { addPropertyString( tm, result, typeId, filter, CmsCmisTypeManager.PROPERTY_PREFIX + prop.getName(), prop.getValue()); propertiesToAdd.remove(prop.getName()); } for (String propName : propertiesToAdd) { addPropertyString(tm, result, typeId, filter, CmsCmisTypeManager.PROPERTY_PREFIX + propName, null); } // inherited OpenCms properties List inheritedProps = cms.readPropertyObjects(resource, true); Set inheritedPropertiesToAdd = new LinkedHashSet( m_repository.getTypeManager().getCmsPropertyNames()); for (CmsProperty prop : inheritedProps) { addPropertyString( tm, result, typeId, filter, CmsCmisTypeManager.INHERITED_PREFIX + prop.getName(), prop.getValue()); inheritedPropertiesToAdd.remove(prop.getName()); } for (String propName : inheritedPropertiesToAdd) { addPropertyString(tm, result, typeId, filter, CmsCmisTypeManager.INHERITED_PREFIX + propName, null); } I_CmsResourceType resType = OpenCms.getResourceManager().getResourceType(resource); addPropertyString( tm, result, typeId, filter, CmsCmisTypeManager.PROPERTY_RESOURCE_TYPE, resType.getTypeName()); CmsCmisUtil.addDynamicProperties(cms, m_repository.getTypeManager(), result, typeId, resource, filter); return result; } catch (Exception e) { if (e instanceof CmisBaseException) { throw (CmisBaseException)e; } throw new CmisRuntimeException(e.getMessage(), e); } } /** * Collects renditions for a resource.

* * @param cms the CMS context * @param resource the resource for which we want the renditions * @param renditionFilterString the filter string for the renditions * @param objectInfo the object info in which the renditions should be saved * * @return the rendition data for the given resource */ protected List collectRenditions( CmsObject cms, CmsResource resource, String renditionFilterString, ObjectInfoImpl objectInfo) { List providers = m_repository.getRenditionProviders( new CmsCmisRenditionFilter(renditionFilterString)); List result = new ArrayList(); List renditionInfos = new ArrayList(); for (I_CmsCmisRenditionProvider provider : providers) { RenditionData renditionData = provider.getRendition(cms, resource); if (renditionData != null) { RenditionInfoImpl renditionInfo = new RenditionInfoImpl(); renditionInfo.setContentType(renditionData.getMimeType()); renditionInfo.setKind(renditionData.getKind()); renditionInfo.setId(renditionData.getStreamId()); result.add(renditionData); renditionInfos.add(renditionInfo); } } if (objectInfo != null) { objectInfo.setRenditionInfos(renditionInfos); } return result; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy