mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-06-30 18:15:39 +00:00
40238: CLOUD-37 - Initial Commit to test Merged BRANCHES/DEV/AMILLER/CLOUD1_SPRINT1 to BRANCHES/DEV/CLOUD1_SPRINT1: 40077: CLOUD-37: Initial commit. 40101: CLOUD-37: Fix build error. 40114: CLOUD-37: Fix path names and missing files. 40122: CLOUD-37: Initial drop of UI code for investigation of progress issues 40124: CLOUD-37: A couple of minor UI tweaks (set icon and hide panel before archive download) 40125: CLOUD-37: Download files and folders as zip 40134: CLOUD-37: Updates to UI (javascript doc, CSS tweaks, intervals for requests, labels, etc). 40143: CLOUD-37: Error messages for failures, more JavaScript doc, archive naming, code tidy 40157: CLOUD-37 - Download files and folders as zip 40202: CLOUD-37: UI tweaks following UX review 40217: CLOUD-37: Add file count to status reports. 40222: CLOUD-37: Added information to download dialog to report on the number of files added to the zip 40240: CLOUD-37: Remove extraneous file, breaking build 40513: CLOUD-37: Add Action Service Metrics Merged BRANCHES/DEV/AMILLER/CLOUD1_SPRINT1 to BRANCHES/DEV/CLOUD1_SPRINT1: 40260: CLOUD-37: Add action service metrics 40309: CLOUD-37: Fix JMX configuration, pointing at renamed class. 40514: CLOUD-37: Enable the execution of the zip creation process on a remote transformation node Merged BRANCHES/DEV/AMILLER/CLOUD1_SPRINT1 to BRANCHES/DEV/CLOUD1_SPRINT1: 40369: CLOUD-37: Enable the execution of the zip creation process on a remote transformation node 40516: CLOUD-37: Implement clean up job. Merged BRANCHES/DEV/AMILLER/CLOUD1_SPRINT1 to BRANCHES/DEV/CLOUD1_SPRINT1: 40462: CLOUD-37: Implement clean up job. 40517: CLOUD-505: Add entries for folders. Merged BRANCHES/DEV/AMILLER/CLOUD1_SPRINT1 to BRANCHES/DEV/CLOUD1_SPRINT1: 40493: CLOUD-505: Add entries for folders. 40547: CLOUD-37: Fix broken test 40595: CLOUD-518: Add working copy/locked file filtering 40642: CLOUD-508: Prevent problems occurring when cancelling and restarting the same download 40643: CLOUD-507: When a single item is selected for download it the item name gets used for the archive name 41442: CLOUD-590: Limit the total size of the content which can be downloaded. This can be set via the property, download.maxContentSize. The default is 2GB. 41472: CLOUD-589: Added cancelled flag to download type and added checks in Zip creation action to act upon the setting of this flag. Also added webscript for canceling the download. 41692: Adds support to Alfresco.util.formatFileSize for file sizes with commas (as needed by zip download) 41693: Zip Download enhancements: CLOUD-590: Notifies the user when they've exceeded the maximum file size limit. CLOUD-626: Better handling when there are errors during zipping. (WIP) 41713: Zip Download Updates: CLOUD-589: A cancel download UI action now triggers a delete of the archive on the server. CLOUD-626: The UI now triggers a full download cancel (with node delete) in event of an error. 41737: Updates Alfresco.util.formatFileSize to support an optional decimal places param. (For CLOUD-685) 41739: CLOUD-685: Display total file size of files for download to two decimal places when there is an error. 41832: Fixes: CLOUD-704: new CANCELLED status is now handled correctly. 41887: CLOUD-686: Updated maximum download content size to 2152852358 bytes (2.005GB) 41965: CLOUD-703: Upload content now runs as system user, and Quota Service returns unlimited quota for system user. 42025: CLOUD-703: Fix test failures and ensure S3 content store works in the clustered and non-clustered environments git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@42146 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
256 lines
9.7 KiB
Java
256 lines
9.7 KiB
Java
/*
|
|
* Copyright 2005-2012 Alfresco Software, Ltd. All rights reserved.
|
|
*
|
|
* License rights for this program may be obtained from Alfresco Software, Ltd.
|
|
* pursuant to a written agreement and any use of this program without such an
|
|
* agreement is prohibited.
|
|
*/
|
|
package org.alfresco.repo.download;
|
|
|
|
import java.io.Serializable;
|
|
import java.util.Collections;
|
|
import java.util.Date;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
import org.alfresco.model.ContentModel;
|
|
import org.alfresco.query.CannedQueryFactory;
|
|
import org.alfresco.query.CannedQueryResults;
|
|
import org.alfresco.repo.download.cannedquery.DownloadEntity;
|
|
import org.alfresco.repo.download.cannedquery.GetDownloadsCannedQuery;
|
|
import org.alfresco.repo.download.cannedquery.GetDownloadsCannedQueryFactory;
|
|
import org.alfresco.repo.importer.ImporterBootstrap;
|
|
import org.alfresco.repo.model.Repository;
|
|
import org.alfresco.repo.node.SystemNodeUtils;
|
|
import org.alfresco.service.cmr.download.DownloadRequest;
|
|
import org.alfresco.service.cmr.download.DownloadStatus;
|
|
import org.alfresco.service.cmr.repository.AssociationRef;
|
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
|
import org.alfresco.service.cmr.repository.NodeRef;
|
|
import org.alfresco.service.cmr.repository.NodeService;
|
|
import org.alfresco.service.namespace.NamespaceService;
|
|
import org.alfresco.service.namespace.QName;
|
|
import org.alfresco.util.registry.NamedObjectRegistry;
|
|
import org.apache.commons.logging.Log;
|
|
import org.apache.commons.logging.LogFactory;
|
|
|
|
/**
|
|
* This class is responsible for the persistence of {@link DownloadDefinition} objects using lower-level
|
|
* repo services such as the {@link NodeService}. The higher-level business logic around these CRUD calls
|
|
* is contained within the {@link DownloadServiceImpl}.
|
|
*
|
|
* @author Alex Miller
|
|
*/
|
|
public class DownloadStorage
|
|
{
|
|
private static final Log log = LogFactory.getLog(DownloadStorage.class);
|
|
|
|
// service dependencies
|
|
private ImporterBootstrap bootstrap;
|
|
private Repository repositoryHelper;
|
|
private NodeService nodeService;
|
|
private NamespaceService namespaceService;
|
|
private NamedObjectRegistry<CannedQueryFactory<? extends Object>> queryRegistry;
|
|
|
|
public void setImporterBootstrap(ImporterBootstrap bootstrap)
|
|
{
|
|
this.bootstrap = bootstrap;
|
|
}
|
|
|
|
public void setQueryRegistry(NamedObjectRegistry<CannedQueryFactory<? extends Object>> queryRegistry)
|
|
{
|
|
this.queryRegistry = queryRegistry;
|
|
}
|
|
|
|
public void setRepositoryHelper(Repository repositoryHelper)
|
|
{
|
|
this.repositoryHelper = repositoryHelper;
|
|
}
|
|
|
|
public void setNodeService(NodeService nodeService)
|
|
{
|
|
this.nodeService = nodeService;
|
|
}
|
|
|
|
public void setNamespaceService(NamespaceService namespaceService)
|
|
{
|
|
this.namespaceService = namespaceService;
|
|
}
|
|
|
|
/**
|
|
* This method finds the SyncSet Definition Container NodeRef, creating one if it does not exist.
|
|
*
|
|
* @return the syncset definition container
|
|
*/
|
|
public NodeRef getOrCreateDowloadContainer()
|
|
{
|
|
NodeRef downloadsContainer = getContainer();
|
|
|
|
if (downloadsContainer == null)
|
|
{
|
|
if (log.isInfoEnabled())
|
|
log.info("Lazy creating the Downloads System Container ");
|
|
|
|
downloadsContainer = SystemNodeUtils.getOrCreateSystemChildContainer(getContainerQName(), nodeService, repositoryHelper).getFirst();
|
|
}
|
|
return downloadsContainer;
|
|
}
|
|
|
|
private NodeRef getContainer()
|
|
{
|
|
return SystemNodeUtils.getSystemChildContainer(getContainerQName(), nodeService, repositoryHelper);
|
|
}
|
|
|
|
private QName getContainerQName()
|
|
{
|
|
String name = bootstrap.getConfiguration().getProperty("system.downloads_container.childname");
|
|
QName container = QName.createQName(name, namespaceService);
|
|
return container;
|
|
}
|
|
|
|
|
|
public NodeRef createDownloadNode(boolean recursive)
|
|
{
|
|
NodeRef downloadsContainer = getOrCreateDowloadContainer();
|
|
|
|
Map<QName, Serializable> downloadProperties = new HashMap<QName, Serializable>();
|
|
downloadProperties.put(DownloadModel.PROP_RECURSIVE, recursive);
|
|
|
|
ChildAssociationRef newChildAssoc = nodeService.createNode(downloadsContainer,
|
|
ContentModel.ASSOC_CHILDREN, ContentModel.ASSOC_CHILDREN,
|
|
DownloadModel.TYPE_DOWNLOAD,
|
|
downloadProperties);
|
|
|
|
final NodeRef downloadNodeRef = newChildAssoc.getChildRef();
|
|
|
|
if (log.isDebugEnabled())
|
|
{
|
|
StringBuilder msg = new StringBuilder();
|
|
msg.append("Created Download. ")
|
|
.append("', Download-NodeRef=");
|
|
log.debug(msg.toString());
|
|
}
|
|
return downloadNodeRef;
|
|
}
|
|
|
|
public void cancelDownload(NodeRef downloadNodeRef)
|
|
{
|
|
validateNode(downloadNodeRef);
|
|
|
|
nodeService.setProperty(downloadNodeRef, DownloadModel.PROP_CANCELLED, true);
|
|
}
|
|
|
|
public boolean isCancelled(NodeRef downloadNodeRef)
|
|
{
|
|
validateNode(downloadNodeRef);
|
|
|
|
return (Boolean)nodeService.getProperty(downloadNodeRef, DownloadModel.PROP_CANCELLED);
|
|
}
|
|
|
|
public void addNodeToDownload(NodeRef downloadNode, NodeRef nodeToAdd)
|
|
{
|
|
nodeService.createAssociation(downloadNode, nodeToAdd, DownloadModel.ASSOC_REQUESTED_NODES);
|
|
|
|
if (log.isDebugEnabled())
|
|
{
|
|
StringBuilder msg = new StringBuilder();
|
|
msg.append("Node added to Download-NodeRef '")
|
|
.append(downloadNode).append("'. RequestedNode=")
|
|
.append(nodeToAdd);
|
|
log.debug(msg.toString());
|
|
}
|
|
|
|
}
|
|
|
|
public DownloadRequest getDownloadRequest(NodeRef downloadNodeRef)
|
|
{
|
|
validateNode(downloadNodeRef);
|
|
Map<QName, Serializable> properties = nodeService.getProperties(downloadNodeRef);
|
|
|
|
List<AssociationRef> requestedNodes = nodeService.getTargetAssocs(downloadNodeRef, DownloadModel.ASSOC_REQUESTED_NODES);
|
|
|
|
return new DownloadRequest((Boolean)properties.get(DownloadModel.PROP_RECURSIVE), requestedNodes, (String)properties.get(ContentModel.PROP_CREATOR));
|
|
}
|
|
|
|
private void validateNode(NodeRef downloadNodeRef)
|
|
{
|
|
if (nodeService.getType(downloadNodeRef).equals(DownloadModel.TYPE_DOWNLOAD) == false)
|
|
{
|
|
throw new IllegalArgumentException("Invlaid node type for nodeRef:-" + downloadNodeRef);
|
|
}
|
|
}
|
|
|
|
public DownloadStatus getDownloadStatus(NodeRef downloadNodeRef)
|
|
{
|
|
validateNode(downloadNodeRef);
|
|
Map<QName, Serializable> properties = nodeService.getProperties(downloadNodeRef);
|
|
|
|
Long done = (Long)properties.get(DownloadModel.PROP_DONE);
|
|
Long total = (Long)properties.get(DownloadModel.PROP_TOTAL);
|
|
Long filesAdded = (Long)properties.get(DownloadModel.PROP_FILES_ADDED);
|
|
Long totalFiles = (Long)properties.get(DownloadModel.PROP_TOTAL_FILES);
|
|
|
|
return new DownloadStatus(DownloadStatus.Status.valueOf((String)properties.get(DownloadModel.PROP_STATUS)),
|
|
done != null ? done.longValue() : 0l,
|
|
total != null ? total.longValue() : 0l,
|
|
filesAdded != null ? filesAdded.longValue() : 0l,
|
|
totalFiles != null ? totalFiles.longValue() : 0l);
|
|
}
|
|
|
|
public int getSequenceNumber(NodeRef nodeRef)
|
|
{
|
|
validateNode(nodeRef);
|
|
Serializable sequenceNumber = nodeService.getProperty(nodeRef, DownloadModel.PROP_SEQUENCE_NUMBER);
|
|
|
|
return ((Integer)sequenceNumber).intValue();
|
|
}
|
|
|
|
public void updateStatus(NodeRef nodeRef, DownloadStatus status)
|
|
{
|
|
validateNode(nodeRef);
|
|
|
|
nodeService.setProperty(nodeRef, DownloadModel.PROP_STATUS, status.getStatus().toString());
|
|
nodeService.setProperty(nodeRef, DownloadModel.PROP_DONE, new Long(status.getDone()));
|
|
nodeService.setProperty(nodeRef, DownloadModel.PROP_TOTAL, new Long(status.getTotal()));
|
|
nodeService.setProperty(nodeRef, DownloadModel.PROP_FILES_ADDED, status.getFilesAdded());
|
|
nodeService.setProperty(nodeRef, DownloadModel.PROP_TOTAL_FILES, status.getTotalFiles());
|
|
}
|
|
|
|
/**
|
|
* Get all the downloads created before before.
|
|
*/
|
|
public List<List<DownloadEntity>> getDownloadsCreatedBefore(Date before)
|
|
{
|
|
NodeRef container = getContainer();
|
|
|
|
if (container == null)
|
|
{
|
|
return Collections.emptyList();
|
|
}
|
|
|
|
// Grab the factory
|
|
GetDownloadsCannedQueryFactory getDownloadCannedQueryFactory =
|
|
(GetDownloadsCannedQueryFactory)queryRegistry.getNamedObject("downloadGetDownloadsCannedQueryFactory");
|
|
|
|
// Run the canned query
|
|
GetDownloadsCannedQuery cq = (GetDownloadsCannedQuery)getDownloadCannedQueryFactory.getDownloadsCannedQuery(container, before);
|
|
|
|
// Execute the canned query
|
|
CannedQueryResults<DownloadEntity> results = cq.execute();
|
|
|
|
return results.getPages();
|
|
}
|
|
|
|
/**
|
|
* Delete the download node identified by nodeRef
|
|
* @param nodeRef
|
|
*/
|
|
public void delete(NodeRef nodeRef)
|
|
{
|
|
validateNode(nodeRef);
|
|
|
|
nodeService.deleteNode(nodeRef);
|
|
}
|
|
}
|