mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-11-05 15:32:21 +00:00
[MNT-25404] Query Performance - High performance cost in retrieving nodes/node properties for large result sets
- pre-commit changes
This commit is contained in:
@@ -46,6 +46,7 @@ public interface DeletedNodes
|
||||
{
|
||||
/**
|
||||
* Lists deleted nodes using a ArchivedNodesCannedQuery
|
||||
*
|
||||
* @param parameters
|
||||
* @return Collection of deleted Nodes
|
||||
*/
|
||||
@@ -53,9 +54,11 @@ public interface DeletedNodes
|
||||
|
||||
/**
|
||||
* Gets a single deleted node by id.
|
||||
*
|
||||
* @param originalId
|
||||
* @param parameters
|
||||
* @param fullnode Should we return the full representation of the minimal one?
|
||||
* @param fullnode
|
||||
* Should we return the full representation of the minimal one?
|
||||
* @param mapUserInfo
|
||||
* @return a deleted node
|
||||
*/
|
||||
@@ -86,6 +89,7 @@ public interface DeletedNodes
|
||||
|
||||
/**
|
||||
* Permanently delete the node.
|
||||
*
|
||||
* @param archivedId
|
||||
*/
|
||||
void purgeArchivedNode(String archivedId);
|
||||
@@ -118,9 +122,12 @@ public interface DeletedNodes
|
||||
/**
|
||||
* Gets a presigned URL to directly access content.
|
||||
*
|
||||
* @param archivedId The node id for which to obtain the direct access {@code URL}
|
||||
* @param renditionId The rendition id for which to obtain the direct access {@code URL}
|
||||
* @param attachment {@code true} if an attachment {@code URL} is requested, {@code false} for an embedded {@code URL}, {@code true} by default.
|
||||
* @param archivedId
|
||||
* The node id for which to obtain the direct access {@code URL}
|
||||
* @param renditionId
|
||||
* The rendition id for which to obtain the direct access {@code URL}
|
||||
* @param attachment
|
||||
* {@code true} if an attachment {@code URL} is requested, {@code false} for an embedded {@code URL}, {@code true} by default.
|
||||
* @return A direct access {@code URL} object for the content.
|
||||
*/
|
||||
default DirectAccessUrl requestContentDirectUrl(String archivedId, String renditionId, boolean attachment)
|
||||
@@ -131,10 +138,14 @@ public interface DeletedNodes
|
||||
/**
|
||||
* Gets a presigned URL to directly access content.
|
||||
*
|
||||
* @param archivedId The node id for which to obtain the direct access {@code URL}
|
||||
* @param renditionId The rendition id for which to obtain the direct access {@code URL}
|
||||
* @param attachment {@code true} if an attachment {@code URL} is requested, {@code false} for an embedded {@code URL}, {@code true} by default.
|
||||
* @param validFor The time at which the direct access {@code URL} will expire.
|
||||
* @param archivedId
|
||||
* The node id for which to obtain the direct access {@code URL}
|
||||
* @param renditionId
|
||||
* The rendition id for which to obtain the direct access {@code URL}
|
||||
* @param attachment
|
||||
* {@code true} if an attachment {@code URL} is requested, {@code false} for an embedded {@code URL}, {@code true} by default.
|
||||
* @param validFor
|
||||
* The time at which the direct access {@code URL} will expire.
|
||||
* @return A direct access {@code URL} object for the content.
|
||||
*/
|
||||
DirectAccessUrl requestContentDirectUrl(String archivedId, String renditionId, boolean attachment, Long validFor);
|
||||
|
||||
@@ -31,6 +31,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.extensions.webscripts.servlet.FormData;
|
||||
|
||||
import org.alfresco.rest.api.model.AssocChild;
|
||||
import org.alfresco.rest.api.model.AssocTarget;
|
||||
import org.alfresco.rest.api.model.Document;
|
||||
@@ -48,7 +50,6 @@ import org.alfresco.service.cmr.repository.DirectAccessUrl;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.springframework.extensions.webscripts.servlet.FormData;
|
||||
|
||||
/**
|
||||
* File Folder (Nodes) API
|
||||
@@ -63,7 +64,8 @@ public interface Nodes
|
||||
/**
|
||||
* Get the node representation for the given node.
|
||||
*
|
||||
* @param nodeId String
|
||||
* @param nodeId
|
||||
* String
|
||||
* @return Node
|
||||
*/
|
||||
Node getNode(String nodeId);
|
||||
@@ -71,7 +73,8 @@ public interface Nodes
|
||||
/**
|
||||
* Get the document representation for the given node.
|
||||
*
|
||||
* @param nodeRef NodeRef
|
||||
* @param nodeRef
|
||||
* NodeRef
|
||||
* @return Document
|
||||
*/
|
||||
Document getDocument(NodeRef nodeRef);
|
||||
@@ -79,7 +82,8 @@ public interface Nodes
|
||||
/**
|
||||
* Get the folder representation for the given node.
|
||||
*
|
||||
* @param nodeRef NodeRef
|
||||
* @param nodeRef
|
||||
* NodeRef
|
||||
* @return Folder
|
||||
*/
|
||||
Folder getFolder(NodeRef nodeRef);
|
||||
@@ -87,10 +91,10 @@ public interface Nodes
|
||||
/**
|
||||
* Get the folder or document representation (as appropriate) for the given node.
|
||||
*
|
||||
* @param nodeId String nodeId or well-known alias, eg. "-root-" or "-my-"
|
||||
* @param parameters the {@link Parameters} object to get the parameters passed into the request
|
||||
* including:
|
||||
* - incPrimaryParent
|
||||
* @param nodeId
|
||||
* String nodeId or well-known alias, eg. "-root-" or "-my-"
|
||||
* @param parameters
|
||||
* the {@link Parameters} object to get the parameters passed into the request including: - incPrimaryParent
|
||||
* @return
|
||||
*/
|
||||
Node getFolderOrDocument(String nodeId, Parameters parameters);
|
||||
@@ -102,7 +106,8 @@ public interface Nodes
|
||||
/**
|
||||
* Get the folder or document representation (as appropriate) for the given node.
|
||||
*
|
||||
* @param nodeRef A real Node
|
||||
* @param nodeRef
|
||||
* A real Node
|
||||
* @param parentNodeRef
|
||||
* @param nodeTypeQName
|
||||
* @param includeParam
|
||||
@@ -121,14 +126,14 @@ public interface Nodes
|
||||
* @return
|
||||
*/
|
||||
List<Node> getFoldersOrDocuments(List<NodeRef> nodeRefs, List<String> includeParam, Map<String, UserInfo> mapUserInfo);
|
||||
|
||||
/**
|
||||
* Get list of children of a parent folder.
|
||||
*
|
||||
* @param parentFolderNodeId String id of parent folder node or well-known alias, eg. "-root-" or "-my-"
|
||||
* @param parameters the {@link Parameters} object to get the parameters passed into the request
|
||||
* including:
|
||||
* - filter, sort & paging params (where, orderBy, skipCount, maxItems)
|
||||
* - incFiles, incFolders (both true by default)
|
||||
* @param parentFolderNodeId
|
||||
* String id of parent folder node or well-known alias, eg. "-root-" or "-my-"
|
||||
* @param parameters
|
||||
* the {@link Parameters} object to get the parameters passed into the request including: - filter, sort & paging params (where, orderBy, skipCount, maxItems) - incFiles, incFolders (both true by default)
|
||||
* @return a paged list of {@code org.alfresco.rest.api.model.Node} objects
|
||||
*/
|
||||
CollectionWithPagingInfo<Node> listChildren(String parentFolderNodeId, Parameters parameters);
|
||||
@@ -136,9 +141,10 @@ public interface Nodes
|
||||
/**
|
||||
* Delete the given node. Note: will cascade delete for a folder.
|
||||
*
|
||||
* @param nodeId String id of node (folder or document)
|
||||
* @param parameters the {@link Parameters} object to get the parameters passed into the request
|
||||
* - permanent (default false)
|
||||
* @param nodeId
|
||||
* String id of node (folder or document)
|
||||
* @param parameters
|
||||
* the {@link Parameters} object to get the parameters passed into the request - permanent (default false)
|
||||
*/
|
||||
void deleteNode(String nodeId, Parameters parameters);
|
||||
|
||||
@@ -178,7 +184,8 @@ public interface Nodes
|
||||
*
|
||||
* @param fileNodeId
|
||||
* @param parameters
|
||||
* @param recordActivity true, if an activity post is required.
|
||||
* @param recordActivity
|
||||
* true, if an activity post is required.
|
||||
* @return
|
||||
*/
|
||||
BinaryResource getContent(String fileNodeId, Parameters parameters, boolean recordActivity);
|
||||
@@ -186,9 +193,11 @@ public interface Nodes
|
||||
/**
|
||||
* Download file content.
|
||||
*
|
||||
* @param nodeRef the content nodeRef
|
||||
* @param nodeRef
|
||||
* the content nodeRef
|
||||
* @param parameters
|
||||
* @param recordActivity true, if an activity post is required.
|
||||
* @param recordActivity
|
||||
* true, if an activity post is required.
|
||||
* @return
|
||||
*/
|
||||
BinaryResource getContent(NodeRef nodeRef, Parameters parameters, boolean recordActivity);
|
||||
@@ -209,18 +218,24 @@ public interface Nodes
|
||||
/**
|
||||
* Uploads file content and meta-data into the repository.
|
||||
*
|
||||
* @param parentFolderNodeId String id of parent folder node or well-known alias, eg. "-root-" or "-my-"
|
||||
* @param formData the {@link FormData}
|
||||
* @param parameters the {@link Parameters} object to get the parameters passed into the request
|
||||
* @param parentFolderNodeId
|
||||
* String id of parent folder node or well-known alias, eg. "-root-" or "-my-"
|
||||
* @param formData
|
||||
* the {@link FormData}
|
||||
* @param parameters
|
||||
* the {@link Parameters} object to get the parameters passed into the request
|
||||
* @return {@code Node} if successful
|
||||
*/
|
||||
Node upload(String parentFolderNodeId, FormData formData, Parameters parameters);
|
||||
|
||||
|
||||
NodeRef validateNode(StoreRef storeRef, String nodeId);
|
||||
|
||||
List<NodeRef> validateNodes(StoreRef storeRef, List<String> nodeIds);
|
||||
|
||||
NodeRef validateNode(String nodeId);
|
||||
|
||||
NodeRef validateNode(NodeRef nodeRef);
|
||||
|
||||
NodeRef validateOrLookupNode(String nodeId, String path);
|
||||
|
||||
boolean nodeMatches(NodeRef nodeRef, Set<QName> expectedTypes, Set<QName> excludedTypes);
|
||||
@@ -228,9 +243,12 @@ public interface Nodes
|
||||
/**
|
||||
* Determines whether the type of the given nodeRef is a sub-class of another class or not.
|
||||
*
|
||||
* @param nodeRef source nodeRef
|
||||
* @param ofClassQName the class to test against
|
||||
* @param validateNodeRef whether to validate the given source node or not
|
||||
* @param nodeRef
|
||||
* source nodeRef
|
||||
* @param ofClassQName
|
||||
* the class to test against
|
||||
* @param validateNodeRef
|
||||
* whether to validate the given source node or not
|
||||
* @return true if the type of the given nodeRef is a sub-class of another class, otherwise false
|
||||
*/
|
||||
boolean isSubClass(NodeRef nodeRef, QName ofClassQName, boolean validateNodeRef);
|
||||
@@ -238,7 +256,8 @@ public interface Nodes
|
||||
/**
|
||||
* Helper to create a QName from either a fully qualified or short-name QName string
|
||||
*
|
||||
* @param qnameStr Fully qualified or short-name QName string
|
||||
* @param qnameStr
|
||||
* Fully qualified or short-name QName string
|
||||
* @return QName
|
||||
*/
|
||||
QName createQName(String qnameStr);
|
||||
@@ -265,6 +284,7 @@ public interface Nodes
|
||||
|
||||
/**
|
||||
* Lock a node
|
||||
*
|
||||
* @param nodeId
|
||||
* @param lockInfo
|
||||
* @param parameters
|
||||
@@ -274,6 +294,7 @@ public interface Nodes
|
||||
|
||||
/**
|
||||
* Unlock a node
|
||||
*
|
||||
* @param nodeId
|
||||
* @param parameters
|
||||
* @return
|
||||
@@ -282,8 +303,11 @@ public interface Nodes
|
||||
|
||||
/**
|
||||
* Gets a presigned URL to directly access content.
|
||||
* @param nodeId The node id for which to obtain the direct access {@code URL}
|
||||
* @param attachment {@code true} if an attachment {@code URL} is requested, {@code false} for an embedded {@code URL}.
|
||||
*
|
||||
* @param nodeId
|
||||
* The node id for which to obtain the direct access {@code URL}
|
||||
* @param attachment
|
||||
* {@code true} if an attachment {@code URL} is requested, {@code false} for an embedded {@code URL}.
|
||||
* @return A direct access {@code URL} object for the content.
|
||||
*/
|
||||
default DirectAccessUrl requestContentDirectUrl(String nodeId, boolean attachment)
|
||||
@@ -293,8 +317,11 @@ public interface Nodes
|
||||
|
||||
/**
|
||||
* Gets a presigned URL to directly access content.
|
||||
* @param nodeRef The node reference for which to obtain the direct access {@code URL}
|
||||
* @param attachment {@code true} if an attachment {@code URL} is requested, {@code false} for an embedded {@code URL}.
|
||||
*
|
||||
* @param nodeRef
|
||||
* The node reference for which to obtain the direct access {@code URL}
|
||||
* @param attachment
|
||||
* {@code true} if an attachment {@code URL} is requested, {@code false} for an embedded {@code URL}.
|
||||
* @return A direct access {@code URL} object for the content.
|
||||
*/
|
||||
default DirectAccessUrl requestContentDirectUrl(NodeRef nodeRef, boolean attachment)
|
||||
@@ -304,9 +331,13 @@ public interface Nodes
|
||||
|
||||
/**
|
||||
* Gets a presigned URL to directly access content.
|
||||
* @param nodeId The node id for which to obtain the direct access {@code URL}
|
||||
* @param attachment {@code true} if an attachment {@code URL} is requested, {@code false} for an embedded {@code URL}.
|
||||
* @param validFor The time at which the direct access {@code URL} will expire.
|
||||
*
|
||||
* @param nodeId
|
||||
* The node id for which to obtain the direct access {@code URL}
|
||||
* @param attachment
|
||||
* {@code true} if an attachment {@code URL} is requested, {@code false} for an embedded {@code URL}.
|
||||
* @param validFor
|
||||
* The time at which the direct access {@code URL} will expire.
|
||||
* @return A direct access {@code URL} object for the content.
|
||||
*/
|
||||
default DirectAccessUrl requestContentDirectUrl(String nodeId, boolean attachment, Long validFor)
|
||||
@@ -316,17 +347,19 @@ public interface Nodes
|
||||
|
||||
/**
|
||||
* Gets a presigned URL to directly access content.
|
||||
* @param nodeRef The node reference for which to obtain the direct access {@code URL}
|
||||
* @param attachment {@code true} if an attachment {@code URL} is requested, {@code false} for an embedded {@code URL}.
|
||||
* @param validFor The time at which the direct access {@code URL} will expire.
|
||||
*
|
||||
* @param nodeRef
|
||||
* The node reference for which to obtain the direct access {@code URL}
|
||||
* @param attachment
|
||||
* {@code true} if an attachment {@code URL} is requested, {@code false} for an embedded {@code URL}.
|
||||
* @param validFor
|
||||
* The time at which the direct access {@code URL} will expire.
|
||||
* @return A direct access {@code URL} object for the content.
|
||||
*/
|
||||
DirectAccessUrl requestContentDirectUrl(NodeRef nodeRef, boolean attachment, Long validFor);
|
||||
|
||||
/**
|
||||
* Convert from node properties (map of QName to Serializable) retrieved from
|
||||
* the respository to a map of String to Object that can be formatted/expressed
|
||||
* as required by the API JSON response for get nodes, get person etc.
|
||||
* Convert from node properties (map of QName to Serializable) retrieved from the respository to a map of String to Object that can be formatted/expressed as required by the API JSON response for get nodes, get person etc.
|
||||
* <p>
|
||||
* Returns null if there are no properties to return, rather than an empty map.
|
||||
*
|
||||
@@ -340,8 +373,7 @@ public interface Nodes
|
||||
Map<String, Object> mapFromNodeProperties(Map<QName, Serializable> nodeProps, List<String> selectParam, Map<String, UserInfo> mapUserInfo, List<String> excludedNS, List<QName> excludedProps);
|
||||
|
||||
/**
|
||||
* Map from the JSON API format of properties (String to Object) to
|
||||
* the typical node properties map used by the repository (QName to Serializable).
|
||||
* Map from the JSON API format of properties (String to Object) to the typical node properties map used by the repository (QName to Serializable).
|
||||
*
|
||||
* @param props
|
||||
* @return
|
||||
@@ -351,15 +383,16 @@ public interface Nodes
|
||||
/**
|
||||
* Returns the path to the given nodeRef {@code nodeRefIn} or the archived nodeRef {@code archivedParentAssoc}.
|
||||
*
|
||||
* @param nodeRefIn the NodeRef
|
||||
* @param archivedParentAssoc the ChildAssociationRef of the archived NodeRef
|
||||
* @param nodeRefIn
|
||||
* the NodeRef
|
||||
* @param archivedParentAssoc
|
||||
* the ChildAssociationRef of the archived NodeRef
|
||||
* @return the path to the given node
|
||||
*/
|
||||
PathInfo lookupPathInfo(NodeRef nodeRefIn, ChildAssociationRef archivedParentAssoc);
|
||||
|
||||
/**
|
||||
* Map from a String representation of aspect names to a set
|
||||
* of QName objects, as used by the repository.
|
||||
* Map from a String representation of aspect names to a set of QName objects, as used by the repository.
|
||||
*
|
||||
* @param aspectNames
|
||||
* @return
|
||||
@@ -367,9 +400,7 @@ public interface Nodes
|
||||
Set<QName> mapToNodeAspects(List<String> aspectNames);
|
||||
|
||||
/**
|
||||
* Map from aspects (Set of QName) retrieved from the repository to a
|
||||
* map List of String required that can be formatted/expressed as required
|
||||
* by the API JSON response for get nodes, get person etc.
|
||||
* Map from aspects (Set of QName) retrieved from the repository to a map List of String required that can be formatted/expressed as required by the API JSON response for get nodes, get person etc.
|
||||
* <p>
|
||||
* Returns null if there are no aspect names to return, rather than an empty list.
|
||||
*
|
||||
@@ -381,8 +412,7 @@ public interface Nodes
|
||||
List<String> mapFromNodeAspects(Set<QName> nodeAspects, List<String> excludedNS, List<QName> excludedAspects);
|
||||
|
||||
/**
|
||||
* Add aspects to the specified NodeRef. Aspects that appear in the exclusions list
|
||||
* will be ignored.
|
||||
* Add aspects to the specified NodeRef. Aspects that appear in the exclusions list will be ignored.
|
||||
*
|
||||
* @param nodeRef
|
||||
* @param aspectNames
|
||||
@@ -391,8 +421,7 @@ public interface Nodes
|
||||
void addCustomAspects(NodeRef nodeRef, List<String> aspectNames, List<QName> exclusions);
|
||||
|
||||
/**
|
||||
* Update aspects for the specified NodeRef. An empty list will result in
|
||||
* aspects being <strong>removed</strong>.
|
||||
* Update aspects for the specified NodeRef. An empty list will result in aspects being <strong>removed</strong>.
|
||||
*
|
||||
* @param nodeRef
|
||||
* @param aspectNames
|
||||
@@ -404,7 +433,6 @@ public interface Nodes
|
||||
|
||||
void validateProperties(Map<String, Object> properties, List<String> excludedNS, List<QName> excludedProperties);
|
||||
|
||||
|
||||
/**
|
||||
* API Constants - query parameters, etc
|
||||
*/
|
||||
@@ -456,4 +484,3 @@ public interface Nodes
|
||||
String PARAM_ISPRIMARY = "isPrimary";
|
||||
String PARAM_ASSOC_TYPE = "assocType";
|
||||
}
|
||||
|
||||
|
||||
@@ -102,12 +102,14 @@ public class DeletedNodesImpl implements DeletedNodes, RecognizedParamsExtractor
|
||||
|
||||
/**
|
||||
* Sets archived information on the Node
|
||||
*
|
||||
* @param aNode
|
||||
* @param mapUserInfo
|
||||
*/
|
||||
private void mapArchiveInfo(Node aNode, Map<String, UserInfo> mapUserInfo)
|
||||
{
|
||||
if (mapUserInfo == null) {
|
||||
if (mapUserInfo == null)
|
||||
{
|
||||
mapUserInfo = new HashMap<>();
|
||||
}
|
||||
Map<QName, Serializable> nodeProps = nodeService.getProperties(aNode.getNodeRef());
|
||||
@@ -196,7 +198,8 @@ public class DeletedNodesImpl implements DeletedNodes, RecognizedParamsExtractor
|
||||
foundNode = nodes.getFolderOrDocument(archivedNodeRef, null, null, parameters.getInclude(), mapUserInfo);
|
||||
}
|
||||
|
||||
if (foundNode != null) mapArchiveInfo(foundNode,null);
|
||||
if (foundNode != null)
|
||||
mapArchiveInfo(foundNode, null);
|
||||
return foundNode;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,13 @@ import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.extensions.surf.util.Content;
|
||||
import org.springframework.extensions.webscripts.servlet.FormData;
|
||||
|
||||
import org.alfresco.model.ApplicationModel;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.model.QuickShareModel;
|
||||
@@ -164,21 +171,13 @@ import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.extensions.surf.util.Content;
|
||||
import org.springframework.extensions.webscripts.servlet.FormData;
|
||||
|
||||
/**
|
||||
* Centralises access to file/folder/node services and maps between representations.
|
||||
*
|
||||
* Note:
|
||||
* This class was originally used for returning some basic node info when listing Favourites.
|
||||
* Note: This class was originally used for returning some basic node info when listing Favourites.
|
||||
*
|
||||
* It has now been re-purposed and extended to implement the new Nodes (RESTful) API for
|
||||
* managing files & folders, as well as custom node types.
|
||||
* It has now been re-purposed and extended to implement the new Nodes (RESTful) API for managing files & folders, as well as custom node types.
|
||||
*
|
||||
* @author steveglover
|
||||
* @author janv
|
||||
@@ -319,7 +318,8 @@ public class NodesImpl implements Nodes
|
||||
this.defaultIgnoreTypesAndAspects = ignoreTypesAndAspects;
|
||||
}
|
||||
|
||||
public void setPersonLookupProperties(Set<String> personLookupProperties) {
|
||||
public void setPersonLookupProperties(Set<String> personLookupProperties)
|
||||
{
|
||||
this.defaultPersonLookupProperties = personLookupProperties;
|
||||
}
|
||||
|
||||
@@ -377,14 +377,11 @@ public class NodesImpl implements Nodes
|
||||
}
|
||||
|
||||
// list children filtering (via where clause)
|
||||
private final static Set<String> LIST_FOLDER_CHILDREN_EQUALS_QUERY_PROPERTIES =
|
||||
new HashSet<>(Arrays.asList(new String[] {PARAM_ISFOLDER, PARAM_ISFILE, PARAM_NODETYPE, PARAM_ISPRIMARY, PARAM_ASSOC_TYPE}));
|
||||
private final static Set<String> LIST_FOLDER_CHILDREN_EQUALS_QUERY_PROPERTIES = new HashSet<>(Arrays.asList(new String[]{PARAM_ISFOLDER, PARAM_ISFILE, PARAM_NODETYPE, PARAM_ISPRIMARY, PARAM_ASSOC_TYPE}));
|
||||
|
||||
/*
|
||||
* Validates that node exists.
|
||||
/* Validates that node exists.
|
||||
*
|
||||
* Note: assumes workspace://SpacesStore
|
||||
*/
|
||||
* Note: assumes workspace://SpacesStore */
|
||||
@Override
|
||||
public NodeRef validateNode(String nodeId)
|
||||
{
|
||||
@@ -466,9 +463,7 @@ public class NodesImpl implements Nodes
|
||||
return nodes;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that nodes exists and matches given expected/excluded type(s).
|
||||
*/
|
||||
/* Check that nodes exists and matches given expected/excluded type(s). */
|
||||
@Override
|
||||
public boolean nodeMatches(NodeRef nodeRef, Set<QName> expectedTypes, Set<QName> excludedTypes)
|
||||
{
|
||||
@@ -744,19 +739,7 @@ public class NodesImpl implements Nodes
|
||||
|
||||
if (!pathElements.isEmpty() && checkForCompanyHome)
|
||||
{
|
||||
/*
|
||||
if (nodeService.getRootNode(parentNodeRef.getStoreRef()).equals(parentNodeRef))
|
||||
{
|
||||
// special case
|
||||
NodeRef chNodeRef = repositoryHelper.getCompanyHome();
|
||||
String chName = (String) nodeService.getProperty(chNodeRef, ContentModel.PROP_NAME);
|
||||
if (chName.equals(pathElements.get(0)))
|
||||
{
|
||||
pathElements = pathElements.subList(1, pathElements.size());
|
||||
parentNodeRef = chNodeRef;
|
||||
}
|
||||
}
|
||||
*/
|
||||
/* if (nodeService.getRootNode(parentNodeRef.getStoreRef()).equals(parentNodeRef)) { // special case NodeRef chNodeRef = repositoryHelper.getCompanyHome(); String chName = (String) nodeService.getProperty(chNodeRef, ContentModel.PROP_NAME); if (chName.equals(pathElements.get(0))) { pathElements = pathElements.subList(1, pathElements.size()); parentNodeRef = chNodeRef; } } */
|
||||
}
|
||||
|
||||
FileInfo fileInfo = null;
|
||||
@@ -813,8 +796,7 @@ public class NodesImpl implements Nodes
|
||||
final NodeRef contextNodeRef = currentParentRef;
|
||||
// does it exist?
|
||||
// Navigation should not check permissions
|
||||
NodeRef nodeRef = AuthenticationUtil.runAs(new RunAsWork<NodeRef>()
|
||||
{
|
||||
NodeRef nodeRef = AuthenticationUtil.runAs(new RunAsWork<NodeRef>() {
|
||||
@Override
|
||||
public NodeRef doWork() throws Exception
|
||||
{
|
||||
@@ -996,7 +978,6 @@ public class NodesImpl implements Nodes
|
||||
mapPermsToOps.put(PermissionService.WRITE, OP_UPDATE);
|
||||
mapPermsToOps.put(PermissionService.CHANGE_PERMISSIONS, OP_UPDATE_PERMISSIONS);
|
||||
|
||||
|
||||
List<String> allowableOperations = new ArrayList<>(3);
|
||||
for (Entry<String, String> kv : mapPermsToOps.entrySet())
|
||||
{
|
||||
@@ -1039,7 +1020,8 @@ public class NodesImpl implements Nodes
|
||||
if (accessPerm.isSetDirectly())
|
||||
{
|
||||
setDirectlyPerms.add(nodePerm);
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
inheritedPerms.add(nodePerm);
|
||||
}
|
||||
@@ -1109,7 +1091,6 @@ public class NodesImpl implements Nodes
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Node> getFoldersOrDocuments(final List<NodeRef> nodeRefs, List<String> includeParam, Map<String, UserInfo> mapUserInfo)
|
||||
{
|
||||
@@ -1610,8 +1591,7 @@ public class NodesImpl implements Nodes
|
||||
final Map<String, UserInfo> mapUserInfo = new HashMap<>(10);
|
||||
|
||||
final List<FileInfo> page = pagingResults.getPage();
|
||||
List<Node> nodes = new AbstractList<Node>()
|
||||
{
|
||||
List<Node> nodes = new AbstractList<Node>() {
|
||||
@Override
|
||||
public Node get(int index)
|
||||
{
|
||||
@@ -1689,12 +1669,12 @@ public class NodesImpl implements Nodes
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns a List of filter properties specified by request parameters.</p>
|
||||
* <p>
|
||||
* Returns a List of filter properties specified by request parameters.
|
||||
* </p>
|
||||
*
|
||||
* @param parameters The {@link Parameters} object to get the parameters passed into the request
|
||||
* including:
|
||||
* - filter, sort & paging params (where, orderBy, skipCount, maxItems)
|
||||
* - incFiles, incFolders (both true by default)
|
||||
* @param parameters
|
||||
* The {@link Parameters} object to get the parameters passed into the request including: - filter, sort & paging params (where, orderBy, skipCount, maxItems) - incFiles, incFolders (both true by default)
|
||||
* @return The list of {@link FilterProp}. Can be null.
|
||||
*/
|
||||
protected List<FilterProp> getListChildrenFilterProps(final Parameters parameters)
|
||||
@@ -1718,14 +1698,13 @@ public class NodesImpl implements Nodes
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Returns a List of sort properties specified by the "sorting" request parameter.</p>
|
||||
* <p>
|
||||
* Returns a List of sort properties specified by the "sorting" request parameter.
|
||||
* </p>
|
||||
*
|
||||
* @param parameters The {@link Parameters} object to get the parameters passed into the request
|
||||
* including:
|
||||
* - filter, sort & paging params (where, orderBy, skipCount, maxItems)
|
||||
* - incFiles, incFolders (both true by default)
|
||||
* @return The list of <code>Pair<QName, Boolean></code> sort properties. If no sort parameters are
|
||||
* found defaults to {@link #getListChildrenSortPropsDefault() getListChildrenSortPropsDefault}.
|
||||
* @param parameters
|
||||
* The {@link Parameters} object to get the parameters passed into the request including: - filter, sort & paging params (where, orderBy, skipCount, maxItems) - incFiles, incFolders (both true by default)
|
||||
* @return The list of <code>Pair<QName, Boolean></code> sort properties. If no sort parameters are found defaults to {@link #getListChildrenSortPropsDefault() getListChildrenSortPropsDefault}.
|
||||
*/
|
||||
protected List<Pair<QName, Boolean>> getListChildrenSortProps(final Parameters parameters)
|
||||
{
|
||||
@@ -1762,8 +1741,7 @@ public class NodesImpl implements Nodes
|
||||
* Returns the default sort order.
|
||||
* </p>
|
||||
*
|
||||
* @return The list of <code>Pair<QName, Boolean></code> sort
|
||||
* properties.
|
||||
* @return The list of <code>Pair<QName, Boolean></code> sort properties.
|
||||
*/
|
||||
protected List<Pair<QName, Boolean>> getListChildrenSortPropsDefault()
|
||||
{
|
||||
@@ -1803,24 +1781,9 @@ public class NodesImpl implements Nodes
|
||||
{
|
||||
assocTypeQNames = Collections.singleton(assocTypeQName);
|
||||
}
|
||||
/*
|
||||
// TODO review - this works, but reduces from ~100 to ~96 (OOTB)
|
||||
// maybe we could post filter (rather than join) - examples: sys:children, sys:lost_found, sys:archivedLink, sys:archiveUserLink
|
||||
else
|
||||
{
|
||||
Collection<QName> qnames = dictionaryService.getAllAssociations();
|
||||
assocTypeQNames = new HashSet<>(qnames.size());
|
||||
|
||||
// remove system assoc types
|
||||
for (QName qname : qnames)
|
||||
{
|
||||
if ((!EXCLUDED_NS.contains(qname.getNamespaceURI())))
|
||||
{
|
||||
assocTypeQNames.add(qname);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
/* // TODO review - this works, but reduces from ~100 to ~96 (OOTB) // maybe we could post filter (rather than join) - examples: sys:children, sys:lost_found, sys:archivedLink, sys:archiveUserLink else { Collection<QName> qnames = dictionaryService.getAllAssociations(); assocTypeQNames = new HashSet<>(qnames.size());
|
||||
*
|
||||
* // remove system assoc types for (QName qname : qnames) { if ((!EXCLUDED_NS.contains(qname.getNamespaceURI()))) { assocTypeQNames.add(qname); } } } */
|
||||
return assocTypeQNames;
|
||||
}
|
||||
|
||||
@@ -2083,19 +2046,9 @@ public class NodesImpl implements Nodes
|
||||
validateCmObject(nodeTypeQName);
|
||||
}
|
||||
|
||||
/* RA-834: commented-out since not currently applicable for empty file
|
||||
List<ThumbnailDefinition> thumbnailDefs = null;
|
||||
String renditionsParam = parameters.getParameter(PARAM_RENDITIONS);
|
||||
if (renditionsParam != null)
|
||||
{
|
||||
if (!isContent)
|
||||
{
|
||||
throw new InvalidArgumentException("Renditions ['"+renditionsParam+"'] only apply to content types: "+parentNodeRef.getId()+","+nodeName);
|
||||
}
|
||||
|
||||
thumbnailDefs = getThumbnailDefs(renditionsParam);
|
||||
}
|
||||
*/
|
||||
/* RA-834: commented-out since not currently applicable for empty file List<ThumbnailDefinition> thumbnailDefs = null; String renditionsParam = parameters.getParameter(PARAM_RENDITIONS); if (renditionsParam != null) { if (!isContent) { throw new InvalidArgumentException("Renditions ['"+renditionsParam+"'] only apply to content types: "+parentNodeRef.getId()+","+nodeName); }
|
||||
*
|
||||
* thumbnailDefs = getThumbnailDefs(renditionsParam); } */
|
||||
|
||||
Map<QName, Serializable> props = new HashMap<>(1);
|
||||
|
||||
@@ -2180,9 +2133,7 @@ public class NodesImpl implements Nodes
|
||||
|
||||
Node newNode = getFolderOrDocument(nodeRef.getId(), parameters);
|
||||
|
||||
/* RA-834: commented-out since not currently applicable for empty file
|
||||
requestRenditions(thumbnailDefs, newNode); // note: noop for folder
|
||||
*/
|
||||
/* RA-834: commented-out since not currently applicable for empty file requestRenditions(thumbnailDefs, newNode); // note: noop for folder */
|
||||
|
||||
return newNode;
|
||||
}
|
||||
@@ -2330,7 +2281,6 @@ public class NodesImpl implements Nodes
|
||||
return assocType;
|
||||
}
|
||||
|
||||
|
||||
private NodeRef createNodeImpl(NodeRef parentNodeRef, String nodeName, QName nodeTypeQName, Map<QName, Serializable> props, QName assocTypeQName)
|
||||
{
|
||||
NodeRef newNode = null;
|
||||
@@ -2359,16 +2309,16 @@ public class NodesImpl implements Nodes
|
||||
}
|
||||
|
||||
/**
|
||||
* Posts activities based on the activity_type.
|
||||
* If the method is called with aSync=true then a TransactionListener is used post the activity
|
||||
* afterCommit. Otherwise the activity posting is done synchronously.
|
||||
* Posts activities based on the activity_type. If the method is called with aSync=true then a TransactionListener is used post the activity afterCommit. Otherwise the activity posting is done synchronously.
|
||||
*
|
||||
* @param activity_type
|
||||
* @param activityInfo
|
||||
* @param aSync
|
||||
*/
|
||||
protected void postActivity(Activity_Type activity_type, ActivityInfo activityInfo, boolean aSync)
|
||||
{
|
||||
if (activityInfo == null) return; //Nothing to do.
|
||||
if (activityInfo == null)
|
||||
return; // Nothing to do.
|
||||
|
||||
String activityType = determineActivityType(activity_type, activityInfo.getFileInfo().isFolder());
|
||||
if (activityType != null)
|
||||
@@ -2394,8 +2344,7 @@ public class NodesImpl implements Nodes
|
||||
protected ActivityInfo getActivityInfo(NodeRef parentNodeRef, NodeRef nodeRef)
|
||||
{
|
||||
// runAs system, eg. user may not have permission see one or more parents (irrespective of whether in a site context of not)
|
||||
SiteInfo siteInfo = AuthenticationUtil.runAs(new RunAsWork<SiteInfo>()
|
||||
{
|
||||
SiteInfo siteInfo = AuthenticationUtil.runAs(new RunAsWork<SiteInfo>() {
|
||||
@Override
|
||||
public SiteInfo doWork() throws Exception
|
||||
{
|
||||
@@ -2436,10 +2385,12 @@ public class NodesImpl implements Nodes
|
||||
case ADDED:
|
||||
return isFolder ? ActivityType.FOLDER_ADDED : ActivityType.FILE_ADDED;
|
||||
case UPDATED:
|
||||
if (!isFolder) return ActivityType.FILE_UPDATED;
|
||||
if (!isFolder)
|
||||
return ActivityType.FILE_UPDATED;
|
||||
break;
|
||||
case DOWNLOADED:
|
||||
if (!isFolder) return ActivityPoster.DOWNLOADED;
|
||||
if (!isFolder)
|
||||
return ActivityPoster.DOWNLOADED;
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
@@ -2473,10 +2424,8 @@ public class NodesImpl implements Nodes
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check for special case: additional node validation (pending common lower-level service support)
|
||||
* for blacklist of system nodes that should not be deleted or locked, eg. Company Home, Sites, Data Dictionary
|
||||
* Check for special case: additional node validation (pending common lower-level service support) for blacklist of system nodes that should not be deleted or locked, eg. Company Home, Sites, Data Dictionary
|
||||
*
|
||||
* @param nodeRef
|
||||
* @param type
|
||||
@@ -2536,8 +2485,7 @@ public class NodesImpl implements Nodes
|
||||
@Override
|
||||
public Node updateNode(String nodeId, Node nodeInfo, Parameters parameters)
|
||||
{
|
||||
retryingTransactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>()
|
||||
{
|
||||
retryingTransactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Void>() {
|
||||
@Override
|
||||
public Void execute() throws Throwable
|
||||
{
|
||||
@@ -2549,8 +2497,7 @@ public class NodesImpl implements Nodes
|
||||
}
|
||||
}, false, true);
|
||||
|
||||
return retryingTransactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Node>()
|
||||
{
|
||||
return retryingTransactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Node>() {
|
||||
@Override
|
||||
public Node execute() throws Throwable
|
||||
{
|
||||
@@ -3124,7 +3071,8 @@ public class NodesImpl implements Nodes
|
||||
{
|
||||
// quick/weak guess based on file extension
|
||||
writer.setMimetype(mimeType);
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
// stronger guess based on file stream
|
||||
writer.guessMimetype(fileName);
|
||||
@@ -3140,14 +3088,16 @@ public class NodesImpl implements Nodes
|
||||
try
|
||||
{
|
||||
is.reset();
|
||||
} catch (IOException ioe)
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
if (logger.isWarnEnabled())
|
||||
{
|
||||
logger.warn("Failed to reset stream after trying to guess encoding: " + ioe.getMessage());
|
||||
}
|
||||
}
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
is = stream;
|
||||
}
|
||||
@@ -3359,9 +3309,7 @@ public class NodesImpl implements Nodes
|
||||
properties = mapToNodeProperties(qnameStrProps);
|
||||
}
|
||||
|
||||
/*
|
||||
* Existing file handling
|
||||
*/
|
||||
/* Existing file handling */
|
||||
NodeRef existingFile = nodeService.getChildByName(parentNodeRef, assocTypeQName, fileName);
|
||||
if (existingFile != null)
|
||||
{
|
||||
@@ -3413,11 +3361,7 @@ public class NodesImpl implements Nodes
|
||||
throw new PermissionDeniedException(ade.getMessage());
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: Do not clean formData temp files to allow for retries. It's
|
||||
* possible for a temp file to remain if max retry attempts are
|
||||
* made, but this is rare, so leave to usual temp file cleanup.
|
||||
*/
|
||||
/* NOTE: Do not clean formData temp files to allow for retries. It's possible for a temp file to remain if max retry attempts are made, but this is rare, so leave to usual temp file cleanup. */
|
||||
}
|
||||
|
||||
private NodeRef createNewFile(NodeRef parentNodeRef, String fileName, QName nodeType, Content content, Map<QName, Serializable> props, QName assocTypeQName, Parameters params,
|
||||
@@ -3557,11 +3501,12 @@ public class NodesImpl implements Nodes
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a unique file name, if the upload component was configured to
|
||||
* find a new unique name for clashing filenames.
|
||||
* Creates a unique file name, if the upload component was configured to find a new unique name for clashing filenames.
|
||||
*
|
||||
* @param parentNodeRef the parent node
|
||||
* @param fileName the original fileName
|
||||
* @param parentNodeRef
|
||||
* the parent node
|
||||
* @param fileName
|
||||
* the original fileName
|
||||
* @return a new file name
|
||||
*/
|
||||
private String findUniqueName(NodeRef parentNodeRef, String fileName)
|
||||
@@ -3599,7 +3544,8 @@ public class NodesImpl implements Nodes
|
||||
/**
|
||||
* Helper to create a QName from either a fully qualified or short-name QName string
|
||||
*
|
||||
* @param qnameStr Fully qualified or short-name QName string
|
||||
* @param qnameStr
|
||||
* Fully qualified or short-name QName string
|
||||
* @return QName
|
||||
*/
|
||||
public QName createQName(String qnameStr)
|
||||
@@ -3631,7 +3577,8 @@ public class NodesImpl implements Nodes
|
||||
/**
|
||||
* Helper to create a QName from either a fully qualified or short-name QName string
|
||||
*
|
||||
* @param qnameStrList list of fully qualified or short-name QName string
|
||||
* @param qnameStrList
|
||||
* list of fully qualified or short-name QName string
|
||||
* @param excludedProps
|
||||
* @return a list of {@code QName} objects
|
||||
*/
|
||||
@@ -3729,6 +3676,7 @@ public class NodesImpl implements Nodes
|
||||
|
||||
/**
|
||||
* Checks if same permission is sent more than once
|
||||
*
|
||||
* @param locallySetPermissions
|
||||
* @return
|
||||
*/
|
||||
@@ -3823,63 +3771,19 @@ public class NodesImpl implements Nodes
|
||||
/**
|
||||
* @author Jamal Kaabi-Mofrad
|
||||
*/
|
||||
/*
|
||||
private static class ContentInfoWrapper implements BasicContentInfo
|
||||
{
|
||||
private String mimeType;
|
||||
private String encoding;
|
||||
|
||||
public String getEncoding()
|
||||
{
|
||||
return encoding;
|
||||
}
|
||||
|
||||
public String getMimeType()
|
||||
{
|
||||
return mimeType;
|
||||
}
|
||||
|
||||
ContentInfoWrapper(BasicContentInfo basicContentInfo)
|
||||
{
|
||||
if (basicContentInfo != null)
|
||||
{
|
||||
this.mimeType = basicContentInfo.getMimeType();
|
||||
this.encoding = basicContentInfo.getEncoding();
|
||||
}
|
||||
}
|
||||
|
||||
ContentInfoWrapper(ContentInfo contentInfo)
|
||||
{
|
||||
if (contentInfo != null)
|
||||
{
|
||||
this.mimeType = contentInfo.getMimeType();
|
||||
this.encoding = contentInfo.getEncoding();
|
||||
}
|
||||
}
|
||||
|
||||
ContentInfoWrapper(Content content)
|
||||
{
|
||||
if (content != null && StringUtils.isNotEmpty(content.getMimetype()))
|
||||
{
|
||||
try
|
||||
{
|
||||
// TODO I think it makes sense to push contentType parsing into org.springframework.extensions.webscripts.servlet.FormData
|
||||
MediaType media = MediaType.parseMediaType(content.getMimetype());
|
||||
this.mimeType = media.getType() + '/' + media.getSubtype();
|
||||
|
||||
if (media.getCharSet() != null)
|
||||
{
|
||||
this.encoding = media.getCharSet().name();
|
||||
}
|
||||
}
|
||||
catch (InvalidMediaTypeException ime)
|
||||
{
|
||||
throw new InvalidArgumentException(ime.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
/* private static class ContentInfoWrapper implements BasicContentInfo { private String mimeType; private String encoding;
|
||||
*
|
||||
* public String getEncoding() { return encoding; }
|
||||
*
|
||||
* public String getMimeType() { return mimeType; }
|
||||
*
|
||||
* ContentInfoWrapper(BasicContentInfo basicContentInfo) { if (basicContentInfo != null) { this.mimeType = basicContentInfo.getMimeType(); this.encoding = basicContentInfo.getEncoding(); } }
|
||||
*
|
||||
* ContentInfoWrapper(ContentInfo contentInfo) { if (contentInfo != null) { this.mimeType = contentInfo.getMimeType(); this.encoding = contentInfo.getEncoding(); } }
|
||||
*
|
||||
* ContentInfoWrapper(Content content) { if (content != null && StringUtils.isNotEmpty(content.getMimetype())) { try { // TODO I think it makes sense to push contentType parsing into org.springframework.extensions.webscripts.servlet.FormData MediaType media = MediaType.parseMediaType(content.getMimetype()); this.mimeType = media.getType() + '/' + media.getSubtype();
|
||||
*
|
||||
* if (media.getCharSet() != null) { this.encoding = media.getCharSet().name(); } } catch (InvalidMediaTypeException ime) { throw new InvalidArgumentException(ime.getMessage()); } } } } */
|
||||
|
||||
protected NodeService getNodeService()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user