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);
+ }
+}