[feature/MNT-24127-EndpointToCalculateFolderSize] Updated endpoints flow to calculate and retrieve folder size details

This commit is contained in:
mohit-singh4
2024-08-22 12:44:19 +05:30
parent 9f28594ba5
commit a9878d9514
17 changed files with 535 additions and 279 deletions

View File

@@ -0,0 +1,33 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api;
import org.alfresco.rest.api.model.NodeSizeDetails;
public interface SizeDetails
{
NodeSizeDetails calculateNodeSize(String nodeId);
}

View File

@@ -1,77 +0,0 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.impl;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.repo.action.executer.NodeSizeActionExecuter;
import org.alfresco.repo.cache.SimpleCache;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FolderSizeImpl {
private ActionService actionService;
private static final Logger LOG = LoggerFactory.getLogger(FolderSizeImpl.class);
private static final String IN_PROGRESS = "IN-PROGRESS";
private static final String STATUS = "status";
private static final String MESSAGE = "Request has been acknowledged";
public FolderSizeImpl(ActionService actionService)
{
this.actionService = actionService;
}
public Map<String, Object> executingAsynchronousFolderAction(final NodeRef nodeRef, final int defaultItems, final Map<String, Object> result, final SimpleCache<Serializable, Object> simpleCache)
{
if(simpleCache.get(nodeRef.getId()) == null)
{
executeAction(nodeRef, defaultItems, simpleCache);
}
LOG.debug("Executing NodeSizeActionExecuter from executingAsynchronousFolderAction method");
result.putIfAbsent("message",MESSAGE);
return result;
}
protected void executeAction(NodeRef nodeRef, int defaultItems, SimpleCache<Serializable, Object> simpleCache)
{
Map<String, Object> currentStatus = new HashMap<>();
currentStatus.put(STATUS,IN_PROGRESS);
Action folderSizeAction = actionService.createAction(NodeSizeActionExecuter.NAME);
folderSizeAction.setTrackStatus(true);
folderSizeAction.setExecuteAsynchronously(true);
folderSizeAction.setParameterValue(NodeSizeActionExecuter.DEFAULT_SIZE, defaultItems);
simpleCache.put(nodeRef.getId(),currentStatus);
actionService.executeAction(folderSizeAction, nodeRef, false, true);
}
}

View File

