OpenCMIS server performance improvements

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@29571 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Florian Mü
2011-08-05 13:58:17 +00:00
parent 382ed97a94
commit 46ef31e926
6 changed files with 143 additions and 73 deletions

View File

@@ -146,12 +146,14 @@ public class AlfrescoCmisService extends AbstractCmisService
private CMISConnector connector; private CMISConnector connector;
private CallContext context; private CallContext context;
private UserTransaction txn; private UserTransaction txn;
private Map<String, CMISNodeInfoImpl> nodeInfoMap; private Map<String, CMISNodeInfo> nodeInfoMap;
private Map<String, ObjectInfo> objectInfoMap;
public AlfrescoCmisService(CMISConnector connector) public AlfrescoCmisService(CMISConnector connector)
{ {
this.connector = connector; this.connector = connector;
nodeInfoMap = new HashMap<String, CMISNodeInfoImpl>(); nodeInfoMap = new HashMap<String, CMISNodeInfo>();
objectInfoMap = new HashMap<String, ObjectInfo>();
} }
public void beginCall(CallContext context) public void beginCall(CallContext context)
@@ -228,8 +230,7 @@ public class AlfrescoCmisService extends AbstractCmisService
AuthenticationUtil.popAuthentication(); AuthenticationUtil.popAuthentication();
context = null; context = null;
nodeInfoMap.clear(); nodeInfoMap.clear();
objectInfoMap.clear();
super.close();
} }
} }
@@ -291,9 +292,9 @@ public class AlfrescoCmisService extends AbstractCmisService
return result; return result;
} }
protected CMISNodeInfoImpl getOrCreateNodeInfo(String objectId) protected CMISNodeInfo getOrCreateNodeInfo(String objectId)
{ {
CMISNodeInfoImpl result = nodeInfoMap.get(objectId); CMISNodeInfo result = nodeInfoMap.get(objectId);
if (result == null) if (result == null)
{ {
result = connector.createNodeInfo(objectId); result = connector.createNodeInfo(objectId);
@@ -303,22 +304,33 @@ public class AlfrescoCmisService extends AbstractCmisService
return result; return result;
} }
protected CMISNodeInfoImpl getOrCreateNodeInfo(String objectId, String what) protected CMISNodeInfo getOrCreateNodeInfo(String objectId, String what)
{ {
CMISNodeInfoImpl result = getOrCreateNodeInfo(objectId); CMISNodeInfo result = getOrCreateNodeInfo(objectId);
result.checkIfUseful(what); if (result instanceof CMISNodeInfoImpl)
{
((CMISNodeInfoImpl) result).checkIfUseful(what);
}
return result; return result;
} }
protected CMISNodeInfoImpl getOrCreateFolderInfo(String folderId, String what) protected CMISNodeInfo getOrCreateFolderInfo(String folderId, String what)
{ {
CMISNodeInfoImpl result = getOrCreateNodeInfo(folderId); CMISNodeInfo result = getOrCreateNodeInfo(folderId);
result.checkIfFolder(what); if (result instanceof CMISNodeInfoImpl)
{
((CMISNodeInfoImpl) result).checkIfFolder(what);
}
return result; return result;
} }
protected void addNodeInfo(CMISNodeInfo info)
{
nodeInfoMap.put(info.getObjectId(), info);
}
// --- repository service --- // --- repository service ---
@Override @Override
@@ -810,15 +822,16 @@ public class AlfrescoCmisService extends AbstractCmisService
} }
// get the parent // get the parent
ChildAssociationRef parent = connector.getNodeService().getPrimaryParent(info.getNodeRef()); List<CMISNodeInfo> parentInfos = info.getParents();
if (parent == null) if (parentInfos.isEmpty())
{ {
throw new CmisRuntimeException("Folder has no parent and is not the root folder?!"); throw new CmisRuntimeException("Folder has no parent and is not the root folder?!");
} }
// create parent object CMISNodeInfo parentInfo = parentInfos.get(0);
CMISNodeInfo ni = createNodeInfo(parent.getParentRef()); addNodeInfo(parentInfo);
ObjectData result = connector.createCMISObject(ni, filter, false, IncludeRelationships.NONE,
ObjectData result = connector.createCMISObject(parentInfo, filter, false, IncludeRelationships.NONE,
CMISConnector.RENDITION_NONE, false, false); CMISConnector.RENDITION_NONE, false, false);
if (context.isObjectInfoRequired()) if (context.isObjectInfoRequired())
{ {
@@ -848,11 +861,13 @@ public class AlfrescoCmisService extends AbstractCmisService
if (info.isFolder() && !info.isRootFolder()) if (info.isFolder() && !info.isRootFolder())
{ {
ChildAssociationRef parent = connector.getNodeService().getPrimaryParent(info.getNodeRef()); List<CMISNodeInfo> parentInfos = info.getParents();
if (parent != null) if (!parentInfos.isEmpty())
{ {
CMISNodeInfo ni = createNodeInfo(parent.getParentRef()); CMISNodeInfo parentInfo = parentInfos.get(0);
ObjectData object = connector.createCMISObject(ni, filter, includeAllowableActions, addNodeInfo(parentInfo);
ObjectData object = connector.createCMISObject(parentInfo, filter, includeAllowableActions,
includeRelationships, renditionFilter, false, false); includeRelationships, renditionFilter, false, false);
if (context.isObjectInfoRequired()) if (context.isObjectInfoRequired())
{ {
@@ -872,31 +887,28 @@ public class AlfrescoCmisService extends AbstractCmisService
} }
} else if (info.isCurrentVersion() || info.isPWC()) } else if (info.isCurrentVersion() || info.isPWC())
{ {
List<ChildAssociationRef> parents = connector.getNodeService().getParentAssocs(info.getNodeRef(), List<CMISNodeInfo> parentInfos = info.getParents();
ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL); for (CMISNodeInfo parentInfo : parentInfos)
if (parents != null)
{ {
for (ChildAssociationRef parent : parents) addNodeInfo(parentInfo);
ObjectData object = connector.createCMISObject(parentInfo, filter, includeAllowableActions,
includeRelationships, renditionFilter, false, false);
if (context.isObjectInfoRequired())
{ {
CMISNodeInfo ni = createNodeInfo(parent.getParentRef()); getObjectInfo(repositoryId, object.getId());
ObjectData object = connector.createCMISObject(ni, filter, includeAllowableActions,
includeRelationships, renditionFilter, false, false);
if (context.isObjectInfoRequired())
{
getObjectInfo(repositoryId, object.getId());
}
ObjectParentDataImpl objectParent = new ObjectParentDataImpl();
objectParent.setObject(object);
// include relative path segment
if (includeRelativePathSegment)
{
objectParent.setRelativePathSegment(info.getName());
}
result.add(objectParent);
} }
ObjectParentDataImpl objectParent = new ObjectParentDataImpl();
objectParent.setObject(object);
// include relative path segment
if (includeRelativePathSegment)
{
objectParent.setRelativePathSegment(info.getName());
}
result.add(objectParent);
} }
} }
@@ -1507,7 +1519,7 @@ public class AlfrescoCmisService extends AbstractCmisService
checkRepositoryId(repositoryId); checkRepositoryId(repositoryId);
// what kind of object is it? // what kind of object is it?
final CMISNodeInfoImpl info = getOrCreateNodeInfo(objectId, "Object"); final CMISNodeInfo info = getOrCreateNodeInfo(objectId, "Object");
// run transaction // run transaction
endReadOnlyTransaction(); endReadOnlyTransaction();
@@ -1559,7 +1571,7 @@ public class AlfrescoCmisService extends AbstractCmisService
} }
} else if (info.isVariant(CMISObjectVariant.VERSION)) } else if (info.isVariant(CMISObjectVariant.VERSION))
{ {
Version version = info.getVersion(); Version version = ((CMISNodeInfoImpl) info).getVersion();
connector.getVersionService().deleteVersion(nodeRef, version); connector.getVersionService().deleteVersion(nodeRef, version);
return true; return true;
} }
@@ -1757,7 +1769,7 @@ public class AlfrescoCmisService extends AbstractCmisService
checkRepositoryId(repositoryId); checkRepositoryId(repositoryId);
// what kind of object is it? // what kind of object is it?
CMISNodeInfoImpl info = getOrCreateNodeInfo(objectId, "Object"); CMISNodeInfo info = getOrCreateNodeInfo(objectId, "Object");
// relationships cannot have content // relationships cannot have content
if (info.isVariant(CMISObjectVariant.ASSOC)) if (info.isVariant(CMISObjectVariant.ASSOC))
@@ -2051,10 +2063,12 @@ public class AlfrescoCmisService extends AbstractCmisService
} }
// what kind of object is it? // what kind of object is it?
CMISNodeInfoImpl info = getOrCreateNodeInfo(versionSeriesId, "Version Series"); CMISNodeInfo info = getOrCreateNodeInfo(versionSeriesId, "Version Series");
CMISNodeInfo versionInfo = createNodeInfo(((CMISNodeInfoImpl) info).getLatestVersionNodeRef(major));
addNodeInfo(versionInfo);
return connector.createCMISObject(createNodeInfo(info.getLatestVersionNodeRef(major)), filter, return connector.createCMISObject(versionInfo, filter, includeAllowableActions, includeRelationships,
includeAllowableActions, includeRelationships, renditionFilter, includePolicyIds, includeAcl); renditionFilter, includePolicyIds, includeAcl);
} }
@Override @Override
@@ -2070,14 +2084,16 @@ public class AlfrescoCmisService extends AbstractCmisService
} }
// what kind of object is it? // what kind of object is it?
CMISNodeInfoImpl info = getOrCreateNodeInfo(versionSeriesId, "Version Series"); CMISNodeInfo info = getOrCreateNodeInfo(versionSeriesId, "Version Series");
if (info.isVariant(CMISObjectVariant.ASSOC)) if (info.isVariant(CMISObjectVariant.ASSOC))
{ {
return connector.getAssocProperties(info, filter); return connector.getAssocProperties(info, filter);
} else } else
{ {
return connector.getNodeProperties(createNodeInfo(info.getLatestVersionNodeRef(major)), filter); CMISNodeInfo versionInfo = createNodeInfo(((CMISNodeInfoImpl) info).getLatestVersionNodeRef(major));
addNodeInfo(versionInfo);
return connector.getNodeProperties(versionInfo, filter);
} }
} }
@@ -2420,6 +2436,39 @@ public class AlfrescoCmisService extends AbstractCmisService
// -------------------------------------------------------- // --------------------------------------------------------
/**
* Collects the {@link ObjectInfo} about an object.
*
* (Provided by OpenCMIS, but optimized for Alfresco.)
*/
@Override
public ObjectInfo getObjectInfo(String repositoryId, String objectId)
{
ObjectInfo info = objectInfoMap.get(objectId);
if (info == null)
{
CMISNodeInfo nodeInfo = getOrCreateNodeInfo(objectId);
// object info has not been found -> create one
try
{
// get the object and its info
ObjectData object = connector.createCMISObject(nodeInfo, null, false, IncludeRelationships.BOTH, null,
false, false);
info = getObjectInfoIntern(repositoryId, object);
// add object info
objectInfoMap.put(objectId, info);
} catch (Exception e)
{
e.printStackTrace();
info = null;
}
}
return info;
}
/** /**
* Collects the {@link ObjectInfo} about an object. * Collects the {@link ObjectInfo} about an object.
* *
@@ -2499,7 +2548,7 @@ public class AlfrescoCmisService extends AbstractCmisService
info.setFileName(null); info.setFileName(null);
// parent // parent
info.setHasParent(!connector.getRootNodeRef().equals(object.getId())); info.setHasParent(!ni.isRootFolder());
// policies and relationships // policies and relationships
info.setSupportsRelationships(true); info.setSupportsRelationships(true);
@@ -2563,7 +2612,7 @@ public class AlfrescoCmisService extends AbstractCmisService
} }
// parent // parent
info.setHasParent(true); info.setHasParent(ni.isCurrentVersion() || ni.isPWC());
// policies and relationships // policies and relationships
info.setSupportsRelationships(true); info.setSupportsRelationships(true);

View File

@@ -1018,7 +1018,7 @@ public class CMISConnector implements ApplicationContextAware, ApplicationListen
/** /**
* Gets the content from the repository. * Gets the content from the repository.
*/ */
public ContentStream getContentStream(CMISNodeInfoImpl info, String streamId, BigInteger offset, BigInteger length) public ContentStream getContentStream(CMISNodeInfo info, String streamId, BigInteger offset, BigInteger length)
{ {
// get the type and check if the object can have content // get the type and check if the object can have content
TypeDefinitionWrapper type = info.getType(); TypeDefinitionWrapper type = info.getType();

View File

@@ -19,8 +19,10 @@
package org.alfresco.opencmis; package org.alfresco.opencmis;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.alfresco.model.ContentModel; import org.alfresco.model.ContentModel;
@@ -43,6 +45,7 @@ import org.alfresco.service.cmr.version.VersionDoesNotExistException;
import org.alfresco.service.cmr.version.VersionHistory; import org.alfresco.service.cmr.version.VersionHistory;
import org.alfresco.service.cmr.version.VersionType; import org.alfresco.service.cmr.version.VersionType;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException; import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException; import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
import org.apache.chemistry.opencmis.commons.exceptions.CmisPermissionDeniedException; import org.apache.chemistry.opencmis.commons.exceptions.CmisPermissionDeniedException;
@@ -68,6 +71,7 @@ public class CMISNodeInfoImpl implements CMISNodeInfo
private Version version; private Version version;
private Boolean isLatestMajorVersion; private Boolean isLatestMajorVersion;
private Map<String, Serializable> properties; private Map<String, Serializable> properties;
private List<CMISNodeInfo> parents;
public CMISNodeInfoImpl(CMISConnector connector, String objectId) public CMISNodeInfoImpl(CMISConnector connector, String objectId)
{ {
@@ -766,4 +770,25 @@ public class CMISNodeInfoImpl implements CMISNodeInfo
{ {
return getObjectId() + " (" + getNodeRef() + ")"; return getObjectId() + " (" + getNodeRef() + ")";
} }
@Override
public List<CMISNodeInfo> getParents()
{
if (parents == null)
{
parents = new ArrayList<CMISNodeInfo>();
List<ChildAssociationRef> nodeParents = connector.getNodeService().getParentAssocs(nodeRef,
ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
if (nodeParents != null)
{
for (ChildAssociationRef parent : nodeParents)
{
parents.add(new CMISNodeInfoImpl(connector, parent.getParentRef()));
}
}
}
return parents;
}
} }

View File

@@ -18,9 +18,9 @@
*/ */
package org.alfresco.opencmis.mapping; package org.alfresco.opencmis.mapping;
import org.alfresco.opencmis.CMISConnector; import java.util.List;
import org.alfresco.opencmis.dictionary.CMISNodeInfo; import org.alfresco.opencmis.dictionary.CMISNodeInfo;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
/** /**
* Action Evaluator whose evaluation takes place on parent * Action Evaluator whose evaluation takes place on parent
@@ -30,7 +30,6 @@ import org.alfresco.service.cmr.repository.ChildAssociationRef;
public class ParentActionEvaluator extends AbstractActionEvaluator public class ParentActionEvaluator extends AbstractActionEvaluator
{ {
private AbstractActionEvaluator evaluator; private AbstractActionEvaluator evaluator;
private CMISConnector cmisConnector;
/** /**
* Construct * Construct
@@ -38,11 +37,10 @@ public class ParentActionEvaluator extends AbstractActionEvaluator
* @param serviceRegistry * @param serviceRegistry
* @param action * @param action
*/ */
protected ParentActionEvaluator(CMISConnector cmisConnector, AbstractActionEvaluator evaluator) protected ParentActionEvaluator(AbstractActionEvaluator evaluator)
{ {
super(evaluator.getServiceRegistry(), evaluator.getAction()); super(evaluator.getServiceRegistry(), evaluator.getAction());
this.evaluator = evaluator; this.evaluator = evaluator;
this.cmisConnector = cmisConnector;
} }
public boolean isAllowed(CMISNodeInfo nodeInfo) public boolean isAllowed(CMISNodeInfo nodeInfo)
@@ -52,10 +50,10 @@ public class ParentActionEvaluator extends AbstractActionEvaluator
return false; return false;
} }
ChildAssociationRef car = getServiceRegistry().getNodeService().getPrimaryParent(nodeInfo.getNodeRef()); List<CMISNodeInfo> parents = nodeInfo.getParents();
if ((car != null) && (car.getParentRef() != null)) if (!parents.isEmpty())
{ {
return evaluator.isAllowed(cmisConnector.createNodeInfo(car.getParentRef())); return evaluator.isAllowed(parents.get(0));
} }
return false; return false;

View File

@@ -19,11 +19,11 @@
package org.alfresco.opencmis.mapping; package org.alfresco.opencmis.mapping;
import java.io.Serializable; import java.io.Serializable;
import java.util.List;
import org.alfresco.opencmis.CMISConnector; import org.alfresco.opencmis.CMISConnector;
import org.alfresco.opencmis.dictionary.CMISNodeInfo; import org.alfresco.opencmis.dictionary.CMISNodeInfo;
import org.alfresco.service.ServiceRegistry; import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.apache.chemistry.opencmis.commons.PropertyIds; import org.apache.chemistry.opencmis.commons.PropertyIds;
/** /**
@@ -51,10 +51,10 @@ public class ParentProperty extends AbstractProperty
return null; return null;
} }
ChildAssociationRef car = getServiceRegistry().getNodeService().getPrimaryParent(nodeInfo.getNodeRef()); List<CMISNodeInfo> parents = nodeInfo.getParents();
if ((car != null) && (car.getParentRef() != null)) if (!parents.isEmpty())
{ {
return car.getParentRef().toString(); return parents.get(0).getObjectId();
} }
return null; return null;

View File

@@ -159,9 +159,8 @@ public class RuntimePropertyAccessorMapping implements PropertyAccessorMapping,
Action.CAN_GET_PROPERTIES, PermissionService.READ_PROPERTIES)); Action.CAN_GET_PROPERTIES, PermissionService.READ_PROPERTIES));
registerEvaluator(BaseTypeId.CMIS_DOCUMENT, new FixedValueActionEvaluator(serviceRegistry, registerEvaluator(BaseTypeId.CMIS_DOCUMENT, new FixedValueActionEvaluator(serviceRegistry,
Action.CAN_GET_OBJECT_RELATIONSHIPS, true)); Action.CAN_GET_OBJECT_RELATIONSHIPS, true));
registerEvaluator(BaseTypeId.CMIS_DOCUMENT, new ParentActionEvaluator(cmisConnector, registerEvaluator(BaseTypeId.CMIS_DOCUMENT, new ParentActionEvaluator(new PermissionActionEvaluator(
new PermissionActionEvaluator(serviceRegistry, Action.CAN_GET_OBJECT_PARENTS, serviceRegistry, Action.CAN_GET_OBJECT_PARENTS, PermissionService.READ_PERMISSIONS)));
PermissionService.READ_PERMISSIONS)));
// Is CAN_MOVE correct mapping? // Is CAN_MOVE correct mapping?
registerEvaluator(BaseTypeId.CMIS_DOCUMENT, new CurrentVersionEvaluator(serviceRegistry, registerEvaluator(BaseTypeId.CMIS_DOCUMENT, new CurrentVersionEvaluator(serviceRegistry,
new PermissionActionEvaluator(serviceRegistry, Action.CAN_MOVE_OBJECT, PermissionService.DELETE_NODE), new PermissionActionEvaluator(serviceRegistry, Action.CAN_MOVE_OBJECT, PermissionService.DELETE_NODE),
@@ -213,11 +212,10 @@ public class RuntimePropertyAccessorMapping implements PropertyAccessorMapping,
Action.CAN_GET_PROPERTIES, PermissionService.READ_PROPERTIES)); Action.CAN_GET_PROPERTIES, PermissionService.READ_PROPERTIES));
registerEvaluator(BaseTypeId.CMIS_FOLDER, new FixedValueActionEvaluator(serviceRegistry, registerEvaluator(BaseTypeId.CMIS_FOLDER, new FixedValueActionEvaluator(serviceRegistry,
Action.CAN_GET_OBJECT_RELATIONSHIPS, true)); Action.CAN_GET_OBJECT_RELATIONSHIPS, true));
registerEvaluator(BaseTypeId.CMIS_FOLDER, new ParentActionEvaluator(cmisConnector, registerEvaluator(BaseTypeId.CMIS_FOLDER, new ParentActionEvaluator(new PermissionActionEvaluator(
new PermissionActionEvaluator(serviceRegistry, Action.CAN_GET_OBJECT_PARENTS, serviceRegistry, Action.CAN_GET_OBJECT_PARENTS, PermissionService.READ_PERMISSIONS)));
PermissionService.READ_PERMISSIONS)));
registerEvaluator(BaseTypeId.CMIS_FOLDER, new RootFolderEvaluator(serviceRegistry, new ParentActionEvaluator( registerEvaluator(BaseTypeId.CMIS_FOLDER, new RootFolderEvaluator(serviceRegistry, new ParentActionEvaluator(
cmisConnector, new PermissionActionEvaluator(serviceRegistry, Action.CAN_GET_FOLDER_PARENT, new PermissionActionEvaluator(serviceRegistry, Action.CAN_GET_FOLDER_PARENT,
PermissionService.READ_PERMISSIONS)), false)); PermissionService.READ_PERMISSIONS)), false));
registerEvaluator(BaseTypeId.CMIS_FOLDER, new PermissionActionEvaluator(serviceRegistry, registerEvaluator(BaseTypeId.CMIS_FOLDER, new PermissionActionEvaluator(serviceRegistry,
Action.CAN_GET_DESCENDANTS, PermissionService.READ_CHILDREN)); Action.CAN_GET_DESCENDANTS, PermissionService.READ_CHILDREN));