/******************************************************************************* * Copyright (c) 2013 aegif. * * This file is part of NemakiWare. * * NemakiWare is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * NemakiWare 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along with NemakiWare. * If not, see <http://www.gnu.org/licenses/>. * * Contributors: * linzhixing(https://github.com/linzhixing) - initial API and implementation ******************************************************************************/ package jp.aegif.nemaki.cmis.aspect.impl; import java.math.BigInteger; import java.util.ArrayList; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.apache.chemistry.opencmis.commons.PropertyIds; import org.apache.chemistry.opencmis.commons.data.AllowableActions; import org.apache.chemistry.opencmis.commons.data.CmisExtensionElement; import org.apache.chemistry.opencmis.commons.data.ObjectData; import org.apache.chemistry.opencmis.commons.data.ObjectList; import org.apache.chemistry.opencmis.commons.data.PermissionMapping; import org.apache.chemistry.opencmis.commons.data.Principal; import org.apache.chemistry.opencmis.commons.data.Properties; import org.apache.chemistry.opencmis.commons.data.PropertyData; import org.apache.chemistry.opencmis.commons.data.RenditionData; import org.apache.chemistry.opencmis.commons.data.RepositoryCapabilities; import org.apache.chemistry.opencmis.commons.definitions.DocumentTypeDefinition; import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition; import org.apache.chemistry.opencmis.commons.definitions.SecondaryTypeDefinition; import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition; import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionContainer; import org.apache.chemistry.opencmis.commons.enums.Action; import org.apache.chemistry.opencmis.commons.enums.BaseTypeId; import org.apache.chemistry.opencmis.commons.enums.CapabilityRenditions; import org.apache.chemistry.opencmis.commons.enums.ChangeType; import org.apache.chemistry.opencmis.commons.enums.ContentStreamAllowed; import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships; import org.apache.chemistry.opencmis.commons.enums.PropertyType; import org.apache.chemistry.opencmis.commons.enums.RelationshipDirection; import org.apache.chemistry.opencmis.commons.impl.dataobjects.AbstractPropertyData; 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.ChangeEventInfoDataImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.CmisExtensionElementImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectDataImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.ObjectListImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.PolicyIdListImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertiesImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyBooleanImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyDateTimeImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIdImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyIntegerImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyStringImpl; import org.apache.chemistry.opencmis.commons.impl.dataobjects.RenditionDataImpl; import org.apache.chemistry.opencmis.commons.server.CallContext; import org.apache.chemistry.opencmis.commons.spi.Holder; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.rits.cloning.Cloner; import jp.aegif.nemaki.businesslogic.ContentService; import jp.aegif.nemaki.cmis.aspect.CompileService; import jp.aegif.nemaki.cmis.aspect.PermissionService; import jp.aegif.nemaki.cmis.aspect.SortUtil; import jp.aegif.nemaki.cmis.aspect.type.TypeManager; import jp.aegif.nemaki.cmis.factory.info.AclCapabilities; import jp.aegif.nemaki.cmis.factory.info.RepositoryInfoMap; import jp.aegif.nemaki.cmis.service.RepositoryService; import jp.aegif.nemaki.model.Ace; import jp.aegif.nemaki.model.Acl; import jp.aegif.nemaki.model.Aspect; import jp.aegif.nemaki.model.AttachmentNode; import jp.aegif.nemaki.model.Change; import jp.aegif.nemaki.model.Content; import jp.aegif.nemaki.model.Document; import jp.aegif.nemaki.model.Folder; import jp.aegif.nemaki.model.Item; import jp.aegif.nemaki.model.Policy; import jp.aegif.nemaki.model.Property; import jp.aegif.nemaki.model.Relationship; import jp.aegif.nemaki.model.Rendition; import jp.aegif.nemaki.model.VersionSeries; import jp.aegif.nemaki.util.DataUtil; import jp.aegif.nemaki.util.cache.NemakiCachePool; import jp.aegif.nemaki.util.constant.CmisExtensionToken; import net.sf.ehcache.Element; public class CompileServiceImpl implements CompileService { private static final Log log = LogFactory .getLog(CompileServiceImpl.class); private RepositoryInfoMap repositoryInfoMap; private RepositoryService repositoryService; private ContentService contentService; private PermissionService permissionService; private TypeManager typeManager; private AclCapabilities aclCapabilities; private NemakiCachePool nemakiCachePool; private SortUtil sortUtil; private boolean includeRelationshipsEnabled = true; /** * Builds a CMIS ObjectData from the given CouchDB content. */ @Override public ObjectData compileObjectData(CallContext callContext, String repositoryId, Content content, String filter, Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter, Boolean includeAcl) { ObjectDataImpl _result = new ObjectDataImpl(); ObjectData v = nemakiCachePool.get(repositoryId).getObjectDataCache().get(content.getId()); if(v == null){ _result = compileObjectDataWithFullAttributes(callContext, repositoryId, content); }else{ _result = (ObjectDataImpl)v; } ObjectData result = filterObjectData(repositoryId, _result, filter, includeAllowableActions, includeRelationships, renditionFilter, includeAcl); return result; } private ObjectDataImpl compileObjectDataWithFullAttributes(CallContext callContext, String repositoryId, Content content){ ObjectDataImpl result = new ObjectDataImpl(); //Filter(any property filter MUST be done here PropertiesImpl properties = compileProperties(callContext, repositoryId, content); result.setProperties(properties); // Set Allowable actions result.setAllowableActions(compileAllowableActions(callContext, repositoryId, content)); // Set Acl Acl acl = contentService.calculateAcl(repositoryId, content); result.setIsExactAcl(true); result.setAcl(compileAcl(acl, contentService.getAclInheritedWithDefault(repositoryId, content), false)); //Set Relationship(BOTH) if (!content.isRelationship()) { if(includeRelationshipsEnabled){ result.setRelationships(compileRelationships(callContext, repositoryId, content, IncludeRelationships.BOTH)); } } // Set Renditions if (content.isDocument()){ result.setRenditions(compileRenditions(callContext, repositoryId, content)); } nemakiCachePool.get(repositoryId).getObjectDataCache().put(new Element(content.getId(), result)); return result; } private ObjectData filterObjectData(String repositoryId, ObjectData fullObjectData, String filter, Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter, Boolean includeAcl){ //Deep copy ObjectData //Shallow copy will cause a destructive effect after filtering some attributes Cloner cloner=new Cloner(); ObjectDataImpl result = DataUtil.convertObjectDataImpl(cloner.deepClone(fullObjectData)); Properties filteredProperties = filterProperties(result.getProperties(), splitFilter(filter)); result.setProperties(filteredProperties); // Filter Allowable actions Boolean iaa = includeAllowableActions == null ? false: includeAllowableActions.booleanValue(); if (!iaa) { result.setAllowableActions(null); } // Filter Acl Boolean iacl = includeAcl == null ? false : includeAcl.booleanValue(); if (!iacl) { result.setAcl(null); } // Filter Relationships IncludeRelationships irl = includeRelationships == null ? IncludeRelationships.SOURCE : includeRelationships; if (fullObjectData.getBaseTypeId() == BaseTypeId.CMIS_RELATIONSHIP) { result.setRelationships(filterRelationships(result.getId(), result.getRelationships(), irl)); } // Filter Renditions if (fullObjectData.getBaseTypeId() == BaseTypeId.CMIS_DOCUMENT && repositoryInfoMap.get(repositoryId).getCapabilities().getRenditionsCapability() == CapabilityRenditions.NONE) { result.setRenditions(null); } return result; } private ObjectData filterObjectDataInList(CallContext callContext, String repositoryId, ObjectData fullObjectData, String filter, Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter, Boolean includeAcl){ boolean allowed = permissionService.checkPermission(callContext, Action.CAN_GET_PROPERTIES, fullObjectData); if(allowed){ return filterObjectData(repositoryId, fullObjectData, filter, includeAllowableActions, includeRelationships, renditionFilter, includeAcl); }else{ return null; } } private Properties filterProperties(Properties properties, Set<String> filter){ PropertiesImpl result = new PropertiesImpl(); //null filter as NO FILTER: do nothing if(filter == null){ return properties; }else{ for(String key : properties.getProperties().keySet()){ PropertyData<?> pd = properties.getProperties().get(key); if(filter.contains(pd.getQueryName())){ result.addProperty(pd); } } } return result; } private List<ObjectData> filterRelationships(String objectId, List<ObjectData> bothRelationships, IncludeRelationships includeRelationships){ String propertyId; switch(includeRelationships){ case NONE: return null; case SOURCE: propertyId = PropertyIds.SOURCE_ID; case TARGET: propertyId = PropertyIds.TARGET_ID; default: } List<ObjectData> filtered = new ArrayList<ObjectData>(); if(CollectionUtils.isNotEmpty(bothRelationships)){ for(ObjectData rel : bothRelationships){ PropertyData<?> filterId = rel.getProperties(). getProperties().get(PropertyIds.SOURCE_ID); if(objectId.equals(filterId)){ filtered.add(rel); } } return filtered; }else{ return null; } } @Override public <T extends Content> ObjectList compileObjectDataList(CallContext callContext, String repositoryId, List<T> contents, String filter, Boolean includeAllowableActions, IncludeRelationships includeRelationships, String renditionFilter, Boolean includeAcl, BigInteger maxItems, BigInteger skipCount, boolean folderOnly, String orderBy) { if (CollectionUtils.isEmpty(contents)) { //Empty list ObjectListImpl list = new ObjectListImpl(); list.setObjects(new ArrayList<ObjectData>()); list.setNumItems(BigInteger.ZERO); list.setHasMoreItems(false); return list; }else{ List<ObjectData>ods = new ArrayList<ObjectData>(); for(T c : contents){ //Filter by folderOnly if(folderOnly && !c.isFolder()){ continue; } //Get each ObjectData ObjectData _od; ObjectData v = nemakiCachePool.get(repositoryId).getObjectDataCache().get(c.getId()); if(v == null){ _od = compileObjectDataWithFullAttributes(callContext, repositoryId, c); }else{ _od = (ObjectDataImpl)v; } ObjectData od = filterObjectDataInList(callContext, repositoryId, _od, filter, includeAllowableActions, includeRelationships, renditionFilter, includeAcl); if(od != null){ ods.add(od); } } //Sort sortUtil.sort(repositoryId, ods, orderBy); //Set metadata ObjectListImpl list = new ObjectListImpl(); Integer _skipCount = skipCount.intValue(); Integer _maxItems = maxItems.intValue(); if(_skipCount >= ods.size()){ list.setHasMoreItems(false); list.setObjects(new ArrayList<ObjectData>()); }else{ //hasMoreItems Boolean hasMoreItems = _skipCount + _maxItems < ods.size(); list.setHasMoreItems(hasMoreItems); //paged list Integer toIndex = Math.min(_skipCount + _maxItems, ods.size()); list.setObjects(new ArrayList<>(ods.subList(_skipCount, toIndex))); } //totalNumItem list.setNumItems(BigInteger.valueOf(ods.size())); return list; } } @Override public ObjectList compileChangeDataList(CallContext context, String repositoryId, List<Change> changes, Holder<String> changeLogToken, Boolean includeProperties, String filter, Boolean includePolicyIds, Boolean includeAcl) { ObjectListImpl results = new ObjectListImpl(); results.setObjects(new ArrayList<ObjectData>()); Map<String, Content> cachedContents = new HashMap<String, Content>(); if (changes != null && CollectionUtils.isNotEmpty(changes)) { for (Change change : changes) { // Retrieve the content(using caches) String objectId = change.getId(); Content content = new Content(); if (cachedContents.containsKey(objectId)) { content = cachedContents.get(objectId); } else { content = contentService.getContent(repositoryId, objectId); cachedContents.put(objectId, content); } // Compile a change object data depending on its type results.getObjects().add( compileChangeObjectData(repositoryId, change, content, includePolicyIds, includeAcl)); } } results.setNumItems(BigInteger.valueOf(results.getObjects().size())); String latestInRepository = repositoryService.getRepositoryInfo(repositoryId) .getLatestChangeLogToken(); String latestInResults = changeLogToken.getValue(); if (latestInResults != null && latestInResults.equals(latestInRepository)) { results.setHasMoreItems(false); } else { results.setHasMoreItems(true); } return results; } private ObjectData compileChangeObjectData(String repositoryId, Change change, Content content, Boolean includePolicyIds, Boolean includeAcl) { ObjectDataImpl o = new ObjectDataImpl(); // Set Properties PropertiesImpl properties = new PropertiesImpl(); setCmisBasicChangeProperties(properties, change); o.setProperties(properties); // Set PolicyIds setPolcyIds(o, change, includePolicyIds); // Set Acl if (!change.getChangeType().equals(ChangeType.DELETED)) { setAcl(repositoryId, o, content, includeAcl); } // Set Change Event setChangeEvent(o, change); return o; } private void setCmisBasicChangeProperties(PropertiesImpl props, Change change) { props.addProperty(new PropertyIdImpl(PropertyIds.OBJECT_ID, change .getObjectId())); props.addProperty(new PropertyIdImpl(PropertyIds.BASE_TYPE_ID, change .getBaseType())); props.addProperty(new PropertyIdImpl(PropertyIds.OBJECT_TYPE_ID, change .getObjectType())); props.addProperty(new PropertyIdImpl(PropertyIds.NAME, change.getName())); if (change.isOnDocument()) { props.addProperty(new PropertyIdImpl(PropertyIds.VERSION_SERIES_ID, change.getVersionSeriesId())); props.addProperty(new PropertyStringImpl(PropertyIds.VERSION_LABEL, change.getVersionLabel())); } } private void setPolcyIds(ObjectDataImpl object, Change change, Boolean includePolicyids) { boolean iplc = (includePolicyids == null ? false : includePolicyids .booleanValue()); if (iplc) { List<String> policyIds = change.getPolicyIds(); PolicyIdListImpl plist = new PolicyIdListImpl(); plist.setPolicyIds(policyIds); object.setPolicyIds(plist); } } private void setAcl(String repositoryId, ObjectDataImpl object, Content content, Boolean includeAcl) { boolean iacl = (includeAcl == null ? false : includeAcl.booleanValue()); if (iacl) { if (content != null) { Acl acl = contentService.calculateAcl(repositoryId, content); //object.setAcl(compileAcl(acl, content.isAclInherited(), false)); object.setAcl(compileAcl(acl, contentService.getAclInheritedWithDefault(repositoryId, content), false)); } } } private void setChangeEvent(ObjectDataImpl object, Change change) { // Set ChangeEventInfo ChangeEventInfoDataImpl ce = new ChangeEventInfoDataImpl(); ce.setChangeType(change.getChangeType()); ce.setChangeTime(change.getTime()); object.setChangeEventInfo(ce); } /** * Sets allowable action for the content * @param content */ @Override public AllowableActions compileAllowableActions(CallContext callContext, String repositoryId, Content content) { // Get parameters to calculate AllowableActions TypeDefinition tdf = typeManager.getTypeDefinition(repositoryId, content .getObjectType()); jp.aegif.nemaki.model.Acl contentAcl = content.getAcl(); if (tdf.isControllableAcl() && contentAcl == null) return null; Acl acl = contentService.calculateAcl(repositoryId, content); Map<String, PermissionMapping> permissionMap = repositoryInfoMap.get(repositoryId) .getAclCapabilities().getPermissionMapping(); String baseType = content.getType(); // Calculate AllowableActions Set<Action> actionSet = new HashSet<Action>(); VersionSeries versionSeries = null; if(content.isDocument()){ Document d = (Document)content; versionSeries = contentService.getVersionSeries(repositoryId, d); } for (Entry<String, PermissionMapping> mappingEntry : permissionMap .entrySet()) { String key = mappingEntry.getValue().getKey(); // TODO WORKAROUND. implement class cast check // FIXME WORKAROUND: skip canCreatePolicy.Folder if (PermissionMapping.CAN_CREATE_POLICY_FOLDER.equals(key)) { continue; } // Additional check if (!isAllowableByCapability(repositoryId, key)) { continue; } if (!isAllowableByType(key, content, tdf)) { continue; } if (contentService.isRoot(repositoryId, content)) { if (Action.CAN_MOVE_OBJECT == convertKeyToAction(key)) { continue; } } if (versionSeries != null) { Document d = (Document) content; DocumentTypeDefinition dtdf = (DocumentTypeDefinition) tdf; if (!isAllowableActionForVersionableDocument(callContext, mappingEntry.getKey(), d, versionSeries, dtdf)) { continue; } } // Add an allowable action boolean allowable = permissionService.checkPermission(callContext, repositoryId, mappingEntry.getKey(), acl, baseType, content); if (allowable) { actionSet.add(convertKeyToAction(key)); } } AllowableActionsImpl allowableActions = new AllowableActionsImpl(); allowableActions.setAllowableActions(actionSet); return allowableActions; } private boolean isAllowableActionForVersionableDocument( CallContext callContext, String permissionMappingKey, Document document, VersionSeries versionSeries, DocumentTypeDefinition dtdf) { //Versioning action(checkOut / checkIn) if (permissionMappingKey .equals(PermissionMapping.CAN_CHECKOUT_DOCUMENT)) { return dtdf.isVersionable() && !versionSeries.isVersionSeriesCheckedOut() && document.isLatestVersion(); } else if (permissionMappingKey .equals(PermissionMapping.CAN_CHECKIN_DOCUMENT)) { return dtdf.isVersionable() && versionSeries.isVersionSeriesCheckedOut() && document.isPrivateWorkingCopy(); } else if (permissionMappingKey .equals(PermissionMapping.CAN_CANCEL_CHECKOUT_DOCUMENT)) { return dtdf.isVersionable() && versionSeries.isVersionSeriesCheckedOut() && document.isPrivateWorkingCopy(); } //Lock as an effect of checkOut if(dtdf.isVersionable()){ if(isLockableAction(permissionMappingKey)){ if(document.isLatestVersion()){ //LocK only when checked out return !versionSeries.isVersionSeriesCheckedOut(); }else if(document.isPrivateWorkingCopy()){ //Only owner can do actions on pwc return callContext.getUsername().equals(versionSeries.getVersionSeriesCheckedOutBy()); }else{ return false; } } } return true; } private boolean isLockableAction(String key) { return key.equals(PermissionMapping.CAN_UPDATE_PROPERTIES_OBJECT) || key.equals(PermissionMapping.CAN_SET_CONTENT_DOCUMENT) || key.equals(PermissionMapping.CAN_ADD_POLICY_OBJECT) || key.equals(PermissionMapping.CAN_ADD_TO_FOLDER_OBJECT) || key.equals(PermissionMapping.CAN_APPLY_ACL_OBJECT) || key.equals(PermissionMapping.CAN_DELETE_CONTENT_DOCUMENT) || key.equals(PermissionMapping.CAN_DELETE_OBJECT) || key.equals(PermissionMapping.CAN_MOVE_OBJECT) || key.equals(PermissionMapping.CAN_REMOVE_FROM_FOLDER_OBJECT) || key.equals(PermissionMapping.CAN_REMOVE_POLICY_OBJECT); } private boolean isAllowableByCapability(String repositoryId, String key) { RepositoryCapabilities capabilities = repositoryInfoMap.get(repositoryId).getCapabilities(); // Multifiling or Unfiling Capabilities if (PermissionMapping.CAN_ADD_TO_FOLDER_OBJECT.equals(key) || PermissionMapping.CAN_ADD_TO_FOLDER_FOLDER.equals(key)) { // This is not a explicit spec, but it's plausible. return capabilities.isUnfilingSupported() || capabilities.isMultifilingSupported(); } else if (PermissionMapping.CAN_REMOVE_FROM_FOLDER_OBJECT.equals(key) || PermissionMapping.CAN_REMOVE_FROM_FOLDER_FOLDER.equals(key)) { return capabilities.isUnfilingSupported(); // GetDescendents or GetFolderTree Capabilities } else if (PermissionMapping.CAN_GET_DESCENDENTS_FOLDER.equals(key)) { return capabilities.isGetDescendantsSupported() || capabilities.isGetFolderTreeSupported(); } else { return true; } } private boolean isAllowableByType(String key, Content content, TypeDefinition tdf) { // ControllableACL if (PermissionMapping.CAN_APPLY_ACL_OBJECT.equals(key)) { // Default to FALSE boolean ctrlAcl = (tdf.isControllableAcl() == null) ? false : tdf .isControllableAcl(); return ctrlAcl; // ControllablePolicy } else if (PermissionMapping.CAN_ADD_POLICY_OBJECT.equals(key) || PermissionMapping.CAN_ADD_POLICY_POLICY.equals(key) || PermissionMapping.CAN_REMOVE_POLICY_OBJECT.equals(key) || PermissionMapping.CAN_REMOVE_POLICY_POLICY.equals(key)) { // Default to FALSE boolean ctrlPolicy = (tdf.isControllablePolicy() == null) ? false : tdf.isControllablePolicy(); return ctrlPolicy; // setContent } else if (PermissionMapping.CAN_SET_CONTENT_DOCUMENT.equals(key)) { if (BaseTypeId.CMIS_DOCUMENT != tdf.getBaseTypeId()) return true; DocumentTypeDefinition _tdf = (DocumentTypeDefinition) tdf; // Default to REQUIRED ContentStreamAllowed csa = (_tdf.getContentStreamAllowed() == null) ? ContentStreamAllowed.REQUIRED : _tdf.getContentStreamAllowed(); return !(csa == ContentStreamAllowed.NOTALLOWED); // deleteContent } else if (PermissionMapping.CAN_DELETE_CONTENT_DOCUMENT.equals(key)) { if (BaseTypeId.CMIS_DOCUMENT != tdf.getBaseTypeId()) return true; DocumentTypeDefinition _tdf = (DocumentTypeDefinition) tdf; // Default to REQUIRED ContentStreamAllowed csa = (_tdf.getContentStreamAllowed() == null) ? ContentStreamAllowed.REQUIRED : _tdf.getContentStreamAllowed(); return !(csa == ContentStreamAllowed.REQUIRED); } else { return true; } } private List<ObjectData> compileRelationships(CallContext context, String repositoryId, Content content, IncludeRelationships irl) { if (IncludeRelationships.NONE == irl) { return null; } RelationshipDirection rd; switch (irl) { case SOURCE: rd = RelationshipDirection.SOURCE; break; case TARGET: rd = RelationshipDirection.TARGET; break; case BOTH: rd = RelationshipDirection.EITHER; break; default: rd = RelationshipDirection.SOURCE; break; } List<Relationship> _rels = contentService.getRelationsipsOfObject( repositoryId, content.getId(), rd); List<ObjectData> rels = new ArrayList<ObjectData>(); if (CollectionUtils.isNotEmpty(_rels)) { for (Relationship _rel : _rels) { ObjectData rel = compileObjectData(context, repositoryId, _rel, null, false, IncludeRelationships.NONE, null, false); rels.add(rel); } } return rels; } private List<RenditionData> compileRenditions(CallContext callContext, String repositoryId, Content content) { List<RenditionData> renditions = new ArrayList<RenditionData>(); List<Rendition> _renditions = contentService.getRenditions(repositoryId, content .getId()); if (CollectionUtils.isNotEmpty(_renditions)) { for (Rendition _rd : _renditions) { RenditionDataImpl rd = new RenditionDataImpl(); rd.setStreamId(_rd.getId()); rd.setMimeType(_rd.getMimetype()); rd.setBigLength(BigInteger.valueOf(_rd.getLength())); rd.setKind(_rd.getKind()); rd.setTitle(_rd.getTitle()); rd.setBigHeight(BigInteger.valueOf(_rd.getHeight())); rd.setBigWidth(BigInteger.valueOf(_rd.getWidth())); rd.setRenditionDocumentId(_rd.getRenditionDocumentId()); renditions.add(rd); } } return renditions; } /** * Compiles properties of a piece of content. */ @Override public PropertiesImpl compileProperties(CallContext callContext, String repositoryId, Content content) { TypeDefinitionContainer tdfc = typeManager.getTypeById(repositoryId, content.getObjectType()); TypeDefinition tdf = tdfc.getTypeDefinition(); PropertiesImpl properties = new PropertiesImpl(); if (content.isFolder()) { Folder folder = (Folder) content; // Root folder if (contentService.isRoot(repositoryId, folder)) { properties = compileRootFolderProperties(repositoryId, folder, properties, tdf); // Other than root folder } else { properties = compileFolderProperties(repositoryId, folder, properties, tdf); } } else if (content.isDocument()) { Document document = (Document) content; properties = compileDocumentProperties(callContext, repositoryId, document, properties, tdf); } else if (content.isRelationship()) { Relationship relationship = (Relationship) content; properties = compileRelationshipProperties(repositoryId, relationship, properties, tdf); } else if (content.isPolicy()) { Policy policy = (Policy) content; properties = compilePolicyProperties(repositoryId, policy, properties, tdf); } else if (content.isItem()) { Item item = (Item) content; properties = compileItemProperties(repositoryId, item, properties, tdf); } return properties; } private PropertiesImpl compileRootFolderProperties(String repositoryId, Folder folder, PropertiesImpl properties, TypeDefinition tdf) { setCmisBaseProperties(repositoryId, properties, tdf, folder); // Add parentId property without value String _null = null; PropertyIdImpl parentId = new PropertyIdImpl(PropertyIds.PARENT_ID, _null); properties.addProperty(parentId); setCmisFolderProperties(repositoryId, properties, tdf, folder); return properties; } private PropertiesImpl compileFolderProperties(String repositoryId, Folder folder, PropertiesImpl properties, TypeDefinition tdf) { setCmisBaseProperties(repositoryId, properties, tdf, folder); addProperty(properties, tdf, PropertyIds.PARENT_ID, folder.getParentId()); setCmisFolderProperties(repositoryId, properties, tdf, folder); return properties; } private PropertiesImpl compileDocumentProperties(CallContext callContext, String repositoryId, Document document, PropertiesImpl properties, TypeDefinition tdf) { setCmisBaseProperties(repositoryId, properties, tdf, document); setCmisDocumentProperties(callContext, repositoryId, properties, tdf, document); setCmisAttachmentProperties(repositoryId, properties, tdf, document); return properties; } private PropertiesImpl compileRelationshipProperties( String repositoryId, Relationship relationship, PropertiesImpl properties, TypeDefinition tdf) { setCmisBaseProperties(repositoryId, properties, tdf, relationship); setCmisRelationshipProperties(properties, tdf, relationship); return properties; } private PropertiesImpl compilePolicyProperties(String repositoryId, Policy policy, PropertiesImpl properties, TypeDefinition tdf) { setCmisBaseProperties(repositoryId, properties, tdf, policy); setCmisPolicyProperties(properties, tdf, policy); return properties; } private PropertiesImpl compileItemProperties(String repositoryId, Item item, PropertiesImpl properties, TypeDefinition tdf) { setCmisBaseProperties(repositoryId, properties, tdf, item); setCmisItemProperties(properties, tdf, item); return properties; } private void setCmisBaseProperties(String repositoryId, PropertiesImpl properties, TypeDefinition tdf, Content content) { addProperty(properties, tdf, PropertyIds.NAME, content.getName()); addProperty(properties, tdf, PropertyIds.DESCRIPTION, content.getDescription()); addProperty(properties, tdf, PropertyIds.OBJECT_ID, content.getId()); addProperty(properties, tdf, PropertyIds.OBJECT_TYPE_ID, content.getObjectType()); if (content.getCreated() != null) addProperty(properties, tdf, PropertyIds.CREATION_DATE, content.getCreated()); if (content.getCreator() != null) addProperty(properties, tdf, PropertyIds.CREATED_BY, content.getCreator()); if (content.getModified() != null) { addProperty(properties, tdf, PropertyIds.LAST_MODIFICATION_DATE, content.getModified()); } else { addProperty(properties, tdf, PropertyIds.LAST_MODIFICATION_DATE, content.getCreated()); } if (content.getModifier() != null) { addProperty(properties, tdf, PropertyIds.LAST_MODIFIED_BY, content.getModifier()); } else { addProperty(properties, tdf, PropertyIds.LAST_MODIFIED_BY, content.getCreator()); } addProperty(properties, tdf, PropertyIds.CHANGE_TOKEN, String.valueOf(content.getChangeToken())); // TODO If subType properties is not registered in DB, return void // properties via CMIS // SubType properties List<PropertyDefinition<?>> specificPropertyDefinitions = typeManager .getSpecificPropertyDefinitions(tdf.getId()); if (!CollectionUtils.isEmpty(specificPropertyDefinitions)) { for (PropertyDefinition<?> propertyDefinition : specificPropertyDefinitions) { Property property = extractSubTypeProperty(content, propertyDefinition.getId()); Object value = (property == null) ? null : property.getValue(); addProperty(properties,tdf, propertyDefinition.getId(), value); } } // Secondary properties setCmisSecondaryTypes(repositoryId, properties, content, tdf); } private Property extractSubTypeProperty(Content content, String propertyId) { List<Property> subTypeProperties = content.getSubTypeProperties(); if (CollectionUtils.isNotEmpty(subTypeProperties)) { for (Property subTypeProperty : subTypeProperties) { if (subTypeProperty.getKey().equals(propertyId)) { return subTypeProperty; } } } return null; } private void setCmisFolderProperties(String repositoryId, PropertiesImpl properties, TypeDefinition tdf, Folder folder) { addProperty(properties, tdf, PropertyIds.BASE_TYPE_ID, BaseTypeId.CMIS_FOLDER.value()); addProperty(properties, tdf, PropertyIds.PATH, contentService.calculatePath(repositoryId, folder)); if (checkAddProperty(properties, tdf, PropertyIds.ALLOWED_CHILD_OBJECT_TYPE_IDS)) { List<String> values = new ArrayList<String>(); // If not specified, all child types are allowed. if (!CollectionUtils.isEmpty(folder.getAllowedChildTypeIds())) { values = folder.getAllowedChildTypeIds(); } PropertyData<String> pd = new PropertyIdImpl( PropertyIds.ALLOWED_CHILD_OBJECT_TYPE_IDS, values); properties.addProperty(pd); } } private void setCmisDocumentProperties(CallContext callContext, String repositoryId, PropertiesImpl properties, TypeDefinition tdf, Document document) { addProperty(properties, tdf, PropertyIds.BASE_TYPE_ID, BaseTypeId.CMIS_DOCUMENT.value()); Boolean isImmutable = (document.isImmutable() == null) ? (Boolean) typeManager .getSingleDefaultValue(PropertyIds.IS_IMMUTABLE, tdf.getId(), repositoryId) : document.isImmutable(); addProperty(properties, tdf, PropertyIds.IS_IMMUTABLE, isImmutable); DocumentTypeDefinition type = (DocumentTypeDefinition) typeManager .getTypeDefinition(repositoryId, tdf.getId()); if (type.isVersionable()) { addProperty(properties, tdf, PropertyIds.IS_PRIVATE_WORKING_COPY, document.isPrivateWorkingCopy()); addProperty(properties, tdf, PropertyIds.IS_LATEST_VERSION, document.isLatestVersion()); addProperty(properties, tdf, PropertyIds.IS_MAJOR_VERSION, document.isMajorVersion()); addProperty(properties, tdf, PropertyIds.IS_LATEST_MAJOR_VERSION, document.isLatestMajorVersion()); addProperty(properties, tdf, PropertyIds.VERSION_LABEL, document.getVersionLabel()); addProperty(properties, tdf, PropertyIds.VERSION_SERIES_ID, document.getVersionSeriesId()); addProperty(properties, tdf, PropertyIds.CHECKIN_COMMENT, document.getCheckinComment()); VersionSeries vs = contentService.getVersionSeries(repositoryId, document); addProperty(properties, tdf, PropertyIds.IS_VERSION_SERIES_CHECKED_OUT, vs.isVersionSeriesCheckedOut()); if (vs.isVersionSeriesCheckedOut()) { String userId = callContext.getUsername(); String checkedOutBy = vs.getVersionSeriesCheckedOutBy(); if(userId.equals(checkedOutBy)){ addProperty(properties, tdf, PropertyIds.VERSION_SERIES_CHECKED_OUT_ID, vs.getVersionSeriesCheckedOutId()); addProperty(properties, tdf, PropertyIds.VERSION_SERIES_CHECKED_OUT_BY, checkedOutBy); }else{ addProperty(properties, tdf, PropertyIds.VERSION_SERIES_CHECKED_OUT_ID, null); addProperty(properties, tdf, PropertyIds.VERSION_SERIES_CHECKED_OUT_BY, checkedOutBy); } } else { addProperty(properties, tdf, PropertyIds.VERSION_SERIES_CHECKED_OUT_ID, null); addProperty(properties, tdf, PropertyIds.VERSION_SERIES_CHECKED_OUT_BY, null); } // TODO comment } else { addProperty(properties, tdf, PropertyIds.IS_PRIVATE_WORKING_COPY, false); addProperty(properties, tdf, PropertyIds.IS_LATEST_VERSION, false); addProperty(properties, tdf, PropertyIds.IS_MAJOR_VERSION, false); addProperty(properties, tdf, PropertyIds.IS_LATEST_MAJOR_VERSION, false); addProperty(properties, tdf, PropertyIds.VERSION_LABEL, ""); addProperty(properties, tdf, PropertyIds.VERSION_SERIES_ID, ""); addProperty(properties, tdf, PropertyIds.CHECKIN_COMMENT, ""); addProperty(properties, tdf, PropertyIds.IS_VERSION_SERIES_CHECKED_OUT, false); addProperty(properties, tdf, PropertyIds.VERSION_SERIES_CHECKED_OUT_ID, ""); addProperty(properties, tdf, PropertyIds.VERSION_SERIES_CHECKED_OUT_BY, ""); } } private void setCmisAttachmentProperties(String repositoryId, PropertiesImpl properties, TypeDefinition tdf, Document document) { Long length = null; String mimeType = null; String fileName = null; String streamId = null; //Check if ContentStream is attached DocumentTypeDefinition dtdf = (DocumentTypeDefinition)tdf; ContentStreamAllowed csa = dtdf.getContentStreamAllowed(); if(ContentStreamAllowed.REQUIRED == csa || ContentStreamAllowed.ALLOWED == csa && StringUtils.isNotBlank(document.getAttachmentNodeId())){ AttachmentNode attachment = contentService.getAttachmentRef(repositoryId, document .getAttachmentNodeId()); if(attachment == null){ String attachmentId = (document.getAttachmentNodeId() == null) ? "" : document.getAttachmentNodeId(); log.warn("[objectId=" + document.getId() + " has no file (" + attachmentId + ")"); }else{ length = attachment.getLength(); mimeType = attachment.getMimeType(); fileName = document.getName(); streamId = attachment.getId(); } } //Add ContentStream properties to Document object addProperty(properties, dtdf, PropertyIds.CONTENT_STREAM_LENGTH, length); addProperty(properties, dtdf, PropertyIds.CONTENT_STREAM_MIME_TYPE, mimeType); addProperty(properties, dtdf, PropertyIds.CONTENT_STREAM_FILE_NAME, fileName); addProperty(properties, dtdf, PropertyIds.CONTENT_STREAM_ID, streamId); } private void setCmisRelationshipProperties(PropertiesImpl properties, TypeDefinition typeId, Relationship relationship) { addProperty(properties, typeId, PropertyIds.BASE_TYPE_ID, BaseTypeId.CMIS_RELATIONSHIP.value()); addProperty(properties, typeId, PropertyIds.SOURCE_ID, relationship.getSourceId()); addProperty(properties, typeId, PropertyIds.TARGET_ID, relationship.getTargetId()); } private void setCmisPolicyProperties(PropertiesImpl properties, TypeDefinition tdf, Policy policy) { addProperty(properties, tdf, PropertyIds.BASE_TYPE_ID, BaseTypeId.CMIS_POLICY.value()); addProperty(properties, tdf, PropertyIds.POLICY_TEXT, policy.getPolicyText()); } private void setCmisItemProperties(PropertiesImpl properties, TypeDefinition tdf, Item item) { addProperty(properties, tdf, PropertyIds.BASE_TYPE_ID, BaseTypeId.CMIS_ITEM.value()); } private void setCmisSecondaryTypes(String repositoryId, PropertiesImpl props, Content content, TypeDefinition tdf) { List<Aspect> aspects = content.getAspects(); List<String> secondaryIds = new ArrayList<String>(); // cmis:secondaryObjectTypeIds if (CollectionUtils.isNotEmpty(content.getSecondaryIds())) { for (String secondaryId : content.getSecondaryIds()) { secondaryIds.add(secondaryId); } } new PropertyIdImpl(PropertyIds.SECONDARY_OBJECT_TYPE_IDS, secondaryIds); addProperty(props, tdf, PropertyIds.SECONDARY_OBJECT_TYPE_IDS, secondaryIds); // each secondary properties for (String secondaryId : secondaryIds) { List<PropertyDefinition<?>> secondaryPropertyDefinitions = typeManager .getSpecificPropertyDefinitions(secondaryId); if (CollectionUtils.isEmpty(secondaryPropertyDefinitions)) continue; Aspect aspect = extractAspect(aspects, secondaryId); List<Property> properties = (aspect == null) ? new ArrayList<Property>() : aspect.getProperties(); SecondaryTypeDefinition stdf = (SecondaryTypeDefinition)typeManager.getTypeDefinition(repositoryId, secondaryId); for (PropertyDefinition<?> secondaryPropertyDefinition : secondaryPropertyDefinitions) { Property property = extractProperty(properties, secondaryPropertyDefinition.getId()); Object value = (property == null) ? null : property.getValue(); addProperty(props, stdf, secondaryPropertyDefinition.getId(), value); } } } private Aspect extractAspect(List<Aspect> aspects, String aspectId) { for (Aspect aspect : aspects) { if (aspect.getName().equals(aspectId)) { return aspect; } } return null; } private Property extractProperty(List<Property> properties, String propertyId) { for (Property property : properties) { if (property.getKey().equals(propertyId)) { return property; } } return null; } /** * Verifies that parameters are safe. */ private boolean checkAddProperty(Properties properties, TypeDefinition tdf, String id) { if ((properties == null) || (properties.getProperties() == null)) throw new IllegalArgumentException("Properties must not be null!"); if (StringUtils.isEmpty(id)) throw new IllegalArgumentException("ID must not be null!"); // TODO :performance if (!tdf.getPropertyDefinitions().containsKey(id)) throw new IllegalArgumentException("Unknown property: " + id); //String queryName = tdf.getPropertyDefinitions().get(id).getQueryName(); /* if ((queryName != null) && (filter != null)) { if (!filter.contains(queryName)) { return false; } else { filter.remove(queryName); } }*/ return true; } /** * Adds specified property in property set. * * @param props * property set * @param tdf * object type (e.g. cmis:document) * @param id * property ID * @param value * actual property value */ // TODO if cast fails, continue the operation private void addProperty(PropertiesImpl props, TypeDefinition tdf, String id, Object value) { try { PropertyDefinition<?> pdf = tdf.getPropertyDefinitions().get(id); if (!checkAddProperty(props, tdf, id)) return; switch (pdf.getPropertyType()) { case BOOLEAN: PropertyBooleanImpl propBoolean; if (value instanceof List<?>) { propBoolean = new PropertyBooleanImpl(id, (List<Boolean>) value); } else if (value instanceof Boolean) { propBoolean = new PropertyBooleanImpl(id, (Boolean) value); } else { Boolean _null = null; propBoolean = new PropertyBooleanImpl(id, _null); if (value != null) { String msg = buildCastErrMsg(tdf.getId(), id, pdf.getPropertyType(), value.getClass() .getName(), Boolean.class.getName()); log.warn(msg); } } addPropertyBase(props, id, propBoolean, pdf); break; case INTEGER: PropertyIntegerImpl propInteger; if (value instanceof List<?>) { propInteger = new PropertyIntegerImpl(id, (List<BigInteger>) value); } else if (value instanceof Long || value instanceof Integer) { propInteger = new PropertyIntegerImpl(id, BigInteger.valueOf((Long) value)); } else { BigInteger _null = null; propInteger = new PropertyIntegerImpl(id, _null); if (value != null) { String msg = buildCastErrMsg(tdf.getId(), id, pdf.getPropertyType(), value.getClass() .getName(), Long.class.getName()); log.warn(msg); } } addPropertyBase(props, id, propInteger, pdf); break; case DATETIME: PropertyDateTimeImpl propDate; if (value instanceof List<?>) { propDate = new PropertyDateTimeImpl(id, (List<GregorianCalendar>) value); } else if (value instanceof GregorianCalendar) { propDate = new PropertyDateTimeImpl(id, (GregorianCalendar) value); } else { GregorianCalendar _null = null; propDate = new PropertyDateTimeImpl(id, _null); if (value != null) { String msg = buildCastErrMsg(tdf.getId(), id, pdf.getPropertyType(), value.getClass() .getName(), GregorianCalendar.class.getName()); log.warn(msg); } } addPropertyBase(props, id, propDate, pdf); break; case STRING: PropertyStringImpl propString = new PropertyStringImpl(); propString.setId(id); if (value instanceof List<?>) { propString.setValues((List<String>) value); } else if (value instanceof String) { propString.setValue(String.valueOf(value)); } else { String _null = null; propString = new PropertyStringImpl(id, _null); if (value != null) { String msg = buildCastErrMsg(tdf.getId(), id, pdf.getPropertyType(), value.getClass() .getName(), String.class.getName()); log.warn(msg); } } addPropertyBase(props, id, propString, pdf); break; case ID: PropertyIdImpl propId = new PropertyIdImpl(); propId.setId(id); if (value instanceof List<?>) { propId.setValues((List<String>) value); } else if (value instanceof String) { propId.setValue(String.valueOf(value)); } else { String _null = null; propId = new PropertyIdImpl(id, _null); if (value != null) { String msg = buildCastErrMsg(tdf.getId(), id, pdf.getPropertyType(), value.getClass() .getName(), String.class.getName()); log.warn(msg); } } addPropertyBase(props, id, propId, pdf); break; default: } } catch (Exception e) { log.warn("typeId:" + tdf + ", propertyId:" + id + " Fail to add a property!", e); } } private String buildCastErrMsg(String typeId, String propertyId, PropertyType propertyType, String sourceClass, String targetClass) { return "[typeId:" + typeId + ", propertyId:" + propertyId + ", propertyType:" + propertyType.value() + "]Cannot convert " + sourceClass + " to " + targetClass; } private <T> void addPropertyBase(PropertiesImpl props, String id, AbstractPropertyData<T> p, PropertyDefinition<?> pdf) { p.setDisplayName(pdf.getDisplayName()); p.setLocalName(id); p.setQueryName(pdf.getQueryName()); props.addProperty(p); } /** * Separates filter string with ','. If filter is null or empty, it means * all properties can go. */ // TODO implement CMIS filterNotValid exception? // NOTE: "not set" can mean "all properties" and invalid queryName should be // ignored. // NOTE: So, filterNotValid exception might not be needed. @Override public Set<String> splitFilter(String filter) { final String ASTERISK = "*"; final String COMMA = ","; if (filter == null || filter.trim().length() == 0) { return null; } Set<String> filters = new HashSet<String>(); for (String s : filter.split(COMMA)) { s = s.trim(); if (s.equals(ASTERISK)) { return null; } else if (s.length() > 0) { filters.add(s); } } // set a few base properties for ObjetInfo // query name == id (for base type properties) filters.add(PropertyIds.OBJECT_ID); filters.add(PropertyIds.OBJECT_TYPE_ID); filters.add(PropertyIds.BASE_TYPE_ID); return filters; } private Action convertKeyToAction(String key) { // NavigationServices if (PermissionMapping.CAN_GET_DESCENDENTS_FOLDER.equals(key)) return Action.CAN_GET_DESCENDANTS; if (PermissionMapping.CAN_GET_CHILDREN_FOLDER.equals(key)) return Action.CAN_GET_CHILDREN; if (PermissionMapping.CAN_GET_FOLDER_PARENT_OBJECT.equals(key)) return Action.CAN_GET_FOLDER_PARENT; if (PermissionMapping.CAN_GET_PARENTS_FOLDER.equals(key)) return Action.CAN_GET_OBJECT_PARENTS; // Object Services if (PermissionMapping.CAN_CREATE_DOCUMENT_FOLDER.equals(key)) return Action.CAN_CREATE_DOCUMENT; if (PermissionMapping.CAN_CREATE_FOLDER_FOLDER.equals(key)) return Action.CAN_CREATE_FOLDER; // FIXME the constant already implemented? // if (PermissionMapping.CAN_CREATE_POLICY_FOLDER.equals(key)) // return null; if (PermissionMapping.CAN_CREATE_RELATIONSHIP_SOURCE.equals(key)) return Action.CAN_CREATE_RELATIONSHIP; if (PermissionMapping.CAN_CREATE_RELATIONSHIP_TARGET.equals(key)) return Action.CAN_CREATE_RELATIONSHIP; if (PermissionMapping.CAN_GET_PROPERTIES_OBJECT.equals(key)) return Action.CAN_GET_PROPERTIES; if (PermissionMapping.CAN_UPDATE_PROPERTIES_OBJECT.equals(key)) return Action.CAN_UPDATE_PROPERTIES; if (PermissionMapping.CAN_MOVE_OBJECT.equals(key)) return Action.CAN_MOVE_OBJECT; if (PermissionMapping.CAN_MOVE_TARGET.equals(key)) return Action.CAN_MOVE_OBJECT; if (PermissionMapping.CAN_MOVE_SOURCE.equals(key)) return Action.CAN_MOVE_OBJECT; if (PermissionMapping.CAN_DELETE_OBJECT.equals(key)) return Action.CAN_DELETE_OBJECT; if (PermissionMapping.CAN_VIEW_CONTENT_OBJECT.equals(key)) return Action.CAN_GET_CONTENT_STREAM; if (PermissionMapping.CAN_SET_CONTENT_DOCUMENT.equals(key)) return Action.CAN_SET_CONTENT_STREAM; if (PermissionMapping.CAN_DELETE_CONTENT_DOCUMENT.equals(key)) return Action.CAN_DELETE_CONTENT_STREAM; if (PermissionMapping.CAN_DELETE_TREE_FOLDER.equals(key)) return Action.CAN_DELETE_TREE; // Filing Services if (PermissionMapping.CAN_ADD_TO_FOLDER_OBJECT.equals(key)) return Action.CAN_ADD_OBJECT_TO_FOLDER; if (PermissionMapping.CAN_ADD_TO_FOLDER_OBJECT.equals(key)) return Action.CAN_ADD_OBJECT_TO_FOLDER; if (PermissionMapping.CAN_REMOVE_FROM_FOLDER_OBJECT.equals(key)) return Action.CAN_REMOVE_OBJECT_FROM_FOLDER; if (PermissionMapping.CAN_REMOVE_FROM_FOLDER_FOLDER.equals(key)) return Action.CAN_REMOVE_OBJECT_FROM_FOLDER; // Versioning Services if (PermissionMapping.CAN_CHECKOUT_DOCUMENT.equals(key)) return Action.CAN_CHECK_OUT; if (PermissionMapping.CAN_CANCEL_CHECKOUT_DOCUMENT.equals(key)) return Action.CAN_CANCEL_CHECK_OUT; if (PermissionMapping.CAN_CHECKIN_DOCUMENT.equals(key)) return Action.CAN_CHECK_IN; if (PermissionMapping.CAN_GET_ALL_VERSIONS_VERSION_SERIES.equals(key)) return Action.CAN_GET_ALL_VERSIONS; // Relationship Services if (PermissionMapping.CAN_GET_OBJECT_RELATIONSHIPS_OBJECT.equals(key)) return Action.CAN_GET_OBJECT_RELATIONSHIPS; // Policy Services if (PermissionMapping.CAN_ADD_POLICY_OBJECT.equals(key)) return Action.CAN_APPLY_POLICY; if (PermissionMapping.CAN_ADD_POLICY_POLICY.equals(key)) return Action.CAN_APPLY_POLICY; if (PermissionMapping.CAN_REMOVE_POLICY_OBJECT.equals(key)) return Action.CAN_REMOVE_POLICY; if (PermissionMapping.CAN_REMOVE_POLICY_POLICY.equals(key)) return Action.CAN_REMOVE_POLICY; if (PermissionMapping.CAN_GET_APPLIED_POLICIES_OBJECT.equals(key)) return Action.CAN_GET_APPLIED_POLICIES; // ACL Services if (PermissionMapping.CAN_GET_ACL_OBJECT.equals(key)) return Action.CAN_GET_ACL; if (PermissionMapping.CAN_APPLY_ACL_OBJECT.equals(key)) return Action.CAN_APPLY_ACL; return null; } @Override public org.apache.chemistry.opencmis.commons.data.Acl compileAcl( Acl acl, Boolean isInherited, Boolean onlyBasicPermissions){ //Default to FALSE boolean obp = (onlyBasicPermissions == null) ? false : onlyBasicPermissions; AccessControlListImpl cmisAcl = new AccessControlListImpl(); cmisAcl.setAces(new ArrayList<org.apache.chemistry.opencmis.commons.data.Ace>()); if(acl != null){ // Set local ACEs buildCmisAce(cmisAcl, true, acl.getLocalAces(), obp); // Set inherited ACEs buildCmisAce(cmisAcl, false, acl.getInheritedAces(), obp); } // Set "exact" property cmisAcl.setExact(true); // Set "inherited" property, which is out of bounds to CMIS String namespace = CmisExtensionToken.ACL_INHERITANCE_NAMESPACE; //boolean iht = (isInherited == null)? false : isInherited; CmisExtensionElementImpl inherited = new CmisExtensionElementImpl( namespace, CmisExtensionToken.ACL_INHERITANCE_INHERITED, null, String.valueOf(isInherited)); List<CmisExtensionElement> exts = new ArrayList<CmisExtensionElement>(); exts.add(inherited); cmisAcl.setExtensions(exts); return cmisAcl; } private void buildCmisAce(AccessControlListImpl cmisAcl, boolean direct, List<Ace> aces, boolean onlyBasicPermissions){ if(CollectionUtils.isNotEmpty(aces)){ for (Ace ace : aces) { //Set principal Principal principal = new AccessControlPrincipalDataImpl( ace.getPrincipalId()); //Set permissions List<String> permissions= new ArrayList<String>(); if(onlyBasicPermissions && CollectionUtils.isNotEmpty(ace.getPermissions())){ HashMap<String,String> map = aclCapabilities.getBasicPermissionConversion(); //Translate permissions as CMIS Basic permissions for(String p : ace.getPermissions()){ permissions.add(map.get(p)); } }else{ permissions = ace.getPermissions(); } //Build CMIS ACE AccessControlEntryImpl cmisAce = new AccessControlEntryImpl( principal, permissions); //Set direct flag cmisAce.setDirect(direct); cmisAcl.getAces().add(cmisAce); } } } public void setRepositoryInfoMap(RepositoryInfoMap repositoryInfoMap) { this.repositoryInfoMap = repositoryInfoMap; } public void setRepositoryService(RepositoryService repositoryService) { this.repositoryService = repositoryService; } public void setContentService(ContentService contentService) { this.contentService = contentService; } public void setPermissionService(PermissionService permissionService) { this.permissionService = permissionService; } public void setAclCapabilities(AclCapabilities aclCapabilities) { this.aclCapabilities = aclCapabilities; } public void setTypeManager(TypeManager typeManager) { this.typeManager = typeManager; } public void setNemakiCachePool(NemakiCachePool nemakiCachePool) { this.nemakiCachePool = nemakiCachePool; } public void setIncludeRelationshipsEnabled(boolean includeRelationshipsEnabled) { this.includeRelationshipsEnabled = includeRelationshipsEnabled; } public void setSortUtil(SortUtil sortUtil) { this.sortUtil = sortUtil; } }