@@ -0,0 +1,180 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.impl;
import org.alfresco.repo.cache.SimpleCache;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.SizeDetails;
import org.alfresco.rest.api.model.Node;
import org.alfresco.rest.api.model.NodePermissions;
import org.alfresco.rest.api.model.NodeSizeDetails;
import org.alfresco.rest.framework.core.exceptions.InvalidNodeTypeException;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.QName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.alfresco.service.cmr.repository.NodeRef;
import java.io.Serializable;
import java.util.Map;
import java.util.HashMap;
import org.alfresco.repo.action.executer.NodeSizeDetailsActionExecutor;
public class SizeDetailsImpl implements SizeDetails
{
private static final Logger LOG = LoggerFactory.getLogger(SizeDetailsImpl.class);
private static final String IN_PROGRESS = "IN-PROGRESS";
private static final String STATUS = "status";
private static final String COMPLETED = "COMPLETED";
private static final String NOT_INITIATED = "NOT-INITIATED";
private static final String INVALID_NODEID = "Invalid parameter: value of nodeId is invalid";
private static final String FOLDER = "folder";
private Nodes nodes;
private NodeService nodeService;
private PermissionService permissionService;
private ActionService actionService;
private SimpleCache<Serializable,Object> simpleCache;
private int defaultItems;
public void setNodes(Nodes nodes)
{
this.nodes = nodes;
}
public void setPermissionService(PermissionService permissionService)
{
this.permissionService = permissionService;
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setActionService(ActionService actionService)
{
this.actionService = actionService;
}
public void setSimpleCache(SimpleCache<Serializable, Object> simpleCache)
{
this.simpleCache = simpleCache;
}
public void setDefaultItems(int defaultItems)
{
this.defaultItems = defaultItems;
}
/**
* calculateNodeSize : providing HTTP STATUS 202 which signifies REQUEST ACCEPTED.
* HTTP STATUS 200 will provide the size details response from cache.
*/
public NodeSizeDetails calculateNodeSize(final String nodeId)
{
NodeRef nodeRef = nodes.validateNode(nodeId);
QName qName = nodeService.getType(nodeRef);
validatePermissions(nodeRef, nodeId);
if(!FOLDER.equalsIgnoreCase(qName.getLocalName()))
{
throw new InvalidNodeTypeException(INVALID_NODEID);
}
if(simpleCache.get(nodeRef.getId()) == null)
{
executeAction(nodeRef, defaultItems, simpleCache);
return null;
}
LOG.debug("Executing NodeSizeActionExecuter from calculateNodeSize method");
return executorResultToSizeDetails((Map<String, Object>)simpleCache.get(nodeRef.getId()));
}
/**
* Executing Action Asynchronously.
*/
private void executeAction(NodeRef nodeRef, int defaultItems, SimpleCache<Serializable, Object> simpleCache)
{
Map<String, Object > currentStatus = new HashMap<>();
currentStatus.put(STATUS,IN_PROGRESS);
Action folderSizeAction = actionService.createAction(NodeSizeDetailsActionExecutor.NAME);
folderSizeAction.setTrackStatus(true);
folderSizeAction.setExecuteAsynchronously(true);
folderSizeAction.setParameterValue(NodeSizeDetailsActionExecutor.DEFAULT_SIZE, defaultItems);
simpleCache.put(nodeRef.getId(),currentStatus);
actionService.executeAction(folderSizeAction, nodeRef, false, true);
}
/**
* Converting action executor response to their respective model class.
*/
private NodeSizeDetails executorResultToSizeDetails(final Map<String,Object> result)
{
if (result == null)
{
return new NodeSizeDetails(NOT_INITIATED);
}
else if(result.containsKey(NodeSizeDetailsActionExecutor.EXCEPTION))
{
return new NodeSizeDetails((String) result.get(NodeSizeDetailsActionExecutor.EXCEPTION));
}
// Check for the presence of "size" key.
boolean hasSizeKey = result.containsKey("size");
if (hasSizeKey)
{
return new NodeSizeDetails((String) result.get("nodeId"), (Long) result.get("size"), (String) result.get("calculatedAt"), (Integer) result.get("numberOfFiles"), COMPLETED);
}
else
{
return new NodeSizeDetails(IN_PROGRESS);
}
}
/**
* Validating node permission [i.e. READ permission should be there ]
*/
private void validatePermissions(NodeRef nodeRef, String nodeId)
{
Node nodeInfo = nodes.getNode(nodeId);
NodePermissions nodePerms = nodeInfo.getPermissions();
// Validate permissions.
if (nodePerms != null && permissionService.hasPermission(nodeRef, PermissionService.READ) == AccessStatus.DENIED)
{
throw new AccessDeniedException("permissions.err_access_denied");
}
}
}

View File

@@ -0,0 +1,113 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.model;
public class NodeSizeDetails
{
private String nodeId;
private long size;
private String calculatedAt;
private int numberOfFiles;
private String status;
public NodeSizeDetails()
{
super();
}
public NodeSizeDetails(String status)
{
this.status = status;
}
public NodeSizeDetails(String nodeId, long size, String calculatedAt, int numberOfFiles, String status)
{
this.nodeId = nodeId;
this.size = size;
this.calculatedAt = calculatedAt;
this.numberOfFiles = numberOfFiles;
this.status = status;
}
public String getNodeId()
{
return nodeId;
}
public void setNodeId(String nodeId)
{
this.nodeId = nodeId;
}
public long getSize()
{
return size;
}
public void setSize(long size)
{
this.size = size;
}
public String getCalculatedAt()
{
return calculatedAt;
}
public void setCalculatedAt(String calculatedAt)
{
this.calculatedAt = calculatedAt;
}
public int getNumberOfFiles()
{
return numberOfFiles;
}
public void setNumberOfFiles(int numberOfFiles)
{
this.numberOfFiles = numberOfFiles;
}
public String getStatus()
{
return status;
}
public void setStatus(String status)
{
this.status = status;
}
@Override
public String toString() {
return "NodeSizeDetails{" +
"nodeId='" + nodeId + '\'' +
", size='" + size + '\'' +
", calculatedAt='" + calculatedAt + '\'' +
", numberOfFiles=" + numberOfFiles +
", status='" + status + '\'' +
'}';
}
}

View File

@@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Remote API * Alfresco Remote API
* %% * %%
* Copyright (C) 2005 - 2023 Alfresco Software Limited * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
@@ -27,46 +27,34 @@ package org.alfresco.rest.api.nodes;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import java.io.InputStream; import java.io.InputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.cache.SimpleCache;
import org.alfresco.repo.content.directurl.DirectAccessUrlDisabledException; import org.alfresco.repo.content.directurl.DirectAccessUrlDisabledException;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.rest.api.DirectAccessUrlHelper; import org.alfresco.rest.api.DirectAccessUrlHelper;
import org.alfresco.rest.api.Nodes; import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.impl.FolderSizeImpl;
import org.alfresco.rest.api.model.DirectAccessUrlRequest; import org.alfresco.rest.api.model.DirectAccessUrlRequest;
import org.alfresco.rest.api.model.LockInfo; import org.alfresco.rest.api.model.LockInfo;
import org.alfresco.rest.api.model.Node; import org.alfresco.rest.api.model.Node;
import org.alfresco.rest.api.model.NodeTarget; import org.alfresco.rest.api.model.NodeTarget;
import org.alfresco.rest.api.model.NodePermissions; import org.alfresco.rest.api.model.NodeSizeDetails;
import org.alfresco.rest.framework.BinaryProperties; import org.alfresco.rest.framework.BinaryProperties;
import org.alfresco.rest.framework.Operation; import org.alfresco.rest.framework.Operation;
import org.alfresco.rest.framework.WebApiDescription; import org.alfresco.rest.framework.WebApiDescription;
import org.alfresco.rest.framework.WebApiParam; import org.alfresco.rest.framework.WebApiParam;
import org.alfresco.rest.framework.WebApiParameters; import org.alfresco.rest.framework.WebApiParameters;
import org.alfresco.rest.api.SizeDetails;
import org.alfresco.rest.framework.core.ResourceParameter; import org.alfresco.rest.framework.core.ResourceParameter;
import org.alfresco.rest.framework.core.exceptions.DisabledServiceException; import org.alfresco.rest.framework.core.exceptions.DisabledServiceException;
import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException; import org.alfresco.rest.framework.core.exceptions.EntityNotFoundException;
import org.alfresco.rest.framework.core.exceptions.InvalidNodeTypeException;
import org.alfresco.rest.framework.resource.EntityResource; import org.alfresco.rest.framework.resource.EntityResource;
import org.alfresco.rest.framework.resource.actions.interfaces.BinaryResourceAction; import org.alfresco.rest.framework.resource.actions.interfaces.BinaryResourceAction;
import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction; import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction;
import org.alfresco.rest.framework.resource.actions.interfaces.FolderResourceAction;
import org.alfresco.rest.framework.resource.content.BasicContentInfo; import org.alfresco.rest.framework.resource.content.BasicContentInfo;
import org.alfresco.rest.framework.resource.content.BinaryResource; import org.alfresco.rest.framework.resource.content.BinaryResource;
import org.alfresco.rest.framework.resource.parameters.Parameters; import org.alfresco.rest.framework.resource.parameters.Parameters;
import org.alfresco.rest.framework.webscripts.WithResponse; import org.alfresco.rest.framework.webscripts.WithResponse;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.repository.DirectAccessUrl; import org.alfresco.service.cmr.repository.DirectAccessUrl;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ParameterCheck; import org.alfresco.util.ParameterCheck;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -84,25 +72,13 @@ import org.springframework.extensions.webscripts.Status;
@EntityResource(name="nodes", title = "Nodes") @EntityResource(name="nodes", title = "Nodes")
public class NodesEntityResource implements public class NodesEntityResource implements
EntityResourceAction.ReadById<Node>, EntityResourceAction.Delete, EntityResourceAction.Update<Node>, EntityResourceAction.ReadById<Node>, EntityResourceAction.Delete, EntityResourceAction.Update<Node>,
BinaryResourceAction.Read, BinaryResourceAction.Update<Node>, FolderResourceAction.RetrieveFolderSize<Map<String,Object>>, InitializingBean BinaryResourceAction.Read, BinaryResourceAction.Update<Node>, InitializingBean
{ {
private static final Logger LOG = LoggerFactory.getLogger(NodesEntityResource.class); private static final Logger LOG = LoggerFactory.getLogger(NodesEntityResource.class);
private static final String INVALID_NODEID = "Invalid parameter: value of nodeId is invalid";
private static final String NOT_INITIATED = "NOT-INITIATED";
private static final String STATUS = "status";
private static final String COMPLETED = "COMPLETED";
private static final String FOLDER = "folder";
private static final String EXCEPTION = "Exception";
private Nodes nodes; private Nodes nodes;
private DirectAccessUrlHelper directAccessUrlHelper; private DirectAccessUrlHelper directAccessUrlHelper;
private PermissionService permissionService;
private NodeService nodeService;
private ActionService actionService;
private SimpleCache<Serializable,Object> simpleCache;
private int defaultItems; private SizeDetails sizeDetails;
public void setNodes(Nodes nodes) public void setNodes(Nodes nodes)
{ {
@@ -114,31 +90,6 @@ public class NodesEntityResource implements
this.directAccessUrlHelper = directAccessUrlHelper; this.directAccessUrlHelper = directAccessUrlHelper;
} }
public void setPermissionService(PermissionService permissionService)
{
this.permissionService = permissionService;
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setActionService(ActionService actionService)
{
this.actionService = actionService;
}
public void setSimpleCache(SimpleCache<Serializable, Object> simpleCache)
{
this.simpleCache = simpleCache;
}
public void setDefaultItems(int defaultItems)
{
this.defaultItems = defaultItems;
}
@Override @Override
public void afterPropertiesSet() public void afterPropertiesSet()
{ {
@@ -286,34 +237,32 @@ public class NodesEntityResource implements
} }
/** /**
* Folder Size - returns size of a folder. * Folder Size - returns size details of a folder.
* *
* @param nodeId String id of folder - will also accept well-known alias, eg. -root- or -my- or -shared- * @param nodeId String id of folder - will also accept well-known alias, eg. -root- or -my- or -shared-
* Please refer to OpenAPI spec for more details ! * Please refer to OpenAPI spec for more details !
* Returns the response message i.e. Request has been acknowledged with 202 * Returns the response message i.e. Request has been acknowledged with 202
* GET/size endpoint to check if the action's status has been completed, comprising the size of the node in bytes. * Also, size-details endpoint to check if the action's status has been completed, comprising the size of the node in bytes.
* <p> * <p>
* If nodeId does not represent a folder, InvalidNodeTypeException (status 422). * If nodeId does not represent a folder, InvalidNodeTypeException (status 422).
*/ */
@Operation("calculate-folder-size") @Operation("request-size-details")
@WebApiDescription(title = "Calculating Folder Size", description = "Calculating size of a folder", successStatus = Status.STATUS_ACCEPTED) @WebApiDescription(title = "Calculating Folder Size", description = "Calculating size of a folder",successStatus = Status.STATUS_ACCEPTED)
@WebApiParameters({@WebApiParam(name = "nodeId", title = "The unique id of Execution Job", description = "A single nodeId")}) @WebApiParameters({@WebApiParam(name = "nodeId", title = "The unique id of Execution Job", description = "A single nodeId")})
public Map<String, Object> calculateFolderSize(String nodeId, Void ignore, Parameters parameters, WithResponse withResponse) public NodeSizeDetails calculateFolderSize(String nodeId, Void ignore, Parameters parameters, WithResponse withResponse)
{ {
NodeRef nodeRef = nodes.validateNode(nodeId);
QName qName = nodeService.getType(nodeRef);
Map<String, Object> result = new HashMap<>();
validatePermissions(nodeRef, nodeId);
if(!FOLDER.equalsIgnoreCase(qName.getLocalName()))
{
throw new InvalidNodeTypeException(INVALID_NODEID);
}
try try
{ {
FolderSizeImpl folderSizeImpl = new FolderSizeImpl(actionService); NodeSizeDetails nodeSizeDetails = sizeDetails.calculateNodeSize(nodeId);
return folderSizeImpl.executingAsynchronousFolderAction(nodeRef, defaultItems, result, simpleCache); if(nodeSizeDetails == null)
{
withResponse.setStatus(Status.STATUS_ACCEPTED);
}
else
{
withResponse.setStatus(Status.STATUS_OK);
}
return nodeSizeDetails;
} }
catch (Exception alfrescoRuntimeError) catch (Exception alfrescoRuntimeError)
{ {
@@ -322,64 +271,4 @@ public class NodesEntityResource implements
} }
} }
@Override
@WebApiDescription(title = "Returns Folder Node Size", description = "Returning a Folder Node Size")
@WebApiParameters({@WebApiParam(name = "nodeId", title = "The unique id of Execution Job", description = "A single nodeId")})
@BinaryProperties({"size"})
public Map<String, Object> getFolderSize(String nodeId) throws EntityNotFoundException
{
Map<String, Object> result = new HashMap<>();
try
{
LOG.debug("Retrieving OUTPUT from NodeSizeActionExecutor - NodesEntityResource:getFolderSize");
NodeRef nodeRef = nodes.validateNode(nodeId);
validatePermissions(nodeRef, nodeId);
QName qName = nodeService.getType(nodeRef);
if(!FOLDER.equalsIgnoreCase(qName.getLocalName()))
{
throw new InvalidNodeTypeException(INVALID_NODEID);
}
Map<String, Object> cachedResult = (Map<String, Object>) simpleCache.get(nodeId);
if(cachedResult != null)
{
if(cachedResult.containsKey("size"))
{
cachedResult.put(STATUS, COMPLETED);
result = cachedResult;
}
else
{
result = cachedResult;
}
}
else
{
result.put(STATUS,NOT_INITIATED);
}
return result;
}
catch (Exception ex)
{
LOG.error("Exception occurred in NodesEntityResource:getFolderSize {}", ex.getMessage());
throw ex; // Rethrow with original stack trace
}
}
/**
* Validating node permission [i.e. READ permission should be there ]
*/
private void validatePermissions(NodeRef nodeRef, String nodeId)
{
Node nodeInfo = nodes.getNode(nodeId);
NodePermissions nodePerms = nodeInfo.getPermissions();
// Validate permissions.
if (nodePerms != null && permissionService.hasPermission(nodeRef, PermissionService.READ) == AccessStatus.DENIED)
{
throw new AccessDeniedException("permissions.err_access_denied");
}
}
} }

View File

@@ -64,7 +64,6 @@ import org.alfresco.rest.framework.resource.actions.interfaces.MultiPartRelation
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceBinaryAction; import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceBinaryAction;
import org.alfresco.rest.framework.resource.actions.interfaces.ResourceAction; import org.alfresco.rest.framework.resource.actions.interfaces.ResourceAction;
import org.alfresco.rest.framework.resource.actions.interfaces.FolderResourceAction;
import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.util.Pair; import org.alfresco.util.Pair;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@@ -111,8 +110,6 @@ public class ResourceInspector
ALL_ENTITY_RESOURCE_INTERFACES.add(MultiPartResourceAction.Create.class); ALL_ENTITY_RESOURCE_INTERFACES.add(MultiPartResourceAction.Create.class);
ALL_ENTITY_RESOURCE_INTERFACES.add(FolderResourceAction.RetrieveFolderSize.class);
ALL_RELATIONSHIP_RESOURCE_INTERFACES.add(RelationshipResourceAction.Create.class); ALL_RELATIONSHIP_RESOURCE_INTERFACES.add(RelationshipResourceAction.Create.class);
ALL_RELATIONSHIP_RESOURCE_INTERFACES.add(RelationshipResourceAction.Read.class); ALL_RELATIONSHIP_RESOURCE_INTERFACES.add(RelationshipResourceAction.Read.class);
ALL_RELATIONSHIP_RESOURCE_INTERFACES.add(RelationshipResourceAction.ReadById.class); ALL_RELATIONSHIP_RESOURCE_INTERFACES.add(RelationshipResourceAction.ReadById.class);
@@ -136,7 +133,6 @@ public class ResourceInspector
ALL_PROPERTY_RESOURCE_INTERFACES.add(BinaryResourceAction.ReadWithResponse.class); ALL_PROPERTY_RESOURCE_INTERFACES.add(BinaryResourceAction.ReadWithResponse.class);
ALL_PROPERTY_RESOURCE_INTERFACES.add(BinaryResourceAction.DeleteWithResponse.class); ALL_PROPERTY_RESOURCE_INTERFACES.add(BinaryResourceAction.DeleteWithResponse.class);
ALL_PROPERTY_RESOURCE_INTERFACES.add(BinaryResourceAction.UpdateWithResponse.class); ALL_PROPERTY_RESOURCE_INTERFACES.add(BinaryResourceAction.UpdateWithResponse.class);
ALL_PROPERTY_RESOURCE_INTERFACES.add(FolderResourceAction.RetrieveFolderSize.class);
} }
/** /**
@@ -224,8 +220,6 @@ public class ResourceInspector
findOperation(RelationshipResourceBinaryAction.DeleteWithResponse.class, DELETE, helperForAddressProps); findOperation(RelationshipResourceBinaryAction.DeleteWithResponse.class, DELETE, helperForAddressProps);
findOperation(RelationshipResourceBinaryAction.UpdateWithResponse.class, PUT, helperForAddressProps); findOperation(RelationshipResourceBinaryAction.UpdateWithResponse.class, PUT, helperForAddressProps);
findOperation(FolderResourceAction.RetrieveFolderSize.class, GET, helperForAddressProps);
boolean noAuth = resource.isAnnotationPresent(WebApiNoAuth.class); boolean noAuth = resource.isAnnotationPresent(WebApiNoAuth.class);
if (noAuth) if (noAuth)
{ {

View File

@@ -36,7 +36,6 @@ import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAct
import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction.ReadById; import org.alfresco.rest.framework.resource.actions.interfaces.EntityResourceAction.ReadById;
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction; import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceAction;
import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceBinaryAction; import org.alfresco.rest.framework.resource.actions.interfaces.RelationshipResourceBinaryAction;
import org.alfresco.rest.framework.resource.actions.interfaces.FolderResourceAction;
import org.alfresco.rest.framework.resource.content.BinaryResource; import org.alfresco.rest.framework.resource.content.BinaryResource;
import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo; import org.alfresco.rest.framework.resource.parameters.CollectionWithPagingInfo;
import org.alfresco.rest.framework.resource.parameters.Params; import org.alfresco.rest.framework.resource.parameters.Params;
@@ -59,8 +58,6 @@ public class ResourceWebScriptGet extends AbstractResourceWebScript implements P
{ {
private static Log logger = LogFactory.getLog(ResourceWebScriptGet.class); private static Log logger = LogFactory.getLog(ResourceWebScriptGet.class);
private static final String GET_FOLDERSIZE = "/nodes/{id}/size";
public ResourceWebScriptGet() public ResourceWebScriptGet()
{ {
super(); super();
@@ -228,7 +225,7 @@ public class ResourceWebScriptGet extends AbstractResourceWebScript implements P
} }
} }
case RELATIONSHIP: case RELATIONSHIP:
if (StringUtils.isBlank(params.getRelationshipId()) || params.isCollectionResource()) if (StringUtils.isBlank(params.getRelationshipId()) || (params.isCollectionResource()))
{ {
// Get the collection // Get the collection
if (RelationshipResourceAction.Read.class.isAssignableFrom(resource.getResource().getClass())) if (RelationshipResourceAction.Read.class.isAssignableFrom(resource.getResource().getClass()))
@@ -282,18 +279,7 @@ public class ResourceWebScriptGet extends AbstractResourceWebScript implements P
case PROPERTY: case PROPERTY:
if (StringUtils.isNotBlank(params.getEntityId())) if (StringUtils.isNotBlank(params.getEntityId()))
{ {
if (FolderResourceAction.RetrieveFolderSize.class.isAssignableFrom(resource.getResource().getClass()) if (BinaryResourceAction.Read.class.isAssignableFrom(resource.getResource().getClass()))
&& GET_FOLDERSIZE.equals(resource.getMetaData().getUniqueId()))
{
if (resource.getMetaData().isDeleted(FolderResourceAction.RetrieveFolderSize.class))
{
throw new DeletedResourceException("(GET) "+resource.getMetaData().getUniqueId());
}
FolderResourceAction.RetrieveFolderSize getter = (FolderResourceAction.RetrieveFolderSize) resource.getResource();
Object result = getter.getFolderSize(params.getEntityId());
return result;
}
else if (BinaryResourceAction.Read.class.isAssignableFrom(resource.getResource().getClass()))
{ {
if (resource.getMetaData().isDeleted(BinaryResourceAction.Read.class)) if (resource.getMetaData().isDeleted(BinaryResourceAction.Read.class))
{ {
@@ -303,7 +289,7 @@ public class ResourceWebScriptGet extends AbstractResourceWebScript implements P
BinaryResource prop = getter.readProperty(params.getEntityId(), params); BinaryResource prop = getter.readProperty(params.getEntityId(), params);
return prop; return prop;
} }
else if (BinaryResourceAction.ReadWithResponse.class.isAssignableFrom(resource.getResource().getClass())) if (BinaryResourceAction.ReadWithResponse.class.isAssignableFrom(resource.getResource().getClass()))
{ {
if (resource.getMetaData().isDeleted(BinaryResourceAction.ReadWithResponse.class)) if (resource.getMetaData().isDeleted(BinaryResourceAction.ReadWithResponse.class))
{ {
@@ -313,7 +299,7 @@ public class ResourceWebScriptGet extends AbstractResourceWebScript implements P
BinaryResource prop = getter.readProperty(params.getEntityId(), params, withResponse); BinaryResource prop = getter.readProperty(params.getEntityId(), params, withResponse);
return prop; return prop;
} }
else if (RelationshipResourceBinaryAction.Read.class.isAssignableFrom(resource.getResource().getClass())) if (RelationshipResourceBinaryAction.Read.class.isAssignableFrom(resource.getResource().getClass()))
{ {
if (resource.getMetaData().isDeleted(RelationshipResourceBinaryAction.Read.class)) if (resource.getMetaData().isDeleted(RelationshipResourceBinaryAction.Read.class))
{ {
@@ -323,7 +309,7 @@ public class ResourceWebScriptGet extends AbstractResourceWebScript implements P
BinaryResource prop = getter.readProperty(params.getEntityId(), params.getRelationshipId(), params); BinaryResource prop = getter.readProperty(params.getEntityId(), params.getRelationshipId(), params);
return prop; return prop;
} }
else if (RelationshipResourceBinaryAction.ReadWithResponse.class.isAssignableFrom(resource.getResource().getClass())) if (RelationshipResourceBinaryAction.ReadWithResponse.class.isAssignableFrom(resource.getResource().getClass()))
{ {
if (resource.getMetaData().isDeleted(RelationshipResourceBinaryAction.ReadWithResponse.class)) if (resource.getMetaData().isDeleted(RelationshipResourceBinaryAction.ReadWithResponse.class))
{ {
@@ -333,10 +319,6 @@ public class ResourceWebScriptGet extends AbstractResourceWebScript implements P
BinaryResource prop = getter.readProperty(params.getEntityId(), params.getRelationshipId(), params, withResponse); BinaryResource prop = getter.readProperty(params.getEntityId(), params.getRelationshipId(), params, withResponse);
return prop; return prop;
} }
else
{
throw new UnsupportedResourceOperationException();
}
} }
else else
{ {
@@ -345,7 +327,7 @@ public class ResourceWebScriptGet extends AbstractResourceWebScript implements P
default: default:
throw new UnsupportedResourceOperationException("GET not supported for Actions"); throw new UnsupportedResourceOperationException("GET not supported for Actions");
} }
} }
} }

View File

@@ -996,6 +996,29 @@
</property> </property>
</bean> </bean>
<bean id="sizeDetails" class="org.alfresco.rest.api.impl.SizeDetailsImpl">
<property name="nodes" ref="nodes" />
<property name="nodeService" ref="NodeService" />
<property name="permissionService" ref="permissionService"/>
<property name="actionService" ref="ActionService"/>
<property name="simpleCache" ref="folderSizeSharedCache" />
<property name="defaultItems" value="${alfresco.restApi.calculateFolderSize.items}"/>
</bean>
<bean id="SizeDetails" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.rest.api.SizeDetails</value>
</property>
<property name="target">
<ref bean="sizeDetails" />
</property>
<property name="interceptorNames">
<list>
<idref bean="legacyExceptionInterceptor" />
</list>
</property>
</bean>
<bean class="org.alfresco.rest.api.rules.NodeRuleSettingsRelation"> <bean class="org.alfresco.rest.api.rules.NodeRuleSettingsRelation">
<property name="ruleSettings" ref="RuleSettings" /> <property name="ruleSettings" ref="RuleSettings" />
</bean> </bean>
@@ -1148,11 +1171,7 @@
<bean class="org.alfresco.rest.api.nodes.NodesEntityResource"> <bean class="org.alfresco.rest.api.nodes.NodesEntityResource">
<property name="nodes" ref="Nodes" /> <property name="nodes" ref="Nodes" />
<property name="directAccessUrlHelper" ref="directAccessUrlHelper" /> <property name="directAccessUrlHelper" ref="directAccessUrlHelper" />
<property name="permissionService" ref="permissionService"/> <property name="sizeDetails" ref="SizeDetails" />
<property name="nodeService" ref="NodeService" />
<property name="actionService" ref="ActionService"/>
<property name="simpleCache" ref="folderSizeSharedCache" />
<property name="defaultItems" value="${alfresco.restApi.calculateFolderSize.items}"/>
</bean> </bean>
<bean class="org.alfresco.rest.api.nodes.NodeCommentsRelation"> <bean class="org.alfresco.rest.api.nodes.NodeCommentsRelation">

View File

@@ -25,6 +25,7 @@
*/ */
package org.alfresco; package org.alfresco;
import org.alfresco.rest.api.tests.NodeSizeDetailsTest;
import org.alfresco.util.testing.category.DBTests; import org.alfresco.util.testing.category.DBTests;
import org.alfresco.util.testing.category.NonBuildTests; import org.alfresco.util.testing.category.NonBuildTests;
import org.junit.experimental.categories.Categories; import org.junit.experimental.categories.Categories;
@@ -76,7 +77,7 @@ import org.junit.runners.Suite;
org.alfresco.rest.api.tests.BufferedResponseTest.class, org.alfresco.rest.api.tests.BufferedResponseTest.class,
org.alfresco.rest.workflow.api.tests.DeploymentWorkflowApiTest.class, org.alfresco.rest.workflow.api.tests.DeploymentWorkflowApiTest.class,
org.alfresco.rest.workflow.api.tests.ProcessDefinitionWorkflowApiTest.class, org.alfresco.rest.workflow.api.tests.ProcessDefinitionWorkflowApiTest.class,
org.alfresco.rest.api.tests.NodeFolderSizeApiTest.class NodeSizeDetailsTest.class
}) })
public class AppContext02TestSuite public class AppContext02TestSuite
{ {

View File

@@ -2,7 +2,7 @@
* #%L * #%L
* Alfresco Repository * Alfresco Repository
* %% * %%
* Copyright (C) 2005 - 2021 Alfresco Software Limited * Copyright (C) 2005 - 2024 Alfresco Software Limited
* %% * %%
* This file is part of the Alfresco software. * This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of * If the software was purchased under a paid Alfresco license, the terms of
@@ -77,7 +77,8 @@ import org.junit.runners.Suite;
org.alfresco.repo.web.scripts.node.NodeWebScripTest.class, org.alfresco.repo.web.scripts.node.NodeWebScripTest.class,
org.alfresco.rest.api.impl.CommentsImplUnitTest.class, org.alfresco.rest.api.impl.CommentsImplUnitTest.class,
org.alfresco.rest.api.impl.DownloadsImplCheckArchiveStatusUnitTest.class, org.alfresco.rest.api.impl.DownloadsImplCheckArchiveStatusUnitTest.class,
org.alfresco.rest.api.impl.RestApiDirectUrlConfigUnitTest.class org.alfresco.rest.api.impl.RestApiDirectUrlConfigUnitTest.class,
org.alfresco.rest.api.impl.SizeDetailsImplTest.class
}) })
public class AppContext04TestSuite public class AppContext04TestSuite
{ {

View File

@@ -0,0 +1,120 @@
/*
* #%L
* Alfresco Remote API
* %%
* Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.rest.api.impl;
import org.alfresco.repo.cache.SimpleCache;
import org.alfresco.rest.api.Nodes;
import org.alfresco.rest.api.model.NodeSizeDetails;
import org.alfresco.rest.api.tests.AbstractBaseApiTest;
import org.alfresco.rest.api.tests.client.data.ContentInfo;
import org.alfresco.rest.api.tests.client.data.Document;
import org.alfresco.rest.api.tests.client.data.UserInfo;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.security.PermissionService;
import org.junit.Before;
import org.junit.Test;
import java.io.Serializable;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* Unit tests for {@link SizeDetailsImpl} class.
*
*/
public class SizeDetailsImplTest extends AbstractBaseApiTest
{
private SizeDetailsImpl sizeDetailsImpl;
private Nodes nodes;
private NodeService nodeService;
private PermissionService permissionService;
private ActionService actionService;
private SimpleCache<Serializable,Object> simpleCache;
private final int defaultItems = 1000;
@Before
public void setUp()
{
sizeDetailsImpl = new SizeDetailsImpl();
nodes = mock(Nodes.class);
nodeService = mock(NodeService.class);
permissionService = mock(PermissionService.class);
actionService = mock(ActionService.class);
simpleCache = mock(SimpleCache.class);
sizeDetailsImpl.setNodes(nodes);
sizeDetailsImpl.setNodeService(nodeService);
sizeDetailsImpl.setPermissionService(permissionService);
sizeDetailsImpl.setActionService(actionService);
sizeDetailsImpl.setSimpleCache(simpleCache);
sizeDetailsImpl.setDefaultItems(defaultItems);
}
@Test
public void calculateNodeSize() throws Exception
{
setRequestContext(user1);
UserInfo userInfo = new UserInfo(user1);
String fileName = "content.txt";
String folder0Name = "f0-testParentFolder-"+RUNID;
String parentFolder = createFolder(tDocLibNodeId, folder0Name,null).getId();
NodeRef nodeRef = new NodeRef("protocol", "identifier", parentFolder);
Document d1 = new Document();
d1.setIsFolder(false);
d1.setParentId(parentFolder);
d1.setName(fileName);
d1.setNodeType(TYPE_CM_CONTENT);
d1.setContent(createContentInfo());
d1.setCreatedByUser(userInfo);
d1.setModifiedByUser(userInfo);
when(nodes.validateNode(parentFolder)).thenReturn(nodeRef);
NodeSizeDetails nodeSizeDetails = sizeDetailsImpl.calculateNodeSize(parentFolder);
assertNull("After executing POST/request-size-details first time, it will provide null with 202 status code",nodeSizeDetails);
}
// Method to create content info
private ContentInfo createContentInfo()
{
ContentInfo ciExpected = new ContentInfo();
ciExpected.setMimeType("text/plain");
ciExpected.setMimeTypeName("Plain Text");
ciExpected.setSizeInBytes(44500L);
ciExpected.setEncoding("ISO-8859-1");
return ciExpected;
}
@Override
public String getScope() {
return "public";
}
}

View File

@@ -105,7 +105,7 @@ public abstract class AbstractBaseApiTest extends EnterpriseTestApi
private static final String URL_CHILDREN = "children"; private static final String URL_CHILDREN = "children";
private static final String URL_CONTENT = "content"; private static final String URL_CONTENT = "content";
private static final String URL_CALCULATEFOLDERSIZE = "calculate-folder-size"; private static final String URL_CALCULATEFOLDERSIZE = "request-size-details";
protected static final String TYPE_CM_FOLDER = "cm:folder"; protected static final String TYPE_CM_FOLDER = "cm:folder";
protected static final String TYPE_CM_CONTENT = "cm:content"; protected static final String TYPE_CM_CONTENT = "cm:content";

View File

@@ -27,7 +27,6 @@ package org.alfresco.rest.api.tests;
import org.alfresco.rest.api.model.NodeTarget; import org.alfresco.rest.api.model.NodeTarget;
import org.alfresco.rest.api.model.Site; import org.alfresco.rest.api.model.Site;
import org.alfresco.rest.api.nodes.NodesEntityResource;
import org.alfresco.rest.api.tests.client.HttpResponse; import org.alfresco.rest.api.tests.client.HttpResponse;
import org.alfresco.rest.api.tests.client.PublicApiClient; import org.alfresco.rest.api.tests.client.PublicApiClient;
import org.alfresco.rest.api.tests.client.data.ContentInfo; import org.alfresco.rest.api.tests.client.data.ContentInfo;
@@ -53,16 +52,18 @@ import java.util.Map;
import java.util.UUID; import java.util.UUID;
import static org.alfresco.rest.api.tests.util.RestApiUtil.toJsonAsStringNonNull; import static org.alfresco.rest.api.tests.util.RestApiUtil.toJsonAsStringNonNull;
import static org.junit.Assert.*; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
/** /**
* V1 REST API tests for Folder size * V1 REST API tests for calculating and retrieving Folder size.
*/ */
@FixMethodOrder (MethodSorters.NAME_ASCENDING) @FixMethodOrder (MethodSorters.NAME_ASCENDING)
@RunWith (JUnit4.class) @RunWith (JUnit4.class)
public class NodeFolderSizeApiTest extends AbstractBaseApiTest public class NodeSizeDetailsTest extends AbstractBaseApiTest
{ {
private static final Logger LOG = LoggerFactory.getLogger(NodeFolderSizeApiTest.class); private static final Logger LOG = LoggerFactory.getLogger(NodeSizeDetailsTest.class);
private Site userOneN1Site; private Site userOneN1Site;
private String folderId; private String folderId;
@@ -88,7 +89,7 @@ public class NodeFolderSizeApiTest extends AbstractBaseApiTest
} }
catch (Exception e) catch (Exception e)
{ {
LOG.error("Exception occured in NodeFolderSizeApiTest:addToDocumentLibrary {}", e.getMessage()); LOG.error("Exception occured in NodeSizeDetailsTest:addToDocumentLibrary {}", e.getMessage());
} }
return null; return null;
} }
@@ -109,10 +110,8 @@ public class NodeFolderSizeApiTest extends AbstractBaseApiTest
} }
/** /**
* Test case for POST/calculate-folder-size, which calculates Folder Size. * Test case for POST/request-size-details, which calculates and retrieve size of a folder.
* Test case for GET/size, which receive Folder Size. * {@literal <host>:<port>/alfresco/api/<networkId>/public/alfresco/versions/1/nodes/<nodeId>/request-size-details}
* {@literal <host>:<port>/alfresco/api/<networkId>/public/alfresco/versions/1/nodes/<nodeId>/calculate-folder-size}
* {@literal <host>:<port>/alfresco/api/<networkId>/public/alfresco/versions/1/nodes/<nodeId>/size}
*/ */
@Test @Test
public void testPostAndGetFolderSize() throws Exception public void testPostAndGetFolderSize() throws Exception
@@ -120,7 +119,7 @@ public class NodeFolderSizeApiTest extends AbstractBaseApiTest
// Prepare parameters // Prepare parameters
Map<String, String> params = new HashMap<>(); Map<String, String> params = new HashMap<>();
params.put("nodeId", folderId); params.put("nodeId", folderId);
params.put("maxItems", "100"); params.put("maxItems", "1000");
// Perform POST request // Perform POST request
HttpResponse postResponse = post(getCalculateFolderSizeUrl(folderId), toJsonAsStringNonNull(params), 202); HttpResponse postResponse = post(getCalculateFolderSizeUrl(folderId), toJsonAsStringNonNull(params), 202);
@@ -135,7 +134,7 @@ public class NodeFolderSizeApiTest extends AbstractBaseApiTest
Object document = RestApiUtil.parseRestApiEntry(postResponse.getJsonResponse(), Object.class); Object document = RestApiUtil.parseRestApiEntry(postResponse.getJsonResponse(), Object.class);
assertNotNull("Parsed document should not be null", document); assertNotNull("Parsed document should not be null", document);
HttpResponse getResponse = getSingle(NodesEntityResource.class, folderId + "/size", null, 200); HttpResponse getResponse = post(getCalculateFolderSizeUrl(folderId), toJsonAsStringNonNull(params), 200);
String getJsonResponse = String.valueOf(getResponse.getJsonResponse()); String getJsonResponse = String.valueOf(getResponse.getJsonResponse());
assertNotNull("JSON response should not be null", getJsonResponse); assertNotNull("JSON response should not be null", getJsonResponse);
@@ -192,7 +191,7 @@ public class NodeFolderSizeApiTest extends AbstractBaseApiTest
Object document = RestApiUtil.parseRestApiEntry(postResponse.getJsonResponse(), Object.class); Object document = RestApiUtil.parseRestApiEntry(postResponse.getJsonResponse(), Object.class);
assertNotNull("Parsed document should not be null", document); assertNotNull("Parsed document should not be null", document);
HttpResponse getResponse = getSingle(NodesEntityResource.class, parentFolder + "/size", null, 200); HttpResponse getResponse = post(getCalculateFolderSizeUrl(parentFolder), toJsonAsStringNonNull(params), 200);
String getJsonResponse = String.valueOf(getResponse.getJsonResponse()); String getJsonResponse = String.valueOf(getResponse.getJsonResponse());
assertNotNull("JSON response should not be null", getJsonResponse); assertNotNull("JSON response should not be null", getJsonResponse);

