mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged DEV to HEAD
- ALF-8806 RINF 41: Lucene Removal: Fix CopyService - ALF-9028: RINF 41: Fix Aspect cm:copiedFrom - ALF-9029 RINF 49: Lucene Removal: CheckOutCheckInService API - ALF-9032: RINF 49: fixes to cm:workingcopy aspect 28996: Dev branch for De-Lucene work pending patches 29004: Evaluator runs in read-only txn 29006: Additional PermissionCheckedCollection.create method - Use an existing collection's permission check data (cut-off, etc) to wrap a new collection 29007: CopyService and CheckOutCheckInService refactors to remove Lucene CopyService: Removed cm:source property from cm:copiedfrom aspect and replaced with a cm:original association. Added CQ-based APIs to query for copies Added APIs to support bi-directional walking of copy association Fixed sundry uses of cm:copiedfrom esp. all uses related to cm:workingcopy CheckOutCheckInService: Check-out now creates a source aspect cm:checkedOut with 1:1 relationship to cm:workingcopy via cm:workingcopylink Removed explicit use of cm:workingcopy aspect and replaced it with calls to COCI API 29083: Audit tests fail when indexing is turned off. Also removed a getReader() call during rule evaluation, leading to a 'sub-action' read being recorded. 29113: NodeDAO.getNodesWithAspects supports paging 29135: Removed unused patch queries 29139: Basic patch (still terminates with error) to upgrade cm:copiedfrom and cm:workingcopy 29157: Tested patch for cm:copiedfrom and cm:workingcopy aspects git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@29159 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -32,7 +32,6 @@ import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.CannedQuery;
|
||||
import org.alfresco.query.CannedQueryFactory;
|
||||
import org.alfresco.query.CannedQueryPageDetails;
|
||||
import org.alfresco.query.CannedQueryParameters;
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.query.PagingResults;
|
||||
@@ -43,6 +42,7 @@ import org.alfresco.repo.copy.CopyBehaviourCallback.ChildAssocCopyAction;
|
||||
import org.alfresco.repo.copy.CopyBehaviourCallback.ChildAssocRecurseAction;
|
||||
import org.alfresco.repo.copy.CopyBehaviourCallback.CopyAssociationDetails;
|
||||
import org.alfresco.repo.copy.CopyBehaviourCallback.CopyChildAssociationDetails;
|
||||
import org.alfresco.repo.copy.query.AbstractCopyCannedQueryFactory;
|
||||
import org.alfresco.repo.policy.ClassPolicyDelegate;
|
||||
import org.alfresco.repo.policy.JavaBehaviour;
|
||||
import org.alfresco.repo.policy.PolicyComponent;
|
||||
@@ -61,8 +61,6 @@ import org.alfresco.service.cmr.repository.CopyServiceException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.rule.RuleService;
|
||||
import org.alfresco.service.cmr.search.ResultSet;
|
||||
import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.alfresco.service.cmr.security.AccessPermission;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
@@ -90,7 +88,6 @@ public class CopyServiceImpl implements CopyService
|
||||
|
||||
/* Query names */
|
||||
private static final String QUERY_FACTORY_GET_COPIES = "getCopiesCannedQueryFactory";
|
||||
private static final String QUERY_FACTORY_GET_COPIED = "getCopiesCannedQueryFactory";
|
||||
|
||||
/* I18N labels */
|
||||
private static final String COPY_OF_LABEL = "copy_service.copy_of_label";
|
||||
@@ -100,7 +97,6 @@ public class CopyServiceImpl implements CopyService
|
||||
private NodeService internalNodeService;
|
||||
private NamedObjectRegistry<CannedQueryFactory<CopyInfo>> cannedQueryRegistry;
|
||||
private DictionaryService dictionaryService;
|
||||
private SearchService searchService;
|
||||
private PolicyComponent policyComponent;
|
||||
private RuleService ruleService;
|
||||
private PermissionService permissionService;
|
||||
@@ -148,14 +144,6 @@ public class CopyServiceImpl implements CopyService
|
||||
this.policyComponent = policyComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param searchService the search service
|
||||
*/
|
||||
public void setSearchService(SearchService searchService)
|
||||
{
|
||||
this.searchService = searchService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ruleService the rule service
|
||||
*/
|
||||
@@ -192,15 +180,15 @@ public class CopyServiceImpl implements CopyService
|
||||
|
||||
// Register policy behaviours
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "getCopyCallback"),
|
||||
CopyServicePolicies.OnCopyNodePolicy.QNAME,
|
||||
ContentModel.ASPECT_COPIEDFROM,
|
||||
new JavaBehaviour(this, "getCallbackForCopiedFromAspect"));
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "getCopyCallback"),
|
||||
CopyServicePolicies.OnCopyNodePolicy.QNAME,
|
||||
ContentModel.TYPE_FOLDER,
|
||||
new JavaBehaviour(this, "getCallbackForFolderType"));
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
QName.createQName(NamespaceService.ALFRESCO_URI, "getCopyCallback"),
|
||||
CopyServicePolicies.OnCopyNodePolicy.QNAME,
|
||||
ContentModel.ASPECT_OWNABLE,
|
||||
new JavaBehaviour(this, "getCallbackForOwnableAspect"));
|
||||
}
|
||||
@@ -376,34 +364,40 @@ public class CopyServiceImpl implements CopyService
|
||||
invokeCopyComplete(sourceNodeRef, targetNodeRef, false, copiedNodeRefs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeRef getOriginal(NodeRef nodeRef)
|
||||
{
|
||||
List<AssociationRef> assocs = internalNodeService.getTargetAssocs(nodeRef, ContentModel.ASSOC_ORIGINAL);
|
||||
if (assocs.size() > 1)
|
||||
{
|
||||
logger.warn("Multiple cm:orignal associations from node: " + nodeRef);
|
||||
}
|
||||
if (assocs.size() == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return assocs.get(0).getTargetRef();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NodeRef> getCopies(NodeRef nodeRef)
|
||||
{
|
||||
List<NodeRef> copies = new ArrayList<NodeRef>();
|
||||
|
||||
// Do a search to find the origional document
|
||||
ResultSet resultSet = null;
|
||||
try
|
||||
PagingRequest pagingRequest = new PagingRequest(1000);
|
||||
PagingResults<CopyInfo> page = getCopies(nodeRef, pagingRequest);
|
||||
if (page.hasMoreItems())
|
||||
{
|
||||
resultSet = this.searchService.query(
|
||||
nodeRef.getStoreRef(),
|
||||
SearchService.LANGUAGE_LUCENE,
|
||||
"+@\\{http\\://www.alfresco.org/model/content/1.0\\}" + ContentModel.PROP_COPY_REFERENCE.getLocalName() + ":\"" + nodeRef.toString() + "\"");
|
||||
|
||||
for (NodeRef copy : resultSet.getNodeRefs())
|
||||
{
|
||||
copies.add(copy);
|
||||
}
|
||||
logger.warn("Trimmed page size for deprecated getCopies() call.");
|
||||
}
|
||||
finally
|
||||
List<CopyInfo> pageResults = page.getPage();
|
||||
List<NodeRef> results = new ArrayList<NodeRef>(pageResults.size());
|
||||
for (CopyInfo copyInfo : pageResults)
|
||||
{
|
||||
if (resultSet != null)
|
||||
{
|
||||
resultSet.close();
|
||||
}
|
||||
results.add(copyInfo.getNodeRef());
|
||||
}
|
||||
|
||||
return copies;
|
||||
return results;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -411,9 +405,9 @@ public class CopyServiceImpl implements CopyService
|
||||
{
|
||||
CannedQueryFactory<CopyInfo> queryFactory = cannedQueryRegistry.getNamedObject(QUERY_FACTORY_GET_COPIES);
|
||||
CannedQueryParameters params = new CannedQueryParameters(
|
||||
originalNodeRef,
|
||||
new CannedQueryPageDetails(pagingRequest),
|
||||
null);
|
||||
new AbstractCopyCannedQueryFactory.CopyCannedQueryDetail(originalNodeRef),
|
||||
null,
|
||||
pagingRequest);
|
||||
CannedQuery<CopyInfo> query = queryFactory.getCannedQuery(params);
|
||||
return query.execute();
|
||||
}
|
||||
@@ -421,14 +415,14 @@ public class CopyServiceImpl implements CopyService
|
||||
@Override
|
||||
public PagingResults<CopyInfo> getCopies(
|
||||
NodeRef originalNodeRef,
|
||||
NodeRef copyParentNodeRef, Set<QName> copyNodeAspectsToIgnore,
|
||||
NodeRef copyParentNodeRef,
|
||||
PagingRequest pagingRequest)
|
||||
{
|
||||
CannedQueryFactory<CopyInfo> queryFactory = cannedQueryRegistry.getNamedObject(QUERY_FACTORY_GET_COPIES);
|
||||
CannedQueryParameters params = new CannedQueryParameters(
|
||||
originalNodeRef,
|
||||
new CannedQueryPageDetails(pagingRequest),
|
||||
null);
|
||||
new AbstractCopyCannedQueryFactory.CopyCannedQueryDetail(originalNodeRef, copyParentNodeRef),
|
||||
null,
|
||||
pagingRequest);
|
||||
CannedQuery<CopyInfo> query = queryFactory.getCannedQuery(params);
|
||||
return query.execute();
|
||||
}
|
||||
@@ -593,10 +587,16 @@ public class CopyServiceImpl implements CopyService
|
||||
// Copy residual properties
|
||||
copyResidualProperties(copyDetails, copyTarget);
|
||||
|
||||
// Apply the copy aspect to the new node
|
||||
Map<QName, Serializable> copyProperties = new HashMap<QName, Serializable>();
|
||||
copyProperties.put(ContentModel.PROP_COPY_REFERENCE, sourceNodeRef);
|
||||
internalNodeService.addAspect(copyTarget, ContentModel.ASPECT_COPIEDFROM, copyProperties);
|
||||
// Link the new node to the original, but ensure that we only keep track of the last copy
|
||||
List<AssociationRef> originalAssocs = internalNodeService.getTargetAssocs(copyTarget, ContentModel.ASSOC_ORIGINAL);
|
||||
for (AssociationRef originalAssoc : originalAssocs)
|
||||
{
|
||||
internalNodeService.removeAssociation(
|
||||
originalAssoc.getSourceRef(),
|
||||
originalAssoc.getTargetRef(),
|
||||
ContentModel.ASSOC_ORIGINAL);
|
||||
}
|
||||
internalNodeService.createAssociation(copyTarget, sourceNodeRef, ContentModel.ASSOC_ORIGINAL);
|
||||
|
||||
// Copy permissions
|
||||
copyPermissions(sourceNodeRef, copyTarget);
|
||||
@@ -1389,5 +1389,5 @@ public class CopyServiceImpl implements CopyService
|
||||
public CopyBehaviourCallback getCallbackForOwnableAspect(QName classRef, CopyDetails copyDetails)
|
||||
{
|
||||
return DoNothingCopyBehaviourCallback.getInstance();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -43,6 +43,7 @@ import org.alfresco.repo.dictionary.M2ChildAssociation;
|
||||
import org.alfresco.repo.dictionary.M2Model;
|
||||
import org.alfresco.repo.dictionary.M2Property;
|
||||
import org.alfresco.repo.dictionary.M2Type;
|
||||
import org.alfresco.repo.node.integrity.IntegrityChecker;
|
||||
import org.alfresco.repo.rule.RuleModel;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
@@ -77,6 +78,7 @@ import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.alfresco.util.PropertyMap;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
@@ -477,14 +479,14 @@ public class CopyServiceImplTest extends TestCase
|
||||
/**
|
||||
* Test copy new node within store
|
||||
*/
|
||||
public void DISABLED_testCopyToNewNode()
|
||||
public void testCopyToNewNode()
|
||||
{
|
||||
PagingRequest pageRequest = new PagingRequest(10);
|
||||
PagingResults<CopyInfo> copies = null;
|
||||
|
||||
// Check that the node has no copies
|
||||
copies = copyService.getCopies(sourceNodeRef, pageRequest);
|
||||
assertEquals("Incorrect number of copies", 1, copies.getPage().size());
|
||||
assertEquals("Incorrect number of copies", 0, copies.getPage().size());
|
||||
|
||||
// Copy to new node without copying children
|
||||
NodeRef copy = copyService.copy(
|
||||
@@ -535,7 +537,87 @@ public class CopyServiceImplTest extends TestCase
|
||||
|
||||
//System.out.println(
|
||||
// NodeStoreInspector.dumpNodeStore(nodeService, storeRef));
|
||||
}
|
||||
}
|
||||
|
||||
public void testCopiedFromAspect()
|
||||
{
|
||||
IntegrityChecker integrityChecker = (IntegrityChecker) ctx.getBean("integrityChecker");
|
||||
|
||||
// Create the node used for copying
|
||||
ChildAssociationRef childAssocRef = nodeService.createNode(
|
||||
rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}test"),
|
||||
TEST_TYPE_QNAME,
|
||||
createTypePropertyBag());
|
||||
NodeRef nodeRef = childAssocRef.getChildRef();
|
||||
|
||||
PagingRequest pageRequest = new PagingRequest(10);
|
||||
pageRequest.setRequestTotalCountMax(200);
|
||||
PagingResults<CopyInfo> copies = null;
|
||||
|
||||
NodeRef firstCopy = null;
|
||||
|
||||
for (int i = 1; i <= 100; i++)
|
||||
{
|
||||
NodeRef copyNodeRef = copyService.copy(
|
||||
nodeRef,
|
||||
rootNodeRef,
|
||||
ContentModel.ASSOC_CHILDREN,
|
||||
QName.createQName("{test}copyAssoc"));
|
||||
if (firstCopy == null)
|
||||
{
|
||||
firstCopy = copyNodeRef;
|
||||
}
|
||||
copies = copyService.getCopies(nodeRef, pageRequest);
|
||||
assertEquals("Total count not correct", new Pair<Integer, Integer>(i, i), copies.getTotalResultCount());
|
||||
assertEquals("Incorrect number of copies", (i > 10 ? 10 : i), copies.getPage().size());
|
||||
|
||||
// Since the results are paged, make sure that we have the correct results while we only have a page
|
||||
boolean found = (i > 10) ? true : false;
|
||||
for (CopyInfo copy : copies.getPage())
|
||||
{
|
||||
if (found) // Might not be checking if we are over a page
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (copy.getNodeRef().equals(copyNodeRef))
|
||||
{
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
assertTrue("Did not find the copy in the list of copies.", found);
|
||||
|
||||
// Run integrity checks to ensure that commit has a chance
|
||||
integrityChecker.checkIntegrity();
|
||||
|
||||
// Now query for copies in current parent location
|
||||
copies = copyService.getCopies(nodeRef, rootNodeRef, pageRequest);
|
||||
assertEquals("Total count not correct", new Pair<Integer, Integer>(i, i), copies.getTotalResultCount());
|
||||
assertEquals("Incorrect number of copies", (i > 10 ? 10 : i), copies.getPage().size());
|
||||
|
||||
// Check that the original node can be retrieved
|
||||
NodeRef originalCheck = copyService.getOriginal(copyNodeRef);
|
||||
assertEquals("Original is not as expected. ", nodeRef, originalCheck);
|
||||
|
||||
// Check that the parent node can be included
|
||||
copies = copyService.getCopies(nodeRef, rootNodeRef, pageRequest);
|
||||
assertEquals("Total count not correct", new Pair<Integer, Integer>(i, i), copies.getTotalResultCount());
|
||||
assertEquals("Incorrect number of copies", (i > 10 ? 10 : i), copies.getPage().size());
|
||||
|
||||
// And query against some other parent node
|
||||
copies = copyService.getCopies(nodeRef, sourceNodeRef, pageRequest); // Some arbitrary parent
|
||||
assertEquals("Expected to find no copies", 0, copies.getPage().size());
|
||||
}
|
||||
|
||||
// Should be able to delete the original
|
||||
nodeService.deleteNode(nodeRef);
|
||||
// Run integrity checks to ensure that commit has a chance
|
||||
integrityChecker.checkIntegrity();
|
||||
// Should be no original
|
||||
NodeRef originalCheck = copyService.getOriginal(firstCopy);
|
||||
assertNull("Original should not be present. ", originalCheck);
|
||||
}
|
||||
|
||||
public void testCopyNodeWithRules()
|
||||
{
|
||||
@@ -1069,9 +1151,10 @@ public class CopyServiceImplTest extends TestCase
|
||||
// Check that the copy aspect has been applied to the copy
|
||||
boolean hasCopyAspect = nodeService.hasAspect(destinationNodeRef, ContentModel.ASPECT_COPIEDFROM);
|
||||
assertTrue("Missing aspect: " + ContentModel.ASPECT_COPIEDFROM, hasCopyAspect);
|
||||
NodeRef copyNodeRef = (NodeRef)nodeService.getProperty(destinationNodeRef, ContentModel.PROP_COPY_REFERENCE);
|
||||
assertNotNull(copyNodeRef);
|
||||
assertEquals(sourceNodeRef, copyNodeRef);
|
||||
List<AssociationRef> assocs = nodeService.getTargetAssocs(destinationNodeRef, ContentModel.ASSOC_ORIGINAL);
|
||||
assertEquals("Expectd exactly one reference back to original", 1, assocs.size());
|
||||
NodeRef checkSourceNodeRef = assocs.get(0).getTargetRef();
|
||||
assertEquals("Copy refers to incorrect original source", sourceNodeRef, checkSourceNodeRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
@@ -14,392 +14,396 @@
|
||||
* 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/>.
|
||||
*/
|
||||
package org.alfresco.repo.copy;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.avm.AVMNodeConverter;
|
||||
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
|
||||
import org.alfresco.service.cmr.avm.AVMService;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.CopyService;
|
||||
import org.alfresco.service.cmr.repository.CrossRepositoryCopyService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.Pair;
|
||||
|
||||
/**
|
||||
* Cross Repository Copying.
|
||||
*
|
||||
* @author britt
|
||||
*/
|
||||
public class CrossRepositoryCopyServiceImpl implements CrossRepositoryCopyService
|
||||
{
|
||||
/**
|
||||
* The NodeService reference.
|
||||
*/
|
||||
private NodeService fNodeService;
|
||||
|
||||
/**
|
||||
* The FileFolderService reference.
|
||||
*/
|
||||
private FileFolderService fFileFolderService;
|
||||
|
||||
/**
|
||||
* The regular CopyService reference.
|
||||
*/
|
||||
private CopyService fCopyService;
|
||||
|
||||
/**
|
||||
* The AVMService.
|
||||
*/
|
||||
private AVMService fAVMService;
|
||||
|
||||
/**
|
||||
* The ContentService.
|
||||
*/
|
||||
private ContentService fContentService;
|
||||
|
||||
/**
|
||||
* The DictionaryService.
|
||||
*/
|
||||
private DictionaryService fDictionaryService;
|
||||
|
||||
/**
|
||||
* A default constructor.
|
||||
*/
|
||||
public CrossRepositoryCopyServiceImpl()
|
||||
{
|
||||
}
|
||||
|
||||
// Setters for Spring.
|
||||
|
||||
public void setAvmService(AVMService service)
|
||||
{
|
||||
fAVMService = service;
|
||||
}
|
||||
|
||||
public void setContentService(ContentService service)
|
||||
{
|
||||
fContentService = service;
|
||||
}
|
||||
|
||||
public void setCopyService(CopyService service)
|
||||
{
|
||||
fCopyService = service;
|
||||
}
|
||||
|
||||
public void setDictionaryService(DictionaryService service)
|
||||
{
|
||||
fDictionaryService = service;
|
||||
}
|
||||
|
||||
public void setFileFolderService(FileFolderService service)
|
||||
{
|
||||
fFileFolderService = service;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService service)
|
||||
{
|
||||
fNodeService = service;
|
||||
}
|
||||
|
||||
/**
|
||||
* This copies recursively src, which may be a container or a content type to dst, which must be a container. Copied
|
||||
* nodes will have the copied from aspect applied to them.
|
||||
*
|
||||
* @param src
|
||||
* The node to copy.
|
||||
* @param dst
|
||||
* The container to copy it into.
|
||||
* @param name
|
||||
* The name to give the copy.
|
||||
*/
|
||||
public void copy(NodeRef src, NodeRef dst, String name)
|
||||
{
|
||||
StoreRef srcStoreRef = src.getStoreRef();
|
||||
StoreRef dstStoreRef = dst.getStoreRef();
|
||||
if (srcStoreRef.getProtocol().equals(StoreRef.PROTOCOL_AVM))
|
||||
{
|
||||
if (dstStoreRef.getProtocol().equals(StoreRef.PROTOCOL_AVM))
|
||||
{
|
||||
copyAVMToAVM(src, dst, name);
|
||||
}
|
||||
else if (dstStoreRef.getProtocol().equals(StoreRef.PROTOCOL_WORKSPACE))
|
||||
{
|
||||
copyAVMToRepo(src, dst, name);
|
||||
}
|
||||
}
|
||||
else if (srcStoreRef.getProtocol().equals(StoreRef.PROTOCOL_WORKSPACE))
|
||||
{
|
||||
if (dstStoreRef.getProtocol().equals(StoreRef.PROTOCOL_AVM))
|
||||
{
|
||||
copyRepoToAVM(src, dst, name);
|
||||
}
|
||||
else if (dstStoreRef.getProtocol().equals(StoreRef.PROTOCOL_WORKSPACE))
|
||||
{
|
||||
copyRepoToRepo(src, dst, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle copying from AVM to AVM
|
||||
*
|
||||
* @param src
|
||||
* Source node.
|
||||
* @param dst
|
||||
* Destination directory node.
|
||||
* @param name
|
||||
* Name to give copy.
|
||||
*/
|
||||
private void copyAVMToAVM(NodeRef src, NodeRef dst, String name)
|
||||
{
|
||||
Pair<Integer, String> srcStorePath = AVMNodeConverter.ToAVMVersionPath(src);
|
||||
Pair<Integer, String> dstStorePath = AVMNodeConverter.ToAVMVersionPath(dst);
|
||||
fAVMService.copy(srcStorePath.getFirst(), srcStorePath.getSecond(), dstStorePath.getSecond(), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle copying from AVM to Repo.
|
||||
*
|
||||
* @param src
|
||||
* Source node.
|
||||
* @param dst
|
||||
* Destination Container.
|
||||
* @param name
|
||||
* The name to give the copy.
|
||||
*/
|
||||
private void copyAVMToRepo(NodeRef src, NodeRef dst, String name)
|
||||
{
|
||||
Pair<Integer, String> versionPath = AVMNodeConverter.ToAVMVersionPath(src);
|
||||
AVMNodeDescriptor desc = fAVMService.lookup(versionPath.getFirst(), versionPath.getSecond());
|
||||
NodeRef existing = fFileFolderService.searchSimple(dst, name);
|
||||
if (desc.isFile())
|
||||
{
|
||||
if (existing != null && !fNodeService.getType(existing).equals(ContentModel.TYPE_CONTENT))
|
||||
{
|
||||
fFileFolderService.delete(existing);
|
||||
existing = null;
|
||||
}
|
||||
NodeRef childRef = null;
|
||||
if (existing == null)
|
||||
{
|
||||
childRef = fFileFolderService.create(dst, name, ContentModel.TYPE_CONTENT).getNodeRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
childRef = existing;
|
||||
}
|
||||
InputStream in = fAVMService.getFileInputStream(desc);
|
||||
ContentData cd = fAVMService.getContentDataForRead(versionPath.getFirst(), desc.getPath());
|
||||
ContentWriter writer = fContentService.getWriter(childRef, ContentModel.PROP_CONTENT, true);
|
||||
writer.setEncoding(cd.getEncoding());
|
||||
writer.setMimetype(cd.getMimetype());
|
||||
OutputStream out = writer.getContentOutputStream();
|
||||
copyData(in, out);
|
||||
copyPropsAndAspectsAVMToRepo(src, childRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (existing != null && !fNodeService.getType(existing).equals(ContentModel.TYPE_FOLDER))
|
||||
{
|
||||
fFileFolderService.delete(existing);
|
||||
existing = null;
|
||||
}
|
||||
NodeRef childRef = null;
|
||||
if (existing == null)
|
||||
{
|
||||
childRef = fFileFolderService.create(dst, name, ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
childRef = existing;
|
||||
}
|
||||
copyPropsAndAspectsAVMToRepo(src, childRef);
|
||||
Map<String, AVMNodeDescriptor> listing = fAVMService.getDirectoryListing(desc);
|
||||
for (Map.Entry<String, AVMNodeDescriptor> entry : listing.entrySet())
|
||||
{
|
||||
NodeRef srcChild = AVMNodeConverter.ToNodeRef(versionPath.getFirst(), entry.getValue().getPath());
|
||||
copyAVMToRepo(srcChild, childRef, entry.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper that copies aspects and properties.
|
||||
*
|
||||
* @param src
|
||||
* The source AVM node.
|
||||
* @param dst
|
||||
* The destination Repo node.
|
||||
*/
|
||||
private void copyPropsAndAspectsAVMToRepo(NodeRef src, NodeRef dst)
|
||||
{
|
||||
Map<QName, Serializable> props = fNodeService.getProperties(src);
|
||||
fNodeService.setProperties(dst, props);
|
||||
Set<QName> aspects = fNodeService.getAspects(src);
|
||||
Map<QName, Serializable> empty = new HashMap<QName, Serializable>();
|
||||
for (QName aspect : aspects)
|
||||
{
|
||||
fNodeService.addAspect(dst, aspect, empty);
|
||||
}
|
||||
if (!fNodeService.hasAspect(dst, ContentModel.ASPECT_COPIEDFROM))
|
||||
{
|
||||
empty.put(ContentModel.PROP_COPY_REFERENCE, src);
|
||||
fNodeService.addAspect(dst, ContentModel.ASPECT_COPIEDFROM, empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
fNodeService.setProperty(dst, ContentModel.PROP_COPY_REFERENCE, src);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle copying from Repo to AVM.
|
||||
*
|
||||
* @param src
|
||||
* The source node.
|
||||
* @param dst
|
||||
* The destingation directory.
|
||||
* @param name
|
||||
* The name to give the copy.
|
||||
*/
|
||||
private void copyRepoToAVM(NodeRef src, NodeRef dst, String name)
|
||||
{
|
||||
QName srcType = fNodeService.getType(src);
|
||||
Pair<Integer, String> versionPath = AVMNodeConverter.ToAVMVersionPath(dst);
|
||||
String childPath = AVMNodeConverter.ExtendAVMPath(versionPath.getSecond(), name);
|
||||
NodeRef childNodeRef = AVMNodeConverter.ToNodeRef(-1, childPath);
|
||||
if (fDictionaryService.isSubClass(srcType, ContentModel.TYPE_CONTENT))
|
||||
{
|
||||
ContentReader reader = fContentService.getReader(src, ContentModel.PROP_CONTENT);
|
||||
InputStream in = reader.getContentInputStream();
|
||||
AVMNodeDescriptor desc = fAVMService.lookup(-1, childPath);
|
||||
if (desc != null && !desc.isFile())
|
||||
{
|
||||
fAVMService.removeNode(childPath);
|
||||
desc = null;
|
||||
}
|
||||
if (desc == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
fAVMService.createFile(versionPath.getSecond(), name).close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("I/O Error.", e);
|
||||
}
|
||||
}
|
||||
ContentWriter writer = fAVMService.getContentWriter(childPath, true);
|
||||
writer.setEncoding(reader.getEncoding());
|
||||
writer.setMimetype(reader.getMimetype());
|
||||
OutputStream out = writer.getContentOutputStream();
|
||||
copyData(in, out);
|
||||
copyPropsAndAspectsRepoToAVM(src, childNodeRef, childPath);
|
||||
return;
|
||||
}
|
||||
if (fDictionaryService.isSubClass(srcType, ContentModel.TYPE_FOLDER))
|
||||
{
|
||||
AVMNodeDescriptor desc = fAVMService.lookup(-1, childPath);
|
||||
if (desc != null && !desc.isDirectory())
|
||||
{
|
||||
fAVMService.removeNode(childPath);
|
||||
desc = null;
|
||||
}
|
||||
if (desc == null)
|
||||
{
|
||||
fAVMService.createDirectory(versionPath.getSecond(), name);
|
||||
}
|
||||
copyPropsAndAspectsRepoToAVM(src, childNodeRef, childPath);
|
||||
List<FileInfo> listing = fFileFolderService.list(src);
|
||||
for (FileInfo info : listing)
|
||||
{
|
||||
copyRepoToAVM(info.getNodeRef(), childNodeRef, info.getName());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to copy properties and aspects.
|
||||
*
|
||||
* @param src
|
||||
* The source node.
|
||||
* @param dst
|
||||
* The destination node.
|
||||
* @param dstPath
|
||||
* The destination AVM path.
|
||||
*/
|
||||
private void copyPropsAndAspectsRepoToAVM(NodeRef src, NodeRef dst, String dstPath)
|
||||
{
|
||||
Map<QName, Serializable> props = fNodeService.getProperties(src);
|
||||
fNodeService.setProperties(dst, props);
|
||||
Set<QName> aspects = fNodeService.getAspects(src);
|
||||
for (QName aspect : aspects)
|
||||
{
|
||||
fAVMService.addAspect(dstPath, aspect);
|
||||
}
|
||||
if (!fAVMService.hasAspect(-1, dstPath, ContentModel.ASPECT_COPIEDFROM))
|
||||
{
|
||||
fAVMService.addAspect(dstPath, ContentModel.ASPECT_COPIEDFROM);
|
||||
}
|
||||
fNodeService.setProperty(dst, ContentModel.PROP_COPY_REFERENCE, src);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle copying from Repo to Repo.
|
||||
*
|
||||
* @param src
|
||||
* The source node.
|
||||
* @param dst
|
||||
* The destination container.
|
||||
* @param name
|
||||
* The name to give the copy.
|
||||
*/
|
||||
private void copyRepoToRepo(NodeRef src, NodeRef dst, String name)
|
||||
{
|
||||
ChildAssociationRef assocRef = fNodeService.getPrimaryParent(src);
|
||||
fCopyService.copyAndRename(src, dst, ContentModel.ASSOC_CONTAINS, assocRef.getQName(), true);
|
||||
}
|
||||
|
||||
private void copyData(InputStream in, OutputStream out)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] buff = new byte[8192];
|
||||
int read = 0;
|
||||
while ((read = in.read(buff)) != -1)
|
||||
{
|
||||
out.write(buff, 0, read);
|
||||
}
|
||||
in.close();
|
||||
out.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("I/O Error.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.alfresco.repo.copy;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.avm.AVMNodeConverter;
|
||||
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
|
||||
import org.alfresco.service.cmr.avm.AVMService;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.CopyService;
|
||||
import org.alfresco.service.cmr.repository.CrossRepositoryCopyService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.Pair;
|
||||
|
||||
/**
|
||||
* Cross Repository Copying.
|
||||
*
|
||||
* @author britt
|
||||
*/
|
||||
public class CrossRepositoryCopyServiceImpl implements CrossRepositoryCopyService
|
||||
{
|
||||
/**
|
||||
* The NodeService reference.
|
||||
*/
|
||||
private NodeService fNodeService;
|
||||
|
||||
/**
|
||||
* The FileFolderService reference.
|
||||
*/
|
||||
private FileFolderService fFileFolderService;
|
||||
|
||||
/**
|
||||
* The regular CopyService reference.
|
||||
*/
|
||||
private CopyService fCopyService;
|
||||
|
||||
/**
|
||||
* The AVMService.
|
||||
*/
|
||||
private AVMService fAVMService;
|
||||
|
||||
/**
|
||||
* The ContentService.
|
||||
*/
|
||||
private ContentService fContentService;
|
||||
|
||||
/**
|
||||
* The DictionaryService.
|
||||
*/
|
||||
private DictionaryService fDictionaryService;
|
||||
|
||||
/**
|
||||
* A default constructor.
|
||||
*/
|
||||
public CrossRepositoryCopyServiceImpl()
|
||||
{
|
||||
}
|
||||
|
||||
// Setters for Spring.
|
||||
|
||||
public void setAvmService(AVMService service)
|
||||
{
|
||||
fAVMService = service;
|
||||
}
|
||||
|
||||
public void setContentService(ContentService service)
|
||||
{
|
||||
fContentService = service;
|
||||
}
|
||||
|
||||
public void setCopyService(CopyService service)
|
||||
{
|
||||
fCopyService = service;
|
||||
}
|
||||
|
||||
public void setDictionaryService(DictionaryService service)
|
||||
{
|
||||
fDictionaryService = service;
|
||||
}
|
||||
|
||||
public void setFileFolderService(FileFolderService service)
|
||||
{
|
||||
fFileFolderService = service;
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService service)
|
||||
{
|
||||
fNodeService = service;
|
||||
}
|
||||
|
||||
/**
|
||||
* This copies recursively src, which may be a container or a content type to dst, which must be a container. Copied
|
||||
* nodes will have the copied from aspect applied to them.
|
||||
*
|
||||
* @param src
|
||||
* The node to copy.
|
||||
* @param dst
|
||||
* The container to copy it into.
|
||||
* @param name
|
||||
* The name to give the copy.
|
||||
*/
|
||||
public void copy(NodeRef src, NodeRef dst, String name)
|
||||
{
|
||||
StoreRef srcStoreRef = src.getStoreRef();
|
||||
StoreRef dstStoreRef = dst.getStoreRef();
|
||||
if (srcStoreRef.getProtocol().equals(StoreRef.PROTOCOL_AVM))
|
||||
{
|
||||
if (dstStoreRef.getProtocol().equals(StoreRef.PROTOCOL_AVM))
|
||||
{
|
||||
copyAVMToAVM(src, dst, name);
|
||||
}
|
||||
else if (dstStoreRef.getProtocol().equals(StoreRef.PROTOCOL_WORKSPACE))
|
||||
{
|
||||
copyAVMToRepo(src, dst, name);
|
||||
}
|
||||
}
|
||||
else if (srcStoreRef.getProtocol().equals(StoreRef.PROTOCOL_WORKSPACE))
|
||||
{
|
||||
if (dstStoreRef.getProtocol().equals(StoreRef.PROTOCOL_AVM))
|
||||
{
|
||||
copyRepoToAVM(src, dst, name);
|
||||
}
|
||||
else if (dstStoreRef.getProtocol().equals(StoreRef.PROTOCOL_WORKSPACE))
|
||||
{
|
||||
copyRepoToRepo(src, dst, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle copying from AVM to AVM
|
||||
*
|
||||
* @param src
|
||||
* Source node.
|
||||
* @param dst
|
||||
* Destination directory node.
|
||||
* @param name
|
||||
* Name to give copy.
|
||||
*/
|
||||
private void copyAVMToAVM(NodeRef src, NodeRef dst, String name)
|
||||
{
|
||||
Pair<Integer, String> srcStorePath = AVMNodeConverter.ToAVMVersionPath(src);
|
||||
Pair<Integer, String> dstStorePath = AVMNodeConverter.ToAVMVersionPath(dst);
|
||||
fAVMService.copy(srcStorePath.getFirst(), srcStorePath.getSecond(), dstStorePath.getSecond(), name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle copying from AVM to Repo.
|
||||
*
|
||||
* @param src
|
||||
* Source node.
|
||||
* @param dst
|
||||
* Destination Container.
|
||||
* @param name
|
||||
* The name to give the copy.
|
||||
*/
|
||||
private void copyAVMToRepo(NodeRef src, NodeRef dst, String name)
|
||||
{
|
||||
Pair<Integer, String> versionPath = AVMNodeConverter.ToAVMVersionPath(src);
|
||||
AVMNodeDescriptor desc = fAVMService.lookup(versionPath.getFirst(), versionPath.getSecond());
|
||||
NodeRef existing = fFileFolderService.searchSimple(dst, name);
|
||||
if (desc.isFile())
|
||||
{
|
||||
if (existing != null && !fNodeService.getType(existing).equals(ContentModel.TYPE_CONTENT))
|
||||
{
|
||||
fFileFolderService.delete(existing);
|
||||
existing = null;
|
||||
}
|
||||
NodeRef childRef = null;
|
||||
if (existing == null)
|
||||
{
|
||||
childRef = fFileFolderService.create(dst, name, ContentModel.TYPE_CONTENT).getNodeRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
childRef = existing;
|
||||
}
|
||||
InputStream in = fAVMService.getFileInputStream(desc);
|
||||
ContentData cd = fAVMService.getContentDataForRead(versionPath.getFirst(), desc.getPath());
|
||||
ContentWriter writer = fContentService.getWriter(childRef, ContentModel.PROP_CONTENT, true);
|
||||
writer.setEncoding(cd.getEncoding());
|
||||
writer.setMimetype(cd.getMimetype());
|
||||
OutputStream out = writer.getContentOutputStream();
|
||||
copyData(in, out);
|
||||
copyPropsAndAspectsAVMToRepo(src, childRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (existing != null && !fNodeService.getType(existing).equals(ContentModel.TYPE_FOLDER))
|
||||
{
|
||||
fFileFolderService.delete(existing);
|
||||
existing = null;
|
||||
}
|
||||
NodeRef childRef = null;
|
||||
if (existing == null)
|
||||
{
|
||||
childRef = fFileFolderService.create(dst, name, ContentModel.TYPE_FOLDER).getNodeRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
childRef = existing;
|
||||
}
|
||||
copyPropsAndAspectsAVMToRepo(src, childRef);
|
||||
Map<String, AVMNodeDescriptor> listing = fAVMService.getDirectoryListing(desc);
|
||||
for (Map.Entry<String, AVMNodeDescriptor> entry : listing.entrySet())
|
||||
{
|
||||
NodeRef srcChild = AVMNodeConverter.ToNodeRef(versionPath.getFirst(), entry.getValue().getPath());
|
||||
copyAVMToRepo(srcChild, childRef, entry.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper that copies aspects and properties.
|
||||
*
|
||||
* @param src
|
||||
* The source AVM node.
|
||||
* @param dst
|
||||
* The destination Repo node.
|
||||
*/
|
||||
private void copyPropsAndAspectsAVMToRepo(NodeRef src, NodeRef dst)
|
||||
{
|
||||
Map<QName, Serializable> props = fNodeService.getProperties(src);
|
||||
fNodeService.setProperties(dst, props);
|
||||
Set<QName> aspects = fNodeService.getAspects(src);
|
||||
Map<QName, Serializable> empty = new HashMap<QName, Serializable>();
|
||||
for (QName aspect : aspects)
|
||||
{
|
||||
fNodeService.addAspect(dst, aspect, empty);
|
||||
}
|
||||
// 4.0: Derek Hulley: The cm:copiedFrom aspect is not that important and
|
||||
// AVM doesn't support associations
|
||||
// if (!fNodeService.hasAspect(dst, ContentModel.ASPECT_COPIEDFROM))
|
||||
// {
|
||||
// empty.put(ContentModel.PROP_COPY_REFERENCE, src);
|
||||
// fNodeService.addAspect(dst, ContentModel.ASPECT_COPIEDFROM, empty);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// fNodeService.setProperty(dst, ContentModel.PROP_COPY_REFERENCE, src);
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle copying from Repo to AVM.
|
||||
*
|
||||
* @param src
|
||||
* The source node.
|
||||
* @param dst
|
||||
* The destingation directory.
|
||||
* @param name
|
||||
* The name to give the copy.
|
||||
*/
|
||||
private void copyRepoToAVM(NodeRef src, NodeRef dst, String name)
|
||||
{
|
||||
QName srcType = fNodeService.getType(src);
|
||||
Pair<Integer, String> versionPath = AVMNodeConverter.ToAVMVersionPath(dst);
|
||||
String childPath = AVMNodeConverter.ExtendAVMPath(versionPath.getSecond(), name);
|
||||
NodeRef childNodeRef = AVMNodeConverter.ToNodeRef(-1, childPath);
|
||||
if (fDictionaryService.isSubClass(srcType, ContentModel.TYPE_CONTENT))
|
||||
{
|
||||
ContentReader reader = fContentService.getReader(src, ContentModel.PROP_CONTENT);
|
||||
InputStream in = reader.getContentInputStream();
|
||||
AVMNodeDescriptor desc = fAVMService.lookup(-1, childPath);
|
||||
if (desc != null && !desc.isFile())
|
||||
{
|
||||
fAVMService.removeNode(childPath);
|
||||
desc = null;
|
||||
}
|
||||
if (desc == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
fAVMService.createFile(versionPath.getSecond(), name).close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("I/O Error.", e);
|
||||
}
|
||||
}
|
||||
ContentWriter writer = fAVMService.getContentWriter(childPath, true);
|
||||
writer.setEncoding(reader.getEncoding());
|
||||
writer.setMimetype(reader.getMimetype());
|
||||
OutputStream out = writer.getContentOutputStream();
|
||||
copyData(in, out);
|
||||
copyPropsAndAspectsRepoToAVM(src, childNodeRef, childPath);
|
||||
return;
|
||||
}
|
||||
if (fDictionaryService.isSubClass(srcType, ContentModel.TYPE_FOLDER))
|
||||
{
|
||||
AVMNodeDescriptor desc = fAVMService.lookup(-1, childPath);
|
||||
if (desc != null && !desc.isDirectory())
|
||||
{
|
||||
fAVMService.removeNode(childPath);
|
||||
desc = null;
|
||||
}
|
||||
if (desc == null)
|
||||
{
|
||||
fAVMService.createDirectory(versionPath.getSecond(), name);
|
||||
}
|
||||
copyPropsAndAspectsRepoToAVM(src, childNodeRef, childPath);
|
||||
List<FileInfo> listing = fFileFolderService.list(src);
|
||||
for (FileInfo info : listing)
|
||||
{
|
||||
copyRepoToAVM(info.getNodeRef(), childNodeRef, info.getName());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to copy properties and aspects.
|
||||
*
|
||||
* @param src
|
||||
* The source node.
|
||||
* @param dst
|
||||
* The destination node.
|
||||
* @param dstPath
|
||||
* The destination AVM path.
|
||||
*/
|
||||
private void copyPropsAndAspectsRepoToAVM(NodeRef src, NodeRef dst, String dstPath)
|
||||
{
|
||||
Map<QName, Serializable> props = fNodeService.getProperties(src);
|
||||
fNodeService.setProperties(dst, props);
|
||||
Set<QName> aspects = fNodeService.getAspects(src);
|
||||
for (QName aspect : aspects)
|
||||
{
|
||||
fAVMService.addAspect(dstPath, aspect);
|
||||
}
|
||||
// 4.0: Derek Hulley: The cm:copiedFrom aspect is not that important and
|
||||
// AVM doesn't support associations
|
||||
// if (!fAVMService.hasAspect(-1, dstPath, ContentModel.ASPECT_COPIEDFROM))
|
||||
// {
|
||||
// fAVMService.addAspect(dstPath, ContentModel.ASPECT_COPIEDFROM);
|
||||
// }
|
||||
// fNodeService.setProperty(dst, ContentModel.PROP_COPY_REFERENCE, src);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle copying from Repo to Repo.
|
||||
*
|
||||
* @param src
|
||||
* The source node.
|
||||
* @param dst
|
||||
* The destination container.
|
||||
* @param name
|
||||
* The name to give the copy.
|
||||
*/
|
||||
private void copyRepoToRepo(NodeRef src, NodeRef dst, String name)
|
||||
{
|
||||
ChildAssociationRef assocRef = fNodeService.getPrimaryParent(src);
|
||||
fCopyService.copyAndRename(src, dst, ContentModel.ASSOC_CONTAINS, assocRef.getQName(), true);
|
||||
}
|
||||
|
||||
private void copyData(InputStream in, OutputStream out)
|
||||
{
|
||||
try
|
||||
{
|
||||
byte[] buff = new byte[8192];
|
||||
int read = 0;
|
||||
while ((read = in.read(buff)) != -1)
|
||||
{
|
||||
out.write(buff, 0, read);
|
||||
}
|
||||
in.close();
|
||||
out.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("I/O Error.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -19,9 +19,13 @@
|
||||
package org.alfresco.repo.copy.query;
|
||||
|
||||
import org.alfresco.query.AbstractCannedQueryFactory;
|
||||
import org.alfresco.query.CannedQueryParameters;
|
||||
import org.alfresco.repo.domain.node.NodeDAO;
|
||||
import org.alfresco.repo.domain.qname.QNameDAO;
|
||||
import org.alfresco.repo.domain.query.CannedQueryDAO;
|
||||
import org.alfresco.repo.security.permissions.impl.acegi.MethodSecurityBean;
|
||||
import org.alfresco.service.cmr.repository.CopyService.CopyInfo;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
/**
|
||||
* Support for Canned Queries for copy
|
||||
@@ -34,6 +38,7 @@ public abstract class AbstractCopyCannedQueryFactory<R> extends AbstractCannedQu
|
||||
protected NodeDAO nodeDAO;
|
||||
protected QNameDAO qnameDAO;
|
||||
protected CannedQueryDAO cannedQueryDAO;
|
||||
protected MethodSecurityBean<CopyInfo> methodSecurity;
|
||||
|
||||
public void setNodeDAO(NodeDAO nodeDAO)
|
||||
{
|
||||
@@ -47,4 +52,56 @@ public abstract class AbstractCopyCannedQueryFactory<R> extends AbstractCannedQu
|
||||
{
|
||||
this.cannedQueryDAO = cannedQueryDAO;
|
||||
}
|
||||
|
||||
public void setMethodSecurity(MethodSecurityBean<CopyInfo> methodSecurity)
|
||||
{
|
||||
this.methodSecurity = methodSecurity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameter bean to use for copy queries
|
||||
*
|
||||
* @author Derek Hulley
|
||||
* @since 4.0
|
||||
*/
|
||||
public static class CopyCannedQueryDetail
|
||||
{
|
||||
/*package*/ final NodeRef originalNodeRef;
|
||||
/*package*/ final NodeRef copyParentNodeRef;
|
||||
/**
|
||||
* @param originalNodeRef the original node
|
||||
*/
|
||||
public CopyCannedQueryDetail(NodeRef originalNodeRef)
|
||||
{
|
||||
this(originalNodeRef, null);
|
||||
}
|
||||
/**
|
||||
* @param originalNodeRef the original node
|
||||
* @param copyParentNodeRef the copied node's primary parent (optional)
|
||||
* @param copyNodeAspectsToIgnore aspects on the copied node that effectively hide it
|
||||
* (<tt>null</tt> or empty allowed)
|
||||
*/
|
||||
public CopyCannedQueryDetail(NodeRef originalNodeRef, NodeRef copyParentNodeRef)
|
||||
{
|
||||
super();
|
||||
if (originalNodeRef == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Must supply an originalNodeRef");
|
||||
}
|
||||
this.originalNodeRef = originalNodeRef;
|
||||
this.copyParentNodeRef = copyParentNodeRef;
|
||||
}
|
||||
}
|
||||
|
||||
protected CopyCannedQueryDetail getDetail(CannedQueryParameters parameters)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (CopyCannedQueryDetail) parameters.getParameterBean();
|
||||
}
|
||||
catch (ClassCastException e)
|
||||
{
|
||||
throw new IllegalArgumentException("Expected " + CopyCannedQueryDetail.class);
|
||||
}
|
||||
}
|
||||
}
|
50
source/java/org/alfresco/repo/copy/query/CopyEntity.java
Normal file
50
source/java/org/alfresco/repo/copy/query/CopyEntity.java
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
package org.alfresco.repo.copy.query;
|
||||
|
||||
import org.alfresco.repo.domain.node.NodeEntity;
|
||||
|
||||
/**
|
||||
* Bean class to data about copied nodes
|
||||
*
|
||||
* @author Derek Hulley
|
||||
* @since 4.0
|
||||
*/
|
||||
public class CopyEntity
|
||||
{
|
||||
private NodeEntity copy;
|
||||
private String copyName;
|
||||
|
||||
public NodeEntity getCopy()
|
||||
{
|
||||
return copy;
|
||||
}
|
||||
public void setCopy(NodeEntity copy)
|
||||
{
|
||||
this.copy = copy;
|
||||
}
|
||||
public String getCopyName()
|
||||
{
|
||||
return copyName;
|
||||
}
|
||||
public void setCopyName(String copyName)
|
||||
{
|
||||
this.copyName = copyName;
|
||||
}
|
||||
}
|
@@ -29,7 +29,8 @@ import java.util.List;
|
||||
public class CopyParametersEntity
|
||||
{
|
||||
private Long originalNodeId;
|
||||
private Long copiedFromAssocTypeId;
|
||||
private Long originalAssocTypeId;
|
||||
private Long namePropId;
|
||||
private Long copyParentNodeId;
|
||||
private List<Long> copyAspectIdsToIgnore;
|
||||
|
||||
@@ -41,13 +42,21 @@ public class CopyParametersEntity
|
||||
{
|
||||
this.originalNodeId = originalNodeId;
|
||||
}
|
||||
public Long getCopiedFromAssocTypeId()
|
||||
public Long getOriginalAssocTypeId()
|
||||
{
|
||||
return copiedFromAssocTypeId;
|
||||
return originalAssocTypeId;
|
||||
}
|
||||
public void setCopiedFromAssocTypeId(Long copiedFromAssocTypeId)
|
||||
public void setOriginalAssocTypeId(Long originalAssocTypeId)
|
||||
{
|
||||
this.copiedFromAssocTypeId = copiedFromAssocTypeId;
|
||||
this.originalAssocTypeId = originalAssocTypeId;
|
||||
}
|
||||
public Long getNamePropId()
|
||||
{
|
||||
return namePropId;
|
||||
}
|
||||
public void setNamePropId(Long namePropId)
|
||||
{
|
||||
this.namePropId = namePropId;
|
||||
}
|
||||
public Long getCopyParentNodeId()
|
||||
{
|
||||
@@ -65,4 +74,8 @@ public class CopyParametersEntity
|
||||
{
|
||||
this.copyAspectIdsToIgnore = copyAspectIdsToIgnore;
|
||||
}
|
||||
public boolean getTrue()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -18,10 +18,20 @@
|
||||
*/
|
||||
package org.alfresco.repo.copy.query;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.query.CannedQuery;
|
||||
import org.alfresco.query.CannedQueryParameters;
|
||||
import org.alfresco.repo.security.permissions.impl.acegi.AbstractCannedQueryPermissions;
|
||||
import org.alfresco.repo.security.permissions.impl.acegi.MethodSecurityBean;
|
||||
import org.alfresco.service.cmr.repository.CopyService;
|
||||
import org.alfresco.service.cmr.repository.CopyService.CopyInfo;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.Pair;
|
||||
|
||||
/**
|
||||
* Factory producing queries for the {@link CopyService}
|
||||
@@ -34,6 +44,75 @@ public class GetCopiesCannedQueryFactory extends AbstractCopyCannedQueryFactory<
|
||||
@Override
|
||||
public CannedQuery<CopyInfo> getCannedQuery(CannedQueryParameters parameters)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
return new GetCopiesCannedQuery(parameters, methodSecurity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query to find nodes copied <i>from</i> a given node, optionally filtering out
|
||||
* based on specific values.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
* @since 4.0
|
||||
*/
|
||||
private class GetCopiesCannedQuery extends AbstractCannedQueryPermissions<CopyInfo>
|
||||
{
|
||||
private GetCopiesCannedQuery(CannedQueryParameters parameters, MethodSecurityBean<CopyInfo> methodSecurity)
|
||||
{
|
||||
super(parameters, methodSecurity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<CopyInfo> queryAndFilter(CannedQueryParameters parameters)
|
||||
{
|
||||
CopyCannedQueryDetail detail = GetCopiesCannedQueryFactory.this.getDetail(parameters);
|
||||
// Build parameters
|
||||
CopyParametersEntity queryParameters = new CopyParametersEntity();
|
||||
// Original node
|
||||
Pair<Long, NodeRef> originalNodePair = nodeDAO.getNodePair(detail.originalNodeRef);
|
||||
if (originalNodePair == null)
|
||||
{
|
||||
return Collections.emptyList(); // Shortcut
|
||||
}
|
||||
queryParameters.setOriginalNodeId(originalNodePair.getFirst());
|
||||
// cm:original association type ID
|
||||
Pair<Long, QName> assocTypeQNamePair = qnameDAO.getQName(ContentModel.ASSOC_ORIGINAL);
|
||||
if (assocTypeQNamePair == null)
|
||||
{
|
||||
return Collections.emptyList(); // Shortcut
|
||||
}
|
||||
queryParameters.setOriginalAssocTypeId(assocTypeQNamePair.getFirst());
|
||||
// cm:name property ID
|
||||
Pair<Long, QName> propQNamePair = qnameDAO.getQName(ContentModel.PROP_NAME);
|
||||
if (propQNamePair == null)
|
||||
{
|
||||
return Collections.emptyList(); // Shortcut
|
||||
}
|
||||
queryParameters.setNamePropId(propQNamePair.getFirst());
|
||||
// Copied parent node
|
||||
if (detail.copyParentNodeRef != null)
|
||||
{
|
||||
Pair<Long, NodeRef> copyParentNodePair = nodeDAO.getNodePair(detail.copyParentNodeRef);
|
||||
if (copyParentNodePair == null)
|
||||
{
|
||||
return Collections.emptyList(); // Shortcut
|
||||
}
|
||||
queryParameters.setCopyParentNodeId(copyParentNodePair.getFirst());
|
||||
}
|
||||
// Now query
|
||||
int resultsRequired = parameters.getResultsRequired();
|
||||
List<CopyEntity> copies = cannedQueryDAO.executeQuery(
|
||||
"alfresco.query.copy", "select_GetCopies",
|
||||
queryParameters,
|
||||
0, resultsRequired);
|
||||
// Convert them
|
||||
List<CopyInfo> results = new ArrayList<CopyService.CopyInfo>(copies.size());
|
||||
for (CopyEntity copy : copies)
|
||||
{
|
||||
CopyInfo result = new CopyInfo(copy.getCopy().getNodeRef(), copy.getCopyName());
|
||||
results.add(result);
|
||||
}
|
||||
// Done
|
||||
return results;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user