diff --git a/config/alfresco/messages/transfer-model.properties b/config/alfresco/messages/transfer-model.properties
index f41b3fa067..9cdf74381f 100644
--- a/config/alfresco/messages/transfer-model.properties
+++ b/config/alfresco/messages/transfer-model.properties
@@ -23,6 +23,9 @@ trx_applicationmodel.type.trx_transferReportDest.description=Transfer Report Fro
trx_applicationmodel.type.trx_transferTarget.title=Transfer Target
trx_applicationmodel.type.trx_transferTarget.description=The definition of a transfer target
+trx_applicationmodel.type.trx_fileTransferTarget.title=File Transfer Target
+trx_applicationmodel.type.trx_fileTransferTarget.description=The definition of a file transfer target
+
trx_applicationmodel.property.trx_endpointhost.title=Endpoint Host
trx_applicationmodel.property.trx_endpointhost.description=Endpoint Host
@@ -71,6 +74,9 @@ trx_applicationmodel.property.trx_fromContent.description=The content URLs trans
trx_applicationmodel.association.trx_orphan.title=Transfer Orphan
trx_applicationmodel.association.trx_orphan.description=Transfer Orphan
+trx_applicationmodel.association.trx_fileTransferRootNode.title=Root Folder
+trx_applicationmodel.association.trx_fileTransferRootNode.description=The local folder node that corresponds to the target's root folder
+
trx_applicationmodel.aspect.trx_transferRelated.title=Transfer Related
trx_applicationmodel.aspect.trx_transferRelated.description=Nodes with this aspect are related to a particular transfer.
diff --git a/config/alfresco/model/transferModel.xml b/config/alfresco/model/transferModel.xml
index c1ca166574..2672285b38 100644
--- a/config/alfresco/model/transferModel.xml
+++ b/config/alfresco/model/transferModel.xml
@@ -96,6 +96,25 @@
+
+ File Transfer Target
+ Used to model a file transfer receiver with its corresponding root node
+ trx:transferTarget
+
+
+
+ false
+ true
+
+
+ cm:folder
+ false
+ true
+
+
+
+
+
@@ -185,24 +204,6 @@
-
- File Transfer Target
- Aspect used to model a receiving root for file transfer
-
-
-
- false
- true
-
-
- cm:folder
- false
- true
-
-
-
-
-
Nodes with this aspect are related to a particular transfer.
diff --git a/source/java/org/alfresco/repo/transfer/HttpClientTransmitterImpl.java b/source/java/org/alfresco/repo/transfer/HttpClientTransmitterImpl.java
index 19052fe495..108fe88225 100644
--- a/source/java/org/alfresco/repo/transfer/HttpClientTransmitterImpl.java
+++ b/source/java/org/alfresco/repo/transfer/HttpClientTransmitterImpl.java
@@ -19,14 +19,10 @@
package org.alfresco.repo.transfer;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
import java.io.OutputStream;
-import java.io.OutputStreamWriter;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
@@ -47,7 +43,6 @@ import org.alfresco.service.cmr.transfer.TransferException;
import org.alfresco.service.cmr.transfer.TransferProgress;
import org.alfresco.service.cmr.transfer.TransferTarget;
import org.alfresco.service.cmr.transfer.TransferVersion;
-import org.alfresco.service.descriptor.DescriptorService;
import org.alfresco.util.PropertyCheck;
import org.alfresco.util.json.ExceptionJsonSerializer;
import org.alfresco.util.json.JsonSerializer;
@@ -771,7 +766,7 @@ public class HttpClientTransmitterImpl implements TransferTransmitter
private NodeRef getFileTransferRootNodeRef(NodeRef transferNodeRef)
{
//testing if transferring to file system
- if(!nodeService.hasAspect(transferNodeRef, TransferModel.ASPECT_FILE_TRANSFER_TARGET))
+ if(!TransferModel.TYPE_FILE_TRANSFER_TARGET.equals(nodeService.getType(transferNodeRef)))
return null;
//get association
diff --git a/source/java/org/alfresco/repo/transfer/HttpClientTransmitterImplTest.java b/source/java/org/alfresco/repo/transfer/HttpClientTransmitterImplTest.java
index d578cae5be..b3e4e457bd 100644
--- a/source/java/org/alfresco/repo/transfer/HttpClientTransmitterImplTest.java
+++ b/source/java/org/alfresco/repo/transfer/HttpClientTransmitterImplTest.java
@@ -88,8 +88,7 @@ public class HttpClientTransmitterImplTest extends TestCase
transmitter.setHttpMethodFactory(mockedHttpMethodFactory);
this.mockedNodeService = mock(NodeService.class);
- when(mockedNodeService.hasAspect(any(NodeRef.class),
- eq(TransferModel.ASPECT_FILE_TRANSFER_TARGET))).thenReturn(false);
+ when(mockedNodeService.getType(any(NodeRef.class))).thenReturn(TransferModel.TYPE_TRANSFER_TARGET);
transmitter.setNodeService(mockedNodeService);
this.target = new TransferTargetImpl();
diff --git a/source/java/org/alfresco/repo/transfer/TransferModel.java b/source/java/org/alfresco/repo/transfer/TransferModel.java
index d0d57cb007..d9b42877ed 100644
--- a/source/java/org/alfresco/repo/transfer/TransferModel.java
+++ b/source/java/org/alfresco/repo/transfer/TransferModel.java
@@ -50,8 +50,8 @@ public interface TransferModel
/**
* Aspect : fileTransferTarget
*/
- static final QName ASPECT_FILE_TRANSFER_TARGET = QName.createQName(TRANSFER_MODEL_1_0_URI, "fileTransferTarget");
- static final QName ASSOC_ROOT_FILE_TRANSFER = QName.createQName(TRANSFER_MODEL_1_0_URI, "rootFileTransfer");
+ static final QName TYPE_FILE_TRANSFER_TARGET = QName.createQName(TRANSFER_MODEL_1_0_URI, "fileTransferTarget");
+ static final QName ASSOC_ROOT_FILE_TRANSFER = QName.createQName(TRANSFER_MODEL_1_0_URI, "fileTransferRootNode");
/*
* Type : Transfer Group
diff --git a/source/java/org/alfresco/repo/transfer/TransferServiceImpl2.java b/source/java/org/alfresco/repo/transfer/TransferServiceImpl2.java
index 4be51bb9f2..fbc4f78ffc 100644
--- a/source/java/org/alfresco/repo/transfer/TransferServiceImpl2.java
+++ b/source/java/org/alfresco/repo/transfer/TransferServiceImpl2.java
@@ -929,13 +929,23 @@ public class TransferServiceImpl2 implements TransferService2
{
// which nodes to write to the snapshot
Setnodes = definition.getNodes();
+ SetnodesToRemove = definition.getNodesToRemove();
- if(nodes == null || nodes.size() == 0)
+ if((nodes == null || nodes.size() == 0) && (nodesToRemove == null || nodesToRemove.size() == 0))
{
logger.debug("no nodes to transfer");
throw new TransferException(MSG_NO_NODES);
}
-
+
+ //If a noderef exists in both the "nodes" set and the "nodesToRemove" set then the nodesToRemove wins. It is removed
+ //from the "nodes" set...
+ if (nodes != null && nodesToRemove != null)
+ {
+ nodes.removeAll(nodesToRemove);
+ }
+
+ int nodeCount = ((nodes == null) ? 0 : nodes.size()) + ((nodesToRemove == null) ? 0 : nodesToRemove.size());
+
/**
* create snapshot
*/
@@ -952,15 +962,27 @@ public class TransferServiceImpl2 implements TransferService2
header.setRepositoryId(repositoryId);
header.setTransferVersion(fromVersion);
header.setCreatedDate(new Date());
- header.setNodeCount(nodes.size());
+ header.setNodeCount(nodeCount);
header.setSync(definition.isSync());
header.setReadOnly(definition.isReadOnly());
formatter.startTransferManifest(snapshotWriter);
formatter.writeTransferManifestHeader(header);
- for(NodeRef nodeRef : nodes)
+ if (nodes != null)
{
- TransferManifestNode node = transferManifestNodeFactory.createTransferManifestNode(nodeRef, definition);
- formatter.writeTransferManifestNode(node);
+ for (NodeRef nodeRef : nodes)
+ {
+ TransferManifestNode node = transferManifestNodeFactory.createTransferManifestNode(nodeRef, definition);
+ formatter.writeTransferManifestNode(node);
+ }
+ }
+ if (nodesToRemove != null)
+ {
+ for (NodeRef nodeRef : nodesToRemove)
+ {
+ TransferManifestNode node = transferManifestNodeFactory.createTransferManifestNode(nodeRef, definition,
+ true);
+ formatter.writeTransferManifestNode(node);
+ }
}
formatter.endTransferManifest();
snapshotWriter.close();
diff --git a/source/java/org/alfresco/repo/transfer/TransferServiceImplTest.java b/source/java/org/alfresco/repo/transfer/TransferServiceImplTest.java
index 8cee169925..0c36e9a7e0 100644
--- a/source/java/org/alfresco/repo/transfer/TransferServiceImplTest.java
+++ b/source/java/org/alfresco/repo/transfer/TransferServiceImplTest.java
@@ -185,7 +185,7 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
*/
public void testCreateTarget() throws Exception
{
- String name = "name";
+ String name = "Test Transfer Target " + GUID.generate();
String title = "title";
String description = "description";
String endpointProtocol = "http";
@@ -249,7 +249,7 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
*/
public void testCreateTargetSyntax2() throws Exception
{
- String name = "nameSyntax2";
+ String name = "Test Transfer Target " + GUID.generate();
String title = "title";
String description = "description";
String endpointProtocol = "http";
@@ -324,8 +324,8 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
*/
public void testGetTransferTargets() throws Exception
{
- String nameA = "nameA";
- String nameB = "nameB";
+ String nameA = "Test Transfer Target " + GUID.generate();
+ String nameB = "Test Transfer Target " + GUID.generate();
String title = "title";
String description = "description";
String endpointProtocol = "http";
@@ -402,7 +402,7 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
//TODO Test not complete - can't yet put targets in different groups
public void testGetAllTransferTargetsByGroup() throws Exception
{
- String getMe = "getMe";
+ String getMe = "Test Transfer Target " + GUID.generate();
String title = "title";
String description = "description";
String endpointProtocol = "http";
@@ -439,7 +439,7 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
*/
public void testUpdateTransferTarget() throws Exception
{
- String updateMe = "updateMe";
+ String updateMe = "Test Transfer Target " + GUID.generate();
String title = "title";
String description = "description";
String endpointProtocol = "http";
diff --git a/source/java/org/alfresco/repo/transfer/UnitTestTransferManifestNodeFactory.java b/source/java/org/alfresco/repo/transfer/UnitTestTransferManifestNodeFactory.java
index d2fd0ee139..739a8764a5 100644
--- a/source/java/org/alfresco/repo/transfer/UnitTestTransferManifestNodeFactory.java
+++ b/source/java/org/alfresco/repo/transfer/UnitTestTransferManifestNodeFactory.java
@@ -72,6 +72,11 @@ public class UnitTestTransferManifestNodeFactory implements TransferManifestNode
}
public TransferManifestNode createTransferManifestNode(NodeRef nodeRef, TransferDefinition definition)
+ {
+ return createTransferManifestNode(nodeRef, definition, false);
+ }
+
+ public TransferManifestNode createTransferManifestNode(NodeRef nodeRef, TransferDefinition definition, boolean forceDelete)
{
TransferManifestNode newNode = realFactory.createTransferManifestNode(nodeRef, definition);
diff --git a/source/java/org/alfresco/repo/transfer/manifest/TransferManifestNodeFactory.java b/source/java/org/alfresco/repo/transfer/manifest/TransferManifestNodeFactory.java
index f6fb950e21..76895979e4 100644
--- a/source/java/org/alfresco/repo/transfer/manifest/TransferManifestNodeFactory.java
+++ b/source/java/org/alfresco/repo/transfer/manifest/TransferManifestNodeFactory.java
@@ -23,5 +23,24 @@ import org.alfresco.service.cmr.transfer.TransferDefinition;
public interface TransferManifestNodeFactory
{
+ /**
+ * Create an object that represents the specified node in a form that can be used to transfer it elsewhere.
+ * Calling this operation is identical to calling {@link TransferManifestNodeFactory#createTransferManifestNode(NodeRef, TransferDefinition, boolean)}
+ * specifying false as the value of the forceDelete parameter.
+ * @param nodeRef The identifier of the node to be distilled for transfer
+ * @param definition The transfer definition against which the node is being transferred
+ * @return An object that holds a snapshot of the state of the specified node suitable for transfer elsewhere.
+ */
TransferManifestNode createTransferManifestNode(NodeRef nodeRef, TransferDefinition definition);
+
+ /**
+ * Create an object that represents the specified node in a form that can be used to transfer it elsewhere
+ * @param nodeRef The identifier of the node to be distilled for transfer
+ * @param definition The transfer definition against which the node is being transferred
+ * @param forceDelete If this flag is set then the returned TransferManifestNode object will represent the removal
+ * of the specified node, even if the node still exists in this repository. This allows a node to be removed from the
+ * target repository even if it hasn't been removed in the source repository.
+ * @return An object that holds a snapshot of the state of the specified node suitable for transfer elsewhere.
+ */
+ TransferManifestNode createTransferManifestNode(NodeRef nodeRef, TransferDefinition definition, boolean forceDelete);
}
diff --git a/source/java/org/alfresco/repo/transfer/manifest/TransferManifestNodeFactoryImpl.java b/source/java/org/alfresco/repo/transfer/manifest/TransferManifestNodeFactoryImpl.java
index f38ed737cf..4c20c7e5e7 100644
--- a/source/java/org/alfresco/repo/transfer/manifest/TransferManifestNodeFactoryImpl.java
+++ b/source/java/org/alfresco/repo/transfer/manifest/TransferManifestNodeFactoryImpl.java
@@ -61,6 +61,11 @@ public class TransferManifestNodeFactoryImpl implements TransferManifestNodeFact
}
public TransferManifestNode createTransferManifestNode(NodeRef nodeRef, TransferDefinition definition)
+ {
+ return createTransferManifestNode(nodeRef, definition, false);
+ }
+
+ public TransferManifestNode createTransferManifestNode(NodeRef nodeRef, TransferDefinition definition, boolean forceDelete)
{
NodeRef.Status status = nodeService.getNodeStatus(nodeRef);
@@ -124,6 +129,21 @@ public class TransferManifestNodeFactoryImpl implements TransferManifestNodeFact
return node;
}
+ else if (forceDelete)
+ {
+ ChildAssociationRef primaryParentAssoc = nodeService.getPrimaryParent(nodeRef);
+ TransferManifestDeletedNode node = new TransferManifestDeletedNode();
+ NodeRef parentNodeRef = primaryParentAssoc.getParentRef();
+ node.setNodeRef(primaryParentAssoc.getChildRef());
+ node.setPrimaryParentAssoc(primaryParentAssoc);
+ if (nodeService.exists(parentNodeRef))
+ {
+ // The parent node still exists so it still has a path.
+ Path parentPath = nodeService.getPath(parentNodeRef);
+ node.setParentPath(parentPath);
+ }
+ return node;
+ }
else
{
// This is a "normal" node
diff --git a/source/java/org/alfresco/repo/transfer/manifest/XMLTransferManifestWriter.java b/source/java/org/alfresco/repo/transfer/manifest/XMLTransferManifestWriter.java
index c611e5e2af..aa47b16946 100644
--- a/source/java/org/alfresco/repo/transfer/manifest/XMLTransferManifestWriter.java
+++ b/source/java/org/alfresco/repo/transfer/manifest/XMLTransferManifestWriter.java
@@ -271,7 +271,7 @@ public class XMLTransferManifestWriter implements TransferManifestWriter
formatQName(node.getType()));
attributes.addAttribute("uri", "ancestorType", "ancestorType", "String",
- formatQName(node.getType()));
+ formatQName(node.getAncestorType()));
writer.startElement(TransferModel.TRANSFER_MODEL_1_0_URI,
ManifestModel.LOCALNAME_ELEMENT_NODE, PREFIX + ":"
diff --git a/source/java/org/alfresco/service/cmr/transfer/TransferDefinition.java b/source/java/org/alfresco/service/cmr/transfer/TransferDefinition.java
index ebbcb3d803..dc43236b28 100644
--- a/source/java/org/alfresco/service/cmr/transfer/TransferDefinition.java
+++ b/source/java/org/alfresco/service/cmr/transfer/TransferDefinition.java
@@ -46,8 +46,12 @@ public class TransferDefinition implements Serializable
*/
private static final long serialVersionUID = -8497919749300106861L;
- // Which nodes to deploy
+ // Which nodes to transfer
private Set nodes;
+
+ // Which nodes are to be explicitly removed from the target repository
+ // (irrespective of their state in the source repository)
+ private Set nodesToRemove;
// Which aspects to exclude
private Set excludedAspects;
@@ -80,6 +84,24 @@ public class TransferDefinition implements Serializable
this.setNodes(Arrays.asList(nodes));
}
+ /**
+ * Set nodes that are to be explicitly removed from the the target repository
+ * @param nodes
+ */
+ public void setNodesToRemove(Collection nodes)
+ {
+ this.nodesToRemove = new HashSet(nodes);
+ }
+
+ /**
+ * Set nodes that are to be explicitly removed from the the target repository
+ * @param nodes
+ */
+ public void setNodesToRemove(NodeRef...nodes)
+ {
+ this.setNodesToRemove(Arrays.asList(nodes));
+ }
+
/**
* Get which nodes to transfer
* @return
@@ -89,6 +111,15 @@ public class TransferDefinition implements Serializable
return nodes;
}
+ /**
+ * Get the list of nodes that are to be explicitly removed from the target repository
+ * @return
+ */
+ public Set getNodesToRemove()
+ {
+ return nodesToRemove;
+ }
+
/**
* Sets which aspects to exclude from transfer
*