diff --git a/source/java/org/alfresco/repo/transfer/ChangeCapturingProgressMonitor.java b/source/java/org/alfresco/repo/transfer/ChangeCapturingProgressMonitor.java new file mode 100644 index 0000000000..6f7a7c3e9d --- /dev/null +++ b/source/java/org/alfresco/repo/transfer/ChangeCapturingProgressMonitor.java @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2009-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 . + */ +package org.alfresco.repo.transfer; + +import java.io.InputStream; +import java.util.LinkedList; +import java.util.List; +import java.util.TreeMap; + +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.Path; +import org.alfresco.service.cmr.transfer.TransferException; +import org.alfresco.service.cmr.transfer.TransferProgress; +import org.alfresco.service.cmr.transfer.TransferProgress.Status; + +/** + * A delegating implementation of the {@link TransferProgressMonitor} interface that + * keeps a record of the nodes that have been changed during the course of processing + * an incoming transfer. Used by the {@link RepoTransferReceiverImpl}. + * @author Brian + * @since 3.4 + */ +/*package*/ final class ChangeCapturingProgressMonitor implements TransferProgressMonitor +{ + private final TransferProgressMonitor delegate; + + public static class TransferChangesRecord + { + private final List createdNodes = new LinkedList(); + private final List updatedNodes = new LinkedList(); + private final List deletedNodes = new LinkedList(); + + public List getCreatedNodes() + { + return createdNodes; + } + + public List getUpdatedNodes() + { + return updatedNodes; + } + + public List getDeletedNodes() + { + return deletedNodes; + } + + public void addDeletedNode(NodeRef nodeRef) + { + deletedNodes.add(nodeRef); + } + + public void addUpdatedNode(NodeRef nodeRef) + { + updatedNodes.add(nodeRef); + } + + public void addCreatedNode(NodeRef nodeRef) + { + createdNodes.add(nodeRef); + } + + public void reset() + { + createdNodes.clear(); + updatedNodes.clear(); + deletedNodes.clear(); + } + } + + private final TreeMap changeRecords = new TreeMap(); + + public ChangeCapturingProgressMonitor(TransferProgressMonitor delegatedProgressMonitor) + { + delegate = delegatedProgressMonitor; + } + + public InputStream getLogInputStream(String transferId) throws TransferException + { + return delegate.getLogInputStream(transferId); + } + + public TransferProgress getProgress(String transferId) throws TransferException + { + return delegate.getProgress(transferId); + } + + public void logComment(String transferId, Object obj) throws TransferException + { + delegate.logComment(transferId, obj); + } + + public void logCreated(String transferId, NodeRef sourceNode, NodeRef destNode, NodeRef newParent, Path newPath, + boolean orphan) + { + delegate.logCreated(transferId, sourceNode, destNode, newParent, newPath, orphan); + getChangesRecord(transferId).addCreatedNode(destNode); + } + + public void logDeleted(String transferId, NodeRef sourceNode, NodeRef destNode, Path parentPath) + { + delegate.logDeleted(transferId, sourceNode, destNode, parentPath); + getChangesRecord(transferId).addDeletedNode(destNode); + } + + public void logException(String transferId, Object obj, Throwable ex) throws TransferException + { + delegate.logException(transferId, obj, ex); + } + + public void logMoved(String transferId, NodeRef sourceNodeRef, NodeRef destNodeRef, Path oldPath, + NodeRef newParent, Path newPath) + { + delegate.logMoved(transferId, sourceNodeRef, destNodeRef, oldPath, newParent, newPath); + } + + public void logUpdated(String transferId, NodeRef sourceNode, NodeRef destNode, Path parentPath) + { + delegate.logUpdated(transferId, sourceNode, destNode, parentPath); + getChangesRecord(transferId).addUpdatedNode(destNode); + } + + public void updateProgress(String transferId, int currPos, int endPos) throws TransferException + { + delegate.updateProgress(transferId, currPos, endPos); + } + + public void updateProgress(String transferId, int currPos) throws TransferException + { + delegate.updateProgress(transferId, currPos); + } + + public void updateStatus(String transferId, Status status) throws TransferException + { + delegate.updateStatus(transferId, status); + //If we are entering a "don't commit" state then reset the changes record + //for this transfer, since the effective result is "no change". + if (status == Status.CANCELLED || status == Status.ERROR) + { + getChangesRecord(transferId).reset(); + } + } + + public TransferChangesRecord removeChangeRecord(String transferId) + { + return changeRecords.remove(transferId); + } + + private TransferChangesRecord getChangesRecord(String transferId) + { + TransferChangesRecord record = changeRecords.get(transferId); + if (record == null) + { + record = new TransferChangesRecord(); + changeRecords.put(transferId, record); + } + return record; + } +} diff --git a/source/java/org/alfresco/repo/transfer/RepoTransferReceiverImpl.java b/source/java/org/alfresco/repo/transfer/RepoTransferReceiverImpl.java index 8e96043bec..0582ba43be 100644 --- a/source/java/org/alfresco/repo/transfer/RepoTransferReceiverImpl.java +++ b/source/java/org/alfresco/repo/transfer/RepoTransferReceiverImpl.java @@ -26,16 +26,14 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Serializable; -import java.io.Writer; import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; -import java.util.Iterator; +import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Vector; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import javax.xml.parsers.SAXParser; @@ -46,20 +44,19 @@ import org.alfresco.repo.copy.CopyBehaviourCallback; import org.alfresco.repo.copy.CopyDetails; import org.alfresco.repo.copy.CopyServicePolicies; import org.alfresco.repo.copy.DefaultCopyBehaviourCallback; -import org.alfresco.repo.copy.CopyServicePolicies.BeforeCopyPolicy; import org.alfresco.repo.node.NodeServicePolicies; -import org.alfresco.repo.node.NodeServicePolicies.OnMoveNodePolicy; import org.alfresco.repo.policy.BehaviourFilter; +import org.alfresco.repo.policy.ClassPolicyDelegate; import org.alfresco.repo.policy.JavaBehaviour; import org.alfresco.repo.policy.PolicyComponent; import org.alfresco.repo.policy.Behaviour.NotificationFrequency; -import org.alfresco.repo.rule.RuleModel; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.repo.tenant.TenantService; import org.alfresco.repo.transaction.AlfrescoTransactionSupport; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.repo.transfer.ChangeCapturingProgressMonitor.TransferChangesRecord; import org.alfresco.repo.transfer.manifest.TransferManifestProcessor; import org.alfresco.repo.transfer.manifest.XMLTransferManifestReader; import org.alfresco.repo.transfer.requisite.XMLTransferRequsiteWriter; @@ -76,7 +73,11 @@ import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.transfer.TransferException; import org.alfresco.service.cmr.transfer.TransferProgress; import org.alfresco.service.cmr.transfer.TransferReceiver; +import org.alfresco.service.cmr.transfer.TransferServicePolicies; import org.alfresco.service.cmr.transfer.TransferProgress.Status; +import org.alfresco.service.cmr.transfer.TransferServicePolicies.BeforeStartInboundTransferPolicy; +import org.alfresco.service.cmr.transfer.TransferServicePolicies.OnEndInboundTransferPolicy; +import org.alfresco.service.cmr.transfer.TransferServicePolicies.OnStartInboundTransferPolicy; import org.alfresco.service.descriptor.DescriptorService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; @@ -166,7 +167,7 @@ public class RepoTransferReceiverImpl implements TransferReceiver, private String transferTempFolderPath; private ManifestProcessorFactory manifestProcessorFactory; private BehaviourFilter behaviourFilter; - private TransferProgressMonitor progressMonitor; + private ChangeCapturingProgressMonitor progressMonitor; private ActionService actionService; private TenantService tenantService; private RuleService ruleService; @@ -180,6 +181,10 @@ public class RepoTransferReceiverImpl implements TransferReceiver, private Map transferTempFolderMap = new ConcurrentHashMap(); private Map inboundTransferRecordsFolderMap = new ConcurrentHashMap(); + private ClassPolicyDelegate beforeStartInboundTransferDelegate; + private ClassPolicyDelegate onStartInboundTransferDelegate; + private ClassPolicyDelegate onEndInboundTransferDelegate; + public void init() { PropertyCheck.mandatory(this, "nodeService", nodeService); @@ -195,7 +200,11 @@ public class RepoTransferReceiverImpl implements TransferReceiver, PropertyCheck.mandatory(this, "policyComponent", policyComponent); PropertyCheck.mandatory(this, "descriptorService", descriptorService); PropertyCheck.mandatory(this, "alienProcessor", alienProcessor); - + + beforeStartInboundTransferDelegate = policyComponent.registerClassPolicy(TransferServicePolicies.BeforeStartInboundTransferPolicy.class); + onStartInboundTransferDelegate = policyComponent.registerClassPolicy(TransferServicePolicies.OnStartInboundTransferPolicy.class); + onEndInboundTransferDelegate = policyComponent.registerClassPolicy(TransferServicePolicies.OnEndInboundTransferPolicy.class); + /** * For every new child of a node with the trx:transferred aspect run this.onCreateChildAssociation */ @@ -363,22 +372,27 @@ public class RepoTransferReceiverImpl implements TransferReceiver, public String start() { final NodeRef lockFolder = getLockFolder(); - NodeRef relatedTransferRecord = null; + String transferId = null; RetryingTransactionHelper txHelper = transactionService.getRetryingTransactionHelper(); try { - relatedTransferRecord = txHelper.doInTransaction( - new RetryingTransactionHelper.RetryingTransactionCallback() + transferId = txHelper.doInTransaction( + new RetryingTransactionHelper.RetryingTransactionCallback() { - public NodeRef execute() throws Throwable + public String execute() throws Throwable { + TransferServicePolicies.BeforeStartInboundTransferPolicy beforeStartPolicy = + beforeStartInboundTransferDelegate.get(TransferModel.TYPE_TRANSFER_RECORD); + beforeStartPolicy.beforeStartInboundTransfer(); + final NodeRef relatedTransferRecord = createTransferRecord(); - getTempFolder(relatedTransferRecord.toString()); + String transferId = relatedTransferRecord.toString(); + getTempFolder(transferId); Map props = new HashMap(); props.put(ContentModel.PROP_NAME, LOCK_FILE_NAME); - props.put(TransferModel.PROP_TRANSFER_ID, relatedTransferRecord.toString()); + props.put(TransferModel.PROP_TRANSFER_ID, transferId); if (log.isInfoEnabled()) { @@ -393,7 +407,12 @@ public class RepoTransferReceiverImpl implements TransferReceiver, { log.info("Transfer lock created as node " + assoc.getChildRef()); } - return relatedTransferRecord; + + TransferServicePolicies.OnStartInboundTransferPolicy onStartPolicy = + onStartInboundTransferDelegate.get(TransferModel.TYPE_TRANSFER_RECORD); + onStartPolicy.onStartInboundTransfer(transferId); + + return transferId; } }, false, true); } @@ -403,7 +422,6 @@ public class RepoTransferReceiverImpl implements TransferReceiver, // lock is already taken. throw new TransferException(MSG_TRANSFER_LOCK_UNAVAILABLE); } - String transferId = relatedTransferRecord.toString(); getStagingFolder(transferId); return transferId; } @@ -448,6 +466,7 @@ public class RepoTransferReceiverImpl implements TransferReceiver, ChildAssociationRef assoc = nodeService.createNode(inboundTransferRecordsFolder, ContentModel.ASSOC_CONTAINS, recordName, TransferModel.TYPE_TRANSFER_RECORD, props); log.debug("<-createTransferRecord: " + assoc.getChildRef()); + return assoc.getChildRef(); } @@ -502,14 +521,39 @@ public class RepoTransferReceiverImpl implements TransferReceiver, } catch (Exception ex) { - log.warn("Failed to delete temp store node for transfer id " + transferId + "\nTemp store noderef = " + tempStoreNode); + log.warn("Failed to delete temp store node for transfer id " + transferId + + "\nTemp store noderef = " + tempStoreNode); } - log.debug("delete staging folder " + transferId); - // Delete the staging folder. - File stagingFolder = getStagingFolder(transferId); - deleteFile(stagingFolder); - log.debug("Staging folder deleted"); + File stagingFolder = null; + try + { + log.debug("delete staging folder " + transferId); + // Delete the staging folder. + stagingFolder = getStagingFolder(transferId); + deleteFile(stagingFolder); + log.debug("Staging folder deleted"); + } + catch(Exception ex) + { + log.warn("Failed to delete staging folder for transfer id " + transferId + + "\nStaging folder = " + stagingFolder.toString()); + } + + //Fire the OnEndInboundTransfer policy + Set createdNodes = Collections.emptySet(); + Set updatedNodes = Collections.emptySet(); + Set deletedNodes = Collections.emptySet(); + TransferChangesRecord changesRecord = progressMonitor.removeChangeRecord(transferId); + if (changesRecord != null) + { + createdNodes = new HashSet(changesRecord.getCreatedNodes()); + updatedNodes = new HashSet(changesRecord.getUpdatedNodes()); + deletedNodes = new HashSet(changesRecord.getDeletedNodes()); + } + TransferServicePolicies.OnEndInboundTransferPolicy onEndPolicy = + onEndInboundTransferDelegate.get(TransferModel.TYPE_TRANSFER_RECORD); + onEndPolicy.onEndInboundTransfer(transferId, createdNodes, updatedNodes, deletedNodes); } catch (TransferException ex) { @@ -913,7 +957,7 @@ public class RepoTransferReceiverImpl implements TransferReceiver, */ public void setProgressMonitor(TransferProgressMonitor progressMonitor) { - this.progressMonitor = progressMonitor; + this.progressMonitor = new ChangeCapturingProgressMonitor(progressMonitor); } public void setActionService(ActionService actionService) @@ -1044,7 +1088,6 @@ public class RepoTransferReceiverImpl implements TransferReceiver, public void onRestoreNode(ChildAssociationRef childAssocRef) { log.debug("on restore node"); - final String localRepositoryId = descriptorService.getCurrentRepositoryDescriptor().getId(); log.debug("restoredAssocRef:" + childAssocRef); alienProcessor.afterMoveAlien(childAssocRef); } diff --git a/source/java/org/alfresco/repo/transfer/RepoTransferReceiverImplTest.java b/source/java/org/alfresco/repo/transfer/RepoTransferReceiverImplTest.java index 84b2f9490c..3fd2834506 100644 --- a/source/java/org/alfresco/repo/transfer/RepoTransferReceiverImplTest.java +++ b/source/java/org/alfresco/repo/transfer/RepoTransferReceiverImplTest.java @@ -18,6 +18,8 @@ */ package org.alfresco.repo.transfer; +import static org.mockito.Mockito.*; + import java.io.ByteArrayInputStream; import java.io.File; import java.io.Serializable; @@ -32,6 +34,9 @@ import java.util.Map; import java.util.Set; import org.alfresco.model.ContentModel; +import org.alfresco.repo.policy.JavaBehaviour; +import org.alfresco.repo.policy.PolicyComponent; +import org.alfresco.repo.policy.Behaviour.NotificationFrequency; import org.alfresco.repo.security.authentication.AuthenticationComponent; import org.alfresco.repo.transfer.manifest.TransferManifestDeletedNode; import org.alfresco.repo.transfer.manifest.TransferManifestHeader; @@ -52,6 +57,7 @@ import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.security.MutableAuthenticationService; import org.alfresco.service.cmr.transfer.TransferException; import org.alfresco.service.cmr.transfer.TransferProgress; +import org.alfresco.service.cmr.transfer.TransferServicePolicies; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.service.transaction.TransactionService; @@ -60,6 +66,7 @@ import org.alfresco.util.GUID; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.tools.ant.filters.StringInputStream; +import org.mockito.ArgumentCaptor; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.support.DefaultTransactionDefinition; @@ -80,6 +87,7 @@ public class RepoTransferReceiverImplTest extends BaseAlfrescoSpringTest private String dummyContent; private byte[] dummyContentBytes; private NodeRef guestHome; + private PolicyComponent policyComponent; @Override public void runBare() throws Throwable @@ -106,6 +114,7 @@ public class RepoTransferReceiverImplTest extends BaseAlfrescoSpringTest this.authenticationComponent = (AuthenticationComponent) this.applicationContext .getBean("authenticationComponent"); this.receiver = (RepoTransferReceiverImpl) this.getApplicationContext().getBean("transferReceiver"); + this.policyComponent = (PolicyComponent) this.getApplicationContext().getBean("policyComponent"); this.searchService = (SearchService) this.getApplicationContext().getBean("searchService"); this.dummyContent = "This is some dummy content."; this.dummyContentBytes = dummyContent.getBytes("UTF-8"); @@ -402,8 +411,17 @@ public class RepoTransferReceiverImplTest extends BaseAlfrescoSpringTest } + @SuppressWarnings("unchecked") public void testNodeDeleteAndRestore() throws Exception { + TransferServicePolicies.OnEndInboundTransferPolicy mockedPolicyHandler = + mock(TransferServicePolicies.OnEndInboundTransferPolicy.class); + + policyComponent.bindClassBehaviour( + TransferServicePolicies.OnEndInboundTransferPolicy.QNAME, + TransferModel.TYPE_TRANSFER_RECORD, + new JavaBehaviour(mockedPolicyHandler, "onEndInboundTransfer", NotificationFrequency.EVERY_EVENT)); + log.info("testNodeDeleteAndRestore"); setDefaultRollback(true); @@ -461,9 +479,21 @@ public class RepoTransferReceiverImplTest extends BaseAlfrescoSpringTest assertTrue(nodeService.getAspects(node1.getNodeRef()).contains(ContentModel.ASPECT_ATTACHABLE)); assertFalse(nodeService.getSourceAssocs(node2.getNodeRef(), ContentModel.ASSOC_ATTACHMENTS).isEmpty()); + + ArgumentCaptor transferIdCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor createdNodesCaptor = ArgumentCaptor.forClass(Set.class); + ArgumentCaptor updatedNodesCaptor = ArgumentCaptor.forClass(Set.class); + ArgumentCaptor deletedNodesCaptor = ArgumentCaptor.forClass(Set.class); + verify(mockedPolicyHandler, times(1)).onEndInboundTransfer(transferIdCaptor.capture(), + createdNodesCaptor.capture(), updatedNodesCaptor.capture(), deletedNodesCaptor.capture()); + assertEquals(transferId, transferIdCaptor.getValue()); + Set capturedCreatedNodes = createdNodesCaptor.getValue(); + assertEquals(nodes.size(), capturedCreatedNodes.size()); + for (TransferManifestNode node : nodes) { assertTrue(nodeService.exists(node.getNodeRef())); + assertTrue(capturedCreatedNodes.contains(node.getNodeRef())); } } finally @@ -471,6 +501,8 @@ public class RepoTransferReceiverImplTest extends BaseAlfrescoSpringTest endTransaction(); } + reset(mockedPolicyHandler); + startNewTransaction(); try { @@ -481,6 +513,19 @@ public class RepoTransferReceiverImplTest extends BaseAlfrescoSpringTest log.debug(snapshot); receiver.saveSnapshot(transferId, new StringInputStream(snapshot, "UTF-8")); receiver.commit(transferId); + + ArgumentCaptor transferIdCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor createdNodesCaptor = ArgumentCaptor.forClass(Set.class); + ArgumentCaptor updatedNodesCaptor = ArgumentCaptor.forClass(Set.class); + ArgumentCaptor deletedNodesCaptor = ArgumentCaptor.forClass(Set.class); + verify(mockedPolicyHandler, times(1)).onEndInboundTransfer(transferIdCaptor.capture(), + createdNodesCaptor.capture(), updatedNodesCaptor.capture(), deletedNodesCaptor.capture()); + assertEquals(transferId, transferIdCaptor.getValue()); + Set capturedDeletedNodes = deletedNodesCaptor.getValue(); + assertEquals(3, capturedDeletedNodes.size()); + assertTrue(capturedDeletedNodes.contains(deletedNode8.getNodeRef())); + assertTrue(capturedDeletedNodes.contains(deletedNode2.getNodeRef())); + assertTrue(capturedDeletedNodes.contains(deletedNode11.getNodeRef())); } finally { @@ -494,17 +539,21 @@ public class RepoTransferReceiverImplTest extends BaseAlfrescoSpringTest TransferProgress progress = receiver.getProgressMonitor().getProgress(transferId); assertEquals(TransferProgress.Status.COMPLETE, progress.getStatus()); - assertTrue(nodeService.exists(deletedNode8.getNodeRef())); - assertTrue(nodeService.hasAspect(deletedNode8.getNodeRef(), ContentModel.ASPECT_ARCHIVED)); - log.debug("Successfully tested existence of archive node: " + deletedNode8.getNodeRef()); - - assertTrue(nodeService.exists(deletedNode2.getNodeRef())); - assertTrue(nodeService.hasAspect(deletedNode2.getNodeRef(), ContentModel.ASPECT_ARCHIVED)); - log.debug("Successfully tested existence of archive node: " + deletedNode2.getNodeRef()); + NodeRef archiveNode8 = new NodeRef(StoreRef.STORE_REF_ARCHIVE_SPACESSTORE, node8.getNodeRef().getId()); + NodeRef archiveNode2 = new NodeRef(StoreRef.STORE_REF_ARCHIVE_SPACESSTORE, node2.getNodeRef().getId()); + NodeRef archiveNode11 = new NodeRef(StoreRef.STORE_REF_ARCHIVE_SPACESSTORE, node11.getNodeRef().getId()); - assertTrue(nodeService.exists(deletedNode11.getNodeRef())); - assertTrue(nodeService.hasAspect(deletedNode11.getNodeRef(), ContentModel.ASPECT_ARCHIVED)); - log.debug("Successfully tested existence of archive node: " + deletedNode11.getNodeRef()); + assertTrue(nodeService.exists(archiveNode8)); + assertTrue(nodeService.hasAspect(archiveNode8, ContentModel.ASPECT_ARCHIVED)); + log.debug("Successfully tested existence of archive node: " + archiveNode8); + + assertTrue(nodeService.exists(archiveNode2)); + assertTrue(nodeService.hasAspect(archiveNode2, ContentModel.ASPECT_ARCHIVED)); + log.debug("Successfully tested existence of archive node: " + archiveNode2); + + assertTrue(nodeService.exists(archiveNode11)); + assertTrue(nodeService.hasAspect(archiveNode11, ContentModel.ASPECT_ARCHIVED)); + log.debug("Successfully tested existence of archive node: " + archiveNode11); log.debug("Successfully tested existence of all archive nodes"); @@ -527,6 +576,8 @@ public class RepoTransferReceiverImplTest extends BaseAlfrescoSpringTest } System.out.println("Now try to restore orphan node 2."); + reset(mockedPolicyHandler); + String errorMsgId = null; startNewTransaction(); try @@ -546,8 +597,20 @@ public class RepoTransferReceiverImplTest extends BaseAlfrescoSpringTest { // Expected errorMsgId = ex.getMsgId(); - } + ArgumentCaptor transferIdCaptor = ArgumentCaptor.forClass(String.class); + ArgumentCaptor createdNodesCaptor = ArgumentCaptor.forClass(Set.class); + ArgumentCaptor updatedNodesCaptor = ArgumentCaptor.forClass(Set.class); + ArgumentCaptor deletedNodesCaptor = ArgumentCaptor.forClass(Set.class); + + verify(mockedPolicyHandler, times(1)).onEndInboundTransfer(transferIdCaptor.capture(), + createdNodesCaptor.capture(), updatedNodesCaptor.capture(), deletedNodesCaptor.capture()); + + assertEquals(transferId, transferIdCaptor.getValue()); + assertTrue(createdNodesCaptor.getValue().isEmpty()); + assertTrue(updatedNodesCaptor.getValue().isEmpty()); + assertTrue(deletedNodesCaptor.getValue().isEmpty()); + } } catch (Exception ex) { @@ -679,8 +742,9 @@ public class RepoTransferReceiverImplTest extends BaseAlfrescoSpringTest TransferProgress progress = receiver.getProgressMonitor().getProgress(transferId); assertEquals(TransferProgress.Status.COMPLETE, progress.getStatus()); - assertTrue(nodeService.exists(deletedNode11.getNodeRef())); - assertTrue(nodeService.hasAspect(deletedNode11.getNodeRef(), ContentModel.ASPECT_ARCHIVED)); + NodeRef archivedNodeRef = new NodeRef(StoreRef.STORE_REF_ARCHIVE_SPACESSTORE, deletedNode11.getNodeRef().getId()); + assertTrue(nodeService.exists(archivedNodeRef)); + assertTrue(nodeService.hasAspect(archivedNodeRef, ContentModel.ASPECT_ARCHIVED)); log.debug("Successfully tested existence of archive node: " + deletedNode11.getNodeRef()); log.debug("Successfully tested existence of all archive nodes"); @@ -699,7 +763,6 @@ public class RepoTransferReceiverImplTest extends BaseAlfrescoSpringTest //Finally we transfer node2 and node11 (in that order) - String errorMsgId = null; startNewTransaction(); try { @@ -820,7 +883,7 @@ public class RepoTransferReceiverImplTest extends BaseAlfrescoSpringTest private TransferManifestDeletedNode createDeletedNode(TransferManifestNode nodeToDelete) { TransferManifestDeletedNode deletedNode = new TransferManifestDeletedNode(); - deletedNode.setNodeRef(new NodeRef(StoreRef.STORE_REF_ARCHIVE_SPACESSTORE, nodeToDelete.getNodeRef().getId())); + deletedNode.setNodeRef(nodeToDelete.getNodeRef()); deletedNode.setParentPath(nodeToDelete.getParentPath()); deletedNode.setPrimaryParentAssoc(nodeToDelete.getPrimaryParentAssoc()); deletedNode.setUuid(nodeToDelete.getUuid()); diff --git a/source/java/org/alfresco/service/cmr/transfer/TransferServicePolicies.java b/source/java/org/alfresco/service/cmr/transfer/TransferServicePolicies.java new file mode 100644 index 0000000000..6e16f90f19 --- /dev/null +++ b/source/java/org/alfresco/service/cmr/transfer/TransferServicePolicies.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2009-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 . + */ +package org.alfresco.service.cmr.transfer; + +import java.util.Set; + +import org.alfresco.repo.policy.ClassPolicy; +import org.alfresco.repo.transfer.TransferModel; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; + +/** + * Policies raised by the transfer service. + * @author Brian + * + */ +public interface TransferServicePolicies +{ + /** + * Invoked immediately before processing of a new inbound transfer is started. + * Reported against the "trx:transferRecord" type ({@link TransferModel#TYPE_TRANSFER_RECORD} + */ + public interface BeforeStartInboundTransferPolicy extends ClassPolicy + { + public static final QName QNAME = QName.createQName(NamespaceService.ALFRESCO_URI, "beforeStartInboundTransfer"); + + /** + * Invoked immediately before processing of a new inbound transfer is started. + * Reported against the "trx:transferRecord" type ({@link TransferModel#TYPE_TRANSFER_RECORD} + */ + public void beforeStartInboundTransfer(); + } + + /** + * Invoked immediately after processing of a new inbound transfer is started. This policy is + * invoked within the transaction on which the transfer lock is written. + * Reported against the "trx:transferRecord" type ({@link TransferModel#TYPE_TRANSFER_RECORD} + */ + public interface OnStartInboundTransferPolicy extends ClassPolicy + { + public static final QName QNAME = QName.createQName(NamespaceService.ALFRESCO_URI, "onStartInboundTransfer"); + + /** + * Invoked immediately after processing of a new inbound transfer is started. This policy is + * invoked within the transaction on which the transfer lock is written. + * Reported against the "trx:transferRecord" type ({@link TransferModel#TYPE_TRANSFER_RECORD} + * @param transferId The identifier of the transfer that has been started + */ + public void onStartInboundTransfer(String transferId); + } + + /** + * Invoked immediately after completion of processing of an inbound transfer. + * Reported against the "trx:transferRecord" type ({@link TransferModel#TYPE_TRANSFER_RECORD} + */ + public interface OnEndInboundTransferPolicy extends ClassPolicy + { + public static final QName QNAME = QName.createQName(NamespaceService.ALFRESCO_URI, "onEndInboundTransfer"); + + /** + * Invoked immediately after completion of processing of an inbound transfer. + * Reported against the "trx:transferRecord" type ({@link TransferModel#TYPE_TRANSFER_RECORD} + * @param transferId The identifier of transfer that has ended + * @param createdNodes The set of nodes that have been created by this transfer + * @param updatedNodes The set of nodes that have been updated by this transfer + * @param deletedNodes The set of nodes that have been deleted by this transfer + */ + public void onEndInboundTransfer(String transferId, Set createdNodes, + Set updatedNodes, Set deletedNodes); + } +}