View File

@@ -49,20 +49,20 @@ import java.util.Map;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
/** /**
* NodeSizeActionExecuter * NodeSizeDetailsActionExecutor
* Executing Alfresco FTS Query to find size of Folder Node * Executing Alfresco FTS Query to find size of Folder Node
*/ */
public class NodeSizeActionExecuter extends ActionExecuterAbstractBase public class NodeSizeDetailsActionExecutor extends ActionExecuterAbstractBase
{ {
private static final Logger LOG = LoggerFactory.getLogger(NodeSizeActionExecuter.class); private static final Logger LOG = LoggerFactory.getLogger(NodeSizeDetailsActionExecutor.class);
/** /**
* Action constants * Action constants
*/ */
public static final String NAME = "folder-size"; public static final String NAME = "folder-size";
private static final String EXCEPTION = "Exception"; public static final String EXCEPTION = "Exception";
public static final String DEFAULT_SIZE = "default-size"; public static final String DEFAULT_SIZE = "default-size";
private static final String FIELD_FACET = "content.size"; private static final String FIELD_FACET = "content.size";
private static final String FACET_QUERY = "content.size:[0 TO "+Integer.MAX_VALUE+"] \"label\": \"large\",\"group\":\"Size\""; private static final String FACET_QUERY = "content.size:[0 TO "+Integer.MAX_VALUE+"] \"label\": \"large\",\"group\":\"Size\"";
@@ -160,13 +160,13 @@ public class NodeSizeActionExecuter extends ActionExecuterAbstractBase
} }
catch (RuntimeException runtimeException) catch (RuntimeException runtimeException)
{ {
LOG.error("Exception occurred in NodeSizeActionExecutor:results {}", runtimeException.getMessage()); LOG.error("Exception occurred in NodeSizeDetailsActionExecutor:results {}", runtimeException.getMessage());
response.put(EXCEPTION,runtimeException.getMessage()); response.put(EXCEPTION,runtimeException.getMessage());
simpleCache.put(nodeRef.getId(),response); simpleCache.put(nodeRef.getId(),response);
throw runtimeException; throw runtimeException;
} }
LOG.debug(" Calculating size of Folder Node - NodeSizeActionExecutor:executeImpl "); LOG.debug(" Calculating size of Folder Node - NodeSizeDetailsActionExecutor:executeImpl ");
final LocalDateTime eventTimestamp = LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault()); final LocalDateTime eventTimestamp = LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault());
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy:MM:dd HH:mm:ss"); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy:MM:dd HH:mm:ss");
String formattedTimestamp = eventTimestamp.format(formatter); String formattedTimestamp = eventTimestamp.format(formatter);
@@ -174,6 +174,7 @@ public class NodeSizeActionExecuter extends ActionExecuterAbstractBase
response.put("size", totalSizeFromFacet); response.put("size", totalSizeFromFacet);
response.put("calculatedAt", formattedTimestamp); response.put("calculatedAt", formattedTimestamp);
response.put("numberOfFiles", results != null ? results.getNodeRefs().size() : 0); response.put("numberOfFiles", results != null ? results.getNodeRefs().size() : 0);
if(isCalculationCompleted) if(isCalculationCompleted)
{ {
simpleCache.put(nodeRef.getId(),response); simpleCache.put(nodeRef.getId(),response);

View File

@@ -789,7 +789,7 @@
</property> </property>
</bean> </bean>
<bean id="folder-size" class="org.alfresco.repo.action.executer.NodeSizeActionExecuter" parent="action-executer"> <bean id="folder-size" class="org.alfresco.repo.action.executer.NodeSizeDetailsActionExecutor" parent="action-executer">
<property name="searchService" ref="searchService"/> <property name="searchService" ref="searchService"/>
<property name="simpleCache" ref="folderSizeSharedCache" /> <property name="simpleCache" ref="folderSizeSharedCache" />
</bean> </bean>

View File

@@ -25,6 +25,7 @@
*/ */
package org.alfresco; package org.alfresco;
import org.alfresco.repo.action.executer.NodeSizeDetailsActionExecutorTest;
import org.alfresco.util.testing.category.DBTests; import org.alfresco.util.testing.category.DBTests;
import org.alfresco.util.testing.category.NonBuildTests; import org.alfresco.util.testing.category.NonBuildTests;
import org.junit.experimental.categories.Categories; import org.junit.experimental.categories.Categories;
@@ -78,7 +79,7 @@ import org.junit.runners.Suite;
org.alfresco.repo.activities.SiteActivityTestCaseInsensitivity.class, org.alfresco.repo.activities.SiteActivityTestCaseInsensitivity.class,
org.alfresco.repo.admin.registry.RegistryServiceImplTest.class, org.alfresco.repo.admin.registry.RegistryServiceImplTest.class,
org.alfresco.repo.bootstrap.DataDictionaryFolderTest.class, org.alfresco.repo.bootstrap.DataDictionaryFolderTest.class,
org.alfresco.repo.action.executer.NodeSizeActionExecuterTest.class NodeSizeDetailsActionExecutorTest.class
}) })
public class AppContext01TestSuite public class AppContext01TestSuite
{ {

View File

@@ -43,7 +43,7 @@ import org.junit.Test;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@Transactional @Transactional
public class NodeSizeActionExecuterTest extends BaseSpringTest public class NodeSizeDetailsActionExecutorTest extends BaseSpringTest
{ {
/** /**
* The test node reference * The test node reference
@@ -53,7 +53,7 @@ public class NodeSizeActionExecuterTest extends BaseSpringTest
/** /**
* The folder Size executer * The folder Size executer
*/ */
private NodeSizeActionExecuter executer; private NodeSizeDetailsActionExecutor executer;
/** /**
* Id used to identify the test action created * Id used to identify the test action created
@@ -93,7 +93,7 @@ public class NodeSizeActionExecuterTest extends BaseSpringTest
ContentModel.TYPE_CONTENT).getChildRef(); ContentModel.TYPE_CONTENT).getChildRef();
// Get the executer instance. // Get the executer instance.
this.executer = (NodeSizeActionExecuter)this.applicationContext.getBean(NodeSizeActionExecuter.NAME); this.executer = (NodeSizeDetailsActionExecutor)this.applicationContext.getBean(NodeSizeDetailsActionExecutor.NAME);
simpleCache = (SimpleCache<Serializable, Object>) this.applicationContext.getBean("folderSizeSharedCache"); simpleCache = (SimpleCache<Serializable, Object>) this.applicationContext.getBean("folderSizeSharedCache");
} }
@@ -104,9 +104,9 @@ public class NodeSizeActionExecuterTest extends BaseSpringTest
@Test @Test
public void testExecution() public void testExecution()
{ {
int maxItems = 100; int maxItems = 1000;
ActionImpl action = new ActionImpl(null, ID, NodeSizeActionExecuter.NAME, null); ActionImpl action = new ActionImpl(null, ID, NodeSizeDetailsActionExecutor.NAME, null);
action.setParameterValue(NodeSizeActionExecuter.DEFAULT_SIZE, maxItems); action.setParameterValue(NodeSizeDetailsActionExecutor.DEFAULT_SIZE, maxItems);
this.executer.executeImpl(action, this.nodeRef); this.executer.executeImpl(action, this.nodeRef);
Object resultAction = simpleCache.get(this.nodeRef.getId()); Object resultAction = simpleCache.get(this.nodeRef.getId());
Map<String, Object> mapResult = (Map<String, Object>)resultAction; Map<String, Object> mapResult = (Map<String, Object>)resultAction;