diff --git a/config/alfresco/model/transferModel.xml b/config/alfresco/model/transferModel.xml
index faf32305e8..eed3b51986 100644
--- a/config/alfresco/model/transferModel.xml
+++ b/config/alfresco/model/transferModel.xml
@@ -210,6 +210,13 @@
d:text
true
+
+ ContentProperties
+ The content URLs transferred with this node
+ d:text
+ false
+ true
+
diff --git a/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java b/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java
index dcf697ce46..4e61c69025 100644
--- a/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java
+++ b/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java
@@ -524,16 +524,9 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB
Map props = new HashMap(node.getProperties());
Map existingProps = nodeService.getProperties(nodeToUpdate);
- // inject transferred property here
+ // inject transferred properties/aspect here
injectTransferred(props);
-
-// if(!props.containsKey(TransferModel.PROP_REPOSITORY_ID))
-// {
-// log.debug("injecting repositoryId property");
-// props.put(TransferModel.PROP_REPOSITORY_ID, header.getRepositoryId());
-// }
-// props.put(TransferModel.PROP_FROM_REPOSITORY_ID, header.getRepositoryId());
-
+
// Remove the invadedBy property since that is used by the transfer service
// and is local to this repository.
props.remove(TransferModel.PROP_INVADED_BY);
@@ -937,13 +930,33 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB
* inject transferred
*/
private void injectTransferred(Map props)
- {
+ {
if(!props.containsKey(TransferModel.PROP_REPOSITORY_ID))
{
log.debug("injecting repositoryId property");
props.put(TransferModel.PROP_REPOSITORY_ID, header.getRepositoryId());
}
props.put(TransferModel.PROP_FROM_REPOSITORY_ID, header.getRepositoryId());
+
+ /**
+ * For each property
+ */
+ List contentProps = new ArrayList();
+ for (Serializable value : props.values())
+ {
+ if ((value != null) && ContentData.class.isAssignableFrom(value.getClass()))
+ {
+ ContentData srcContent = (ContentData)value;
+
+ if(srcContent.getContentUrl() != null && !srcContent.getContentUrl().isEmpty())
+ {
+ log.debug("adding part name to from content field");
+ contentProps.add(TransferCommons.URLToPartName(srcContent.getContentUrl()));
+ }
+ }
+ }
+
+ props.put(TransferModel.PROP_FROM_CONTENT, (Serializable)contentProps);
}
public void setAlienProcessor(AlienProcessor alienProcessor)
diff --git a/source/java/org/alfresco/repo/transfer/RepoRequisiteManifestProcessorImpl.java b/source/java/org/alfresco/repo/transfer/RepoRequisiteManifestProcessorImpl.java
index 0e190a9d05..07b222c935 100644
--- a/source/java/org/alfresco/repo/transfer/RepoRequisiteManifestProcessorImpl.java
+++ b/source/java/org/alfresco/repo/transfer/RepoRequisiteManifestProcessorImpl.java
@@ -21,6 +21,7 @@ package org.alfresco.repo.transfer;
import java.io.Serializable;
import java.text.SimpleDateFormat;
+import java.util.Collection;
import java.util.Date;
import java.util.Map;
@@ -94,92 +95,102 @@ public class RepoRequisiteManifestProcessorImpl extends AbstractManifestProcesso
{
/**
* there is a corresponding node so we need to check whether we already
- * have the content item
+ * have the part for each content item
*/
NodeRef destinationNode = resolvedNodes.resolvedChild;
- Map destinationProps = nodeService.getProperties(destinationNode);
-
+ Map destinationProps = nodeService.getProperties(destinationNode);
+ /**
+ * For each property on the source node
+ */
for (Map.Entry propEntry : node.getProperties().entrySet())
{
Serializable value = propEntry.getValue();
+ QName propName = propEntry.getKey();
+
if (log.isDebugEnabled())
{
if (value == null)
{
- log.debug("Received a null value for property " + propEntry.getKey());
+ log.debug("Received a null value for property " + propName);
}
}
if ((value != null) && ContentData.class.isAssignableFrom(value.getClass()))
{
+ /**
+ * Got a content property from source node.
+ */
ContentData srcContent = (ContentData)value;
-
+
if(srcContent.getContentUrl() != null && !srcContent.getContentUrl().isEmpty() )
{
- Serializable destSer = destinationProps.get(propEntry.getKey());
- if(destSer != null && ContentData.class.isAssignableFrom(destSer.getClass()))
+ /**
+ * Source Content is not empty
+ */
+ String partName = TransferCommons.URLToPartName(srcContent.getContentUrl());
+
+ Serializable destSer = destinationProps.get(propName);
+ if(destSer != null && ContentData.class.isAssignableFrom(destSer.getClass()))
{
- ContentData destContent = (ContentData)destinationProps.get(propEntry.getKey());
-
/**
- * If the modification dates for the node are different
+ * Content property not empty and content property already exists on destination
*/
- Serializable srcModified = node.getProperties().get(ContentModel.PROP_MODIFIED);
- Serializable destModified = destinationProps.get(ContentModel.PROP_MODIFIED);
-
- if(log.isDebugEnabled())
- {
- SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
-
- log.debug ("srcModified :" + srcModified + "destModified :" + destModified);
-
- if(srcModified instanceof Date)
- {
- log.debug("srcModified: " + SDF.format(srcModified));
- }
-
- if(destModified instanceof Date)
- {
- log.debug("destModified: " + SDF.format(destModified));
- }
- }
+ ContentData destContent = (ContentData)destSer;
- if(srcModified != null &&
- destModified != null &&
- srcModified instanceof Date &&
- destModified instanceof Date &&
- ((Date)srcModified).getTime() <= ((Date)destModified).getTime())
+ Serializable destFromContents = destinationProps.get(TransferModel.PROP_FROM_CONTENT);
+
+ if(destFromContents != null && Collection.class.isAssignableFrom(destFromContents.getClass()))
{
- if(log.isDebugEnabled())
+ Collection contents = (Collection)destFromContents;
+ /**
+ * Content property not empty and content property already exists on destination
+ */
+ if(contents.contains(partName))
{
- log.debug("the modified date is the same or before - no need send content:" + node.getNodeRef());
+ if(log.isDebugEnabled())
+ {
+ log.debug("part already transferred, no need to send it again, partName:" + partName + ", nodeRef:" + node.getNodeRef());
+ }
+ }
+ else
+ {
+ if(log.isDebugEnabled())
+ {
+ log.debug("part name not transferred, requesting new content item partName:" + partName + ", nodeRef:" + node.getNodeRef());
+ }
+ out.missingContent(node.getNodeRef(), propEntry.getKey(), TransferCommons.URLToPartName(srcContent.getContentUrl()));
}
}
else
{
+ // dest from contents is null
if(log.isDebugEnabled())
{
- log.debug("time different, require content for node : " + node.getNodeRef());
+ log.debug("from contents is null, requesting new content item partName:" + partName + ", nodeRef:" + node.getNodeRef());
}
out.missingContent(node.getNodeRef(), propEntry.getKey(), TransferCommons.URLToPartName(srcContent.getContentUrl()));
}
}
else
{
+ /**
+ * Content property not empty and does not exist on destination
+ */
if(log.isDebugEnabled())
{
- log.debug("no content on destination, content is required" + propEntry.getKey() + srcContent.getContentUrl());
+ log.debug("no content on destination, all content is required" + propEntry.getKey() + srcContent.getContentUrl());
}
// We don't have the property on the destination node
out.missingContent(node.getNodeRef(), propEntry.getKey(), TransferCommons.URLToPartName(srcContent.getContentUrl()));
}
- } // src content url not null
- } // value is content data
- }
+ }
+ } // src content url not null
+ } // value is content data
}
else
{
log.debug("Node does not exist on destination nodeRef:" + node.getNodeRef());
+
/**
* there is no corresponding node so all content properties are "missing."
*/
diff --git a/source/java/org/alfresco/repo/transfer/RepoTransferReceiverImpl.java b/source/java/org/alfresco/repo/transfer/RepoTransferReceiverImpl.java
index 0582ba43be..ee65e9edf9 100644
--- a/source/java/org/alfresco/repo/transfer/RepoTransferReceiverImpl.java
+++ b/source/java/org/alfresco/repo/transfer/RepoTransferReceiverImpl.java
@@ -40,6 +40,7 @@ import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.alfresco.model.ContentModel;
+import org.alfresco.repo.content.ContentServicePolicies;
import org.alfresco.repo.copy.CopyBehaviourCallback;
import org.alfresco.repo.copy.CopyDetails;
import org.alfresco.repo.copy.CopyServicePolicies;
@@ -96,7 +97,8 @@ public class RepoTransferReceiverImpl implements TransferReceiver,
NodeServicePolicies.OnCreateChildAssociationPolicy,
NodeServicePolicies.BeforeDeleteNodePolicy,
NodeServicePolicies.OnRestoreNodePolicy,
- NodeServicePolicies.OnMoveNodePolicy
+ NodeServicePolicies.OnMoveNodePolicy,
+ ContentServicePolicies.OnContentUpdatePolicy
{
/**
@@ -213,6 +215,14 @@ public class RepoTransferReceiverImpl implements TransferReceiver,
TransferModel.ASPECT_TRANSFERRED,
new JavaBehaviour(this, "onCreateChildAssociation", NotificationFrequency.EVERY_EVENT));
+ /**
+ * For every update of a transferred node
+ */
+ this.getPolicyComponent().bindClassBehaviour(
+ ContentServicePolicies.OnContentUpdatePolicy.QNAME,
+ TransferModel.ASPECT_TRANSFERRED,
+ new JavaBehaviour(this, "onContentUpdate", NotificationFrequency.EVERY_EVENT));
+
/**
* For every copy of a transferred node run onCopyTransferred
*/
@@ -1103,8 +1113,23 @@ public class RepoTransferReceiverImpl implements TransferReceiver,
log.debug("onMoveNode");
log.debug("oldChildAssocRef:" + oldChildAssocRef);
log.debug("newChildAssocRef:" + newChildAssocRef);
- alienProcessor.beforeDeleteAlien(newChildAssocRef.getChildRef(), oldChildAssocRef);
- alienProcessor.afterMoveAlien(newChildAssocRef);
+
+ NodeRef oldParentRef = oldChildAssocRef.getParentRef();
+ NodeRef newParentRef = newChildAssocRef.getParentRef();
+
+ if(newParentRef.equals(oldParentRef))
+ {
+ log.debug("old parent and new parent are the same - this is a rename, do nothing");
+ }
+ else
+ {
+ if(log.isDebugEnabled())
+ {
+ log.debug("moving node from oldParentRef:" + oldParentRef +" to:" + newParentRef);
+ }
+ alienProcessor.beforeDeleteAlien(newChildAssocRef.getChildRef(), oldChildAssocRef);
+ alienProcessor.afterMoveAlien(newChildAssocRef);
+ }
}
/**
@@ -1223,4 +1248,18 @@ public class RepoTransferReceiverImpl implements TransferReceiver,
{
return alienProcessor;
}
+
+ @Override
+ public void onContentUpdate(NodeRef nodeRef, boolean newContent)
+ {
+ /**
+ * On update of a transferred node remove the from content from property.
+ */
+ log.debug("on content update called:" + nodeRef);
+ if(newContent)
+ {
+ log.debug("new content remove PROP_FROM_CONTENT from node:" + nodeRef);
+ nodeService.setProperty(nodeRef, TransferModel.PROP_FROM_CONTENT, null);
+ }
+ }
}
diff --git a/source/java/org/alfresco/repo/transfer/TransferModel.java b/source/java/org/alfresco/repo/transfer/TransferModel.java
index d9bb7e7579..5c0a35201f 100644
--- a/source/java/org/alfresco/repo/transfer/TransferModel.java
+++ b/source/java/org/alfresco/repo/transfer/TransferModel.java
@@ -39,13 +39,13 @@ public interface TransferModel
static final QName ASPECT_TRANSFERRED = QName.createQName(TRANSFER_MODEL_1_0_URI, "transferred");
static final QName PROP_REPOSITORY_ID = QName.createQName(TRANSFER_MODEL_1_0_URI, "repositoryId");
static final QName PROP_FROM_REPOSITORY_ID = QName.createQName(TRANSFER_MODEL_1_0_URI, "fromRepositoryId");
+ static final QName PROP_FROM_CONTENT = QName.createQName(TRANSFER_MODEL_1_0_URI, "fromContent");
/**
* Aspect : alien
*/
static final QName ASPECT_ALIEN = QName.createQName(TRANSFER_MODEL_1_0_URI, "alien");
static final QName PROP_INVADED_BY = QName.createQName(TRANSFER_MODEL_1_0_URI, "invadedBy");
-// static final QName PROP_ALIEN = QName.createQName(TRANSFER_MODEL_1_0_URI, "alien");
/*
* Type : Transfer Group
diff --git a/source/java/org/alfresco/repo/transfer/TransferServiceImplTest.java b/source/java/org/alfresco/repo/transfer/TransferServiceImplTest.java
index 9204ba2603..5c8fc1e09b 100644
--- a/source/java/org/alfresco/repo/transfer/TransferServiceImplTest.java
+++ b/source/java/org/alfresco/repo/transfer/TransferServiceImplTest.java
@@ -6975,414 +6975,413 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
}
} // copy node
+
+ /**
+ * Test the transfer method with regard to an empty content property. ALF-4865
+ *
+ * Step 1: create a node with an empty content property
+ * transfer
+ *
+ * Step 2: add non empty content property
+ * transfer
+ *
+ * Step 3: update from non empty content to empty content property
+ * transfer
+ *
+ * This is a unit test so it does some shenanigans to send to the same instance of alfresco.
+ */
+ public void testEmptyContent() throws Exception
+ {
+ setDefaultRollback(false);
+
+ String CONTENT_TITLE = "ContentTitle";
+ String CONTENT_TITLE_UPDATED = "ContentTitleUpdated";
+ Locale CONTENT_LOCALE = Locale.ENGLISH;
+ String CONTENT_ENCODING = "UTF-8";
+ String CONTENT_STRING = "The quick brown fox jumps over the lazy dog.";
+
+ /**
+ * For unit test
+ * - replace the HTTP transport with the in-process transport
+ * - replace the node factory with one that will map node refs, paths etc.
+ *
+ * Fake Repository Id
+ */
+ TransferTransmitter transmitter = new UnitTestInProcessTransmitterImpl(receiver, contentService, transactionService);
+ transferServiceImpl.setTransmitter(transmitter);
+ UnitTestTransferManifestNodeFactory testNodeFactory = new UnitTestTransferManifestNodeFactory(this.transferManifestNodeFactory);
+ transferServiceImpl.setTransferManifestNodeFactory(testNodeFactory);
+ List> pathMap = testNodeFactory.getPathMap();
+ // Map company_home/guest_home to company_home so tranferred nodes and moved "up" one level.
+ pathMap.add(new Pair(PathHelper.stringToPath(GUEST_HOME_XPATH_QUERY), PathHelper.stringToPath(COMPANY_HOME_XPATH_QUERY)));
+
+ DescriptorService mockedDescriptorService = getMockDescriptorService(REPO_ID_A);
+ transferServiceImpl.setDescriptorService(mockedDescriptorService);
+
+ /**
+ * Now go ahead and create our first transfer target
+ */
+ String targetName = "testTransferEmptyContent";
+ TransferTarget transferMe;
+ NodeRef contentNodeRef;
+ NodeRef savedDestinationNodeRef;
+
+ startNewTransaction();
+ try
+ {
+ /**
+ * Get guest home
+ */
+ String guestHomeQuery = "/app:company_home/app:guest_home";
+ ResultSet guestHomeResult = searchService.query(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, SearchService.LANGUAGE_XPATH, guestHomeQuery);
+ assertEquals("", 1, guestHomeResult.length());
+ NodeRef guestHome = guestHomeResult.getNodeRef(0);
-// TODO - temp comment out of unit tests - will be tested on branch rather than head.
-// /**
-// * Test the transfer method with regard to an empty content property. ALF-4865
-// *
-// * Step 1: create a node with an empty content property
-// * transfer
-// *
-// * Step 2: add non empty content property
-// * transfer
-// *
-// * Step 3: update from non empty content to empty content property
-// * transfer
-// *
-// * This is a unit test so it does some shenanigans to send to the same instance of alfresco.
-// */
-// public void testEmptyContent() throws Exception
-// {
-// setDefaultRollback(false);
-//
-// String CONTENT_TITLE = "ContentTitle";
-// String CONTENT_TITLE_UPDATED = "ContentTitleUpdated";
-// Locale CONTENT_LOCALE = Locale.ENGLISH;
-// String CONTENT_ENCODING = "UTF-8";
-// String CONTENT_STRING = "The quick brown fox jumps over the lazy dog.";
-//
-// /**
-// * For unit test
-// * - replace the HTTP transport with the in-process transport
-// * - replace the node factory with one that will map node refs, paths etc.
-// *
-// * Fake Repository Id
-// */
-// TransferTransmitter transmitter = new UnitTestInProcessTransmitterImpl(receiver, contentService, transactionService);
-// transferServiceImpl.setTransmitter(transmitter);
-// UnitTestTransferManifestNodeFactory testNodeFactory = new UnitTestTransferManifestNodeFactory(this.transferManifestNodeFactory);
-// transferServiceImpl.setTransferManifestNodeFactory(testNodeFactory);
-// List> pathMap = testNodeFactory.getPathMap();
-// // Map company_home/guest_home to company_home so tranferred nodes and moved "up" one level.
-// pathMap.add(new Pair(PathHelper.stringToPath(GUEST_HOME_XPATH_QUERY), PathHelper.stringToPath(COMPANY_HOME_XPATH_QUERY)));
-//
-// DescriptorService mockedDescriptorService = getMockDescriptorService(REPO_ID_A);
-// transferServiceImpl.setDescriptorService(mockedDescriptorService);
-//
-// /**
-// * Now go ahead and create our first transfer target
-// */
-// String targetName = "testTransferEmptyContent";
-// TransferTarget transferMe;
-// NodeRef contentNodeRef;
-// NodeRef savedDestinationNodeRef;
-//
-// startNewTransaction();
-// try
-// {
-// /**
-// * Get guest home
-// */
-// String guestHomeQuery = "/app:company_home/app:guest_home";
-// ResultSet guestHomeResult = searchService.query(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, SearchService.LANGUAGE_XPATH, guestHomeQuery);
-// assertEquals("", 1, guestHomeResult.length());
-// NodeRef guestHome = guestHomeResult.getNodeRef(0);
-//
-// /**
-// * Create a test node with an empty content that we will read and write
-// */
-// String name = GUID.generate();
-// ChildAssociationRef child = nodeService.createNode(guestHome, ContentModel.ASSOC_CONTAINS, QName.createQName(name), ContentModel.TYPE_CONTENT);
-// contentNodeRef = child.getChildRef();
-// nodeService.setProperty(contentNodeRef, ContentModel.PROP_TITLE, CONTENT_TITLE);
-// nodeService.setProperty(contentNodeRef, ContentModel.PROP_NAME, name);
-// ContentData cd = new ContentData(null, null, 0, null);
-// nodeService.setProperty(contentNodeRef, ContentModel.PROP_CONTENT, cd);
-//
-// if(!transferService.targetExists(targetName))
-// {
-// transferMe = createTransferTarget(targetName);
-// }
-// else
-// {
-// transferMe = transferService.getTransferTarget(targetName);
-// }
-// transferService.enableTransferTarget(targetName, true);
-// }
-// finally
-// {
-// endTransaction();
-// }
-//
-// SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
-//
-//
-//
-//
-// /**
-// * Step 1: Transfer our node which has empty content
-// */
-// logger.debug("testEmptyContent : First transfer - create new node (empty content)");
-// startNewTransaction();
-// try
-// {
-// ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT);
-// assertNull("test setup content reader not null", reader);
-// Map props = nodeService.getProperties(contentNodeRef);
-// assertTrue(props.containsKey(ContentModel.PROP_CONTENT));
-//
-// TransferDefinition definition = new TransferDefinition();
-// Setnodes = new HashSet();
-// nodes.add(contentNodeRef);
-// definition.setNodes(nodes);
-// transferService.transfer(targetName, definition);
-//
-// }
-// finally
-// {
-// endTransaction();
-// }
-//
-// startNewTransaction();
-// try
-// {
-// Serializable modifiedDate = nodeService.getProperty(contentNodeRef, ContentModel.PROP_MODIFIED);
-// if(modifiedDate instanceof Date)
-// {
-// logger.debug("srcModified: " + SDF.format(modifiedDate));
-// }
-//
-// NodeRef destinationNodeRef = testNodeFactory.getMappedNodeRef(contentNodeRef);
-// savedDestinationNodeRef = destinationNodeRef;
-// assertTrue("content node (dest) does not exist", nodeService.exists(destinationNodeRef));
-//
-// ContentReader reader = contentService.getReader(destinationNodeRef, ContentModel.PROP_CONTENT);
-// assertNull("content reader not null", reader);
-// Map props = nodeService.getProperties(destinationNodeRef);
-// assertTrue(props.containsKey(ContentModel.PROP_CONTENT));
-//
-// }
-// finally
-// {
-// endTransaction();
-// }
-//
-// /**
-// * Step 2: replace empty content with new content
-// */
-// logger.debug("testEmptyContent : Second transfer - replace empty content with some content");
-//
-// startNewTransaction();
-// try
-// {
-// Serializable modifiedDate = nodeService.getProperty(contentNodeRef, ContentModel.PROP_MODIFIED);
-// if(modifiedDate instanceof Date)
-// {
-// logger.debug("srcModified: " + SDF.format(modifiedDate));
-// }
-//
-// ContentWriter writer = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true);
-// writer.setLocale(CONTENT_LOCALE);
-// writer.setEncoding(CONTENT_ENCODING);
-// writer.putContent(CONTENT_STRING);
-// }
-// finally
-// {
-// endTransaction();
-// }
-//
-// startNewTransaction();
-// try
-// {
-// ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT);
-// assertNotNull("test setup content reader not null", reader);
-// Map props = nodeService.getProperties(contentNodeRef);
-// assertTrue(props.containsKey(ContentModel.PROP_CONTENT));
-//
-// /**
-// * Step 2: replace empty content with new content
-// */
-// TransferDefinition definition = new TransferDefinition();
-// Setnodes = new HashSet();
-// nodes.add(contentNodeRef);
-// definition.setNodes(nodes);
-// transferService.transfer(targetName, definition);
-//
-// }
-// finally
-// {
-// endTransaction();
-// }
-//
-// startNewTransaction();
-// try
-// {
-// NodeRef destinationNodeRef = testNodeFactory.getMappedNodeRef(contentNodeRef);
-//
-// assertEquals("test error destinationNodeRef not correct", savedDestinationNodeRef, destinationNodeRef);
-// ContentReader reader = contentService.getReader(destinationNodeRef, ContentModel.PROP_CONTENT);
-// assertNotNull("content reader is null", reader);
-// assertEquals("content encoding is wrong", reader.getEncoding(), CONTENT_ENCODING);
-// assertEquals("content locale is wrong", reader.getLocale(), CONTENT_LOCALE);
-// assertTrue("content does not exist", reader.exists());
-// String contentStr = reader.getContentString();
-// assertEquals("Content is wrong", contentStr, CONTENT_STRING);
-// }
-// finally
-// {
-// endTransaction();
-// }
-//
-// /**
-// * Step 3 - transition from a content property having content to one that is empty
-// */
-// logger.debug("testEmptyContent : Third transfer - remove existing content");
-//
-// startNewTransaction();
-// try
-// {
-// ContentData cd = new ContentData(null, null, 0, null);
-// nodeService.setProperty(contentNodeRef, ContentModel.PROP_CONTENT, cd);
-// }
-// finally
-// {
-// endTransaction();
-// }
-//
-// startNewTransaction();
-// try
-// {
-// ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT);
-// assertNull("test setup content reader not null", reader);
-// Map props = nodeService.getProperties(contentNodeRef);
-// assertTrue(props.containsKey(ContentModel.PROP_CONTENT));
-//
-// /**
-// * Step 3: Transfer our node which has empty content to over-write existing
-// * content
-// */
-// TransferDefinition definition = new TransferDefinition();
-// Setnodes = new HashSet();
-// nodes.add(contentNodeRef);
-// definition.setNodes(nodes);
-// transferService.transfer(targetName, definition);
-// }
-// finally
-// {
-// endTransaction();
-// }
-//
-// startNewTransaction();
-// try
-// {
-// NodeRef destinationNodeRef = testNodeFactory.getMappedNodeRef(contentNodeRef);
-// assertTrue("content node (dest) does not exist", nodeService.exists(destinationNodeRef));
-//
-// ContentReader reader = contentService.getReader(destinationNodeRef, ContentModel.PROP_CONTENT);
-// assertNull("content reader not null", reader);
-// Map props = nodeService.getProperties(destinationNodeRef);
-// assertTrue(props.containsKey(ContentModel.PROP_CONTENT));
-//
-// }
-// finally
-// {
-// endTransaction();
-// }
-//
-// } // end of testEmptyContent
-//
-//
-// /**
-// * Test the transfer method with regard to a repeated update of content.by sending one node (CRUD).
-// *
-// * This is a unit test so it does some shenanigans to send to the same instance of alfresco.
-// */
-// public void testRepeatUpdateOfContent() throws Exception
-// {
-// final RetryingTransactionHelper tran = transactionService.getRetryingTransactionHelper();
-// final String CONTENT_TITLE = "ContentTitle";
-// final Locale CONTENT_LOCALE = Locale.GERMAN;
-// final String CONTENT_ENCODING = "UTF-8";
-//
-// /**
-// * For unit test
-// * - replace the HTTP transport with the in-process transport
-// * - replace the node factory with one that will map node refs, paths etc.
-// *
-// * Fake Repository Id
-// */
-// final TransferTransmitter transmitter = new UnitTestInProcessTransmitterImpl(receiver, contentService, transactionService);
-// transferServiceImpl.setTransmitter(transmitter);
-// final UnitTestTransferManifestNodeFactory testNodeFactory = new UnitTestTransferManifestNodeFactory(this.transferManifestNodeFactory);
-// transferServiceImpl.setTransferManifestNodeFactory(testNodeFactory);
-// final List> pathMap = testNodeFactory.getPathMap();
-// // Map company_home/guest_home to company_home so tranferred nodes and moved "up" one level.
-// pathMap.add(new Pair(PathHelper.stringToPath(GUEST_HOME_XPATH_QUERY), PathHelper.stringToPath(COMPANY_HOME_XPATH_QUERY)));
-//
-// DescriptorService mockedDescriptorService = getMockDescriptorService(REPO_ID_A);
-// transferServiceImpl.setDescriptorService(mockedDescriptorService);
-//
-// final String targetName = "testRepeatUpdateOfContent";
-//
-// class TestContext
-// {
-// TransferTarget transferMe;
-// NodeRef contentNodeRef;
-// NodeRef destNodeRef;
-// String contentString;
-// };
-//
-// RetryingTransactionCallback setupCB = new RetryingTransactionCallback()
-// {
-// @Override
-// public TestContext execute() throws Throwable
-// {
-// TestContext testContext = new TestContext();
-//
-// /**
-// * Get guest home
-// */
-// String guestHomeQuery = "/app:company_home/app:guest_home";
-// ResultSet guestHomeResult = searchService.query(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, SearchService.LANGUAGE_XPATH, guestHomeQuery);
-// assertEquals("", 1, guestHomeResult.length());
-// NodeRef guestHome = guestHomeResult.getNodeRef(0);
-//
-// /**
-// * Create a test node that we will read and write
-// */
-// String name = GUID.generate();
-// ChildAssociationRef child = nodeService.createNode(guestHome, ContentModel.ASSOC_CONTAINS, QName.createQName(name), ContentModel.TYPE_CONTENT);
-// testContext.contentNodeRef = child.getChildRef();
-// nodeService.setProperty(testContext.contentNodeRef, ContentModel.PROP_TITLE, CONTENT_TITLE);
-// nodeService.setProperty(testContext.contentNodeRef, ContentModel.PROP_NAME, name);
-//
-// /**
-// * Make sure the transfer target exists and is enabled.
-// */
-// if(!transferService.targetExists(targetName))
-// {
-// testContext.transferMe = createTransferTarget(targetName);
-// }
-// else
-// {
-// testContext.transferMe = transferService.getTransferTarget(targetName);
-// }
-// transferService.enableTransferTarget(targetName, true);
-// return testContext;
-// }
-// };
-//
-// final TestContext testContext = tran.doInTransaction(setupCB);
-//
-// RetryingTransactionCallback updateContentCB = new RetryingTransactionCallback() {
-//
-// @Override
-// public Void execute() throws Throwable
-// {
-// ContentWriter writer = contentService.getWriter(testContext.contentNodeRef, ContentModel.PROP_CONTENT, true);
-// writer.setLocale(CONTENT_LOCALE);
-// writer.setEncoding(CONTENT_ENCODING);
-// writer.putContent(testContext.contentString);
-// return null;
-// }
-// };
-//
-// RetryingTransactionCallback transferCB = new RetryingTransactionCallback() {
-//
-// @Override
-// public Void execute() throws Throwable
-// {
-// TransferDefinition definition = new TransferDefinition();
-// Setnodes = new HashSet();
-// nodes.add(testContext.contentNodeRef);
-// definition.setNodes(nodes);
-// transferService.transfer(targetName, definition);
-// return null;
-// }
-// };
-//
-// RetryingTransactionCallback checkTransferCB = new RetryingTransactionCallback() {
-//
-// @Override
-// public Void execute() throws Throwable
-// {
-// // Now validate that the target node exists and has similar properties to the source
-// NodeRef destNodeRef = testNodeFactory.getMappedNodeRef(testContext.contentNodeRef);
-//
-// ContentReader reader = contentService.getReader(destNodeRef, ContentModel.PROP_CONTENT);
-// assertNotNull("content reader is null", reader);
-// assertEquals("content encoding is wrong", reader.getEncoding(), CONTENT_ENCODING);
-// assertEquals("content locale is wrong", reader.getLocale(), CONTENT_LOCALE);
-// assertTrue("content does not exist", reader.exists());
-// String contentStr = reader.getContentString();
-// assertEquals("Content is wrong", contentStr, testContext.contentString);
-//
-// return null;
-// }
-// };
-//
-// /**
-// * This is the test
-// */
-// for(int i = 0; i < 6 ; i++)
-// {
-// logger.debug("testRepeatUpdateContent - iteration:" + i);
-// testContext.contentString = String.valueOf(i);
-// tran.doInTransaction(updateContentCB);
-// tran.doInTransaction(transferCB);
-// tran.doInTransaction(checkTransferCB);
-// }
-// } // test repeat update content
+ /**
+ * Create a test node with an empty content that we will read and write
+ */
+ String name = GUID.generate();
+ ChildAssociationRef child = nodeService.createNode(guestHome, ContentModel.ASSOC_CONTAINS, QName.createQName(name), ContentModel.TYPE_CONTENT);
+ contentNodeRef = child.getChildRef();
+ nodeService.setProperty(contentNodeRef, ContentModel.PROP_TITLE, CONTENT_TITLE);
+ nodeService.setProperty(contentNodeRef, ContentModel.PROP_NAME, name);
+ ContentData cd = new ContentData(null, null, 0, null);
+ nodeService.setProperty(contentNodeRef, ContentModel.PROP_CONTENT, cd);
+
+ if(!transferService.targetExists(targetName))
+ {
+ transferMe = createTransferTarget(targetName);
+ }
+ else
+ {
+ transferMe = transferService.getTransferTarget(targetName);
+ }
+ transferService.enableTransferTarget(targetName, true);
+ }
+ finally
+ {
+ endTransaction();
+ }
+
+ SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
+
+
+
+
+ /**
+ * Step 1: Transfer our node which has empty content
+ */
+ logger.debug("testEmptyContent : First transfer - create new node (empty content)");
+ startNewTransaction();
+ try
+ {
+ ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT);
+ assertNull("test setup content reader not null", reader);
+ Map props = nodeService.getProperties(contentNodeRef);
+ assertTrue(props.containsKey(ContentModel.PROP_CONTENT));
+
+ TransferDefinition definition = new TransferDefinition();
+ Setnodes = new HashSet();
+ nodes.add(contentNodeRef);
+ definition.setNodes(nodes);
+ transferService.transfer(targetName, definition);
+
+ }
+ finally
+ {
+ endTransaction();
+ }
+
+ startNewTransaction();
+ try
+ {
+ Serializable modifiedDate = nodeService.getProperty(contentNodeRef, ContentModel.PROP_MODIFIED);
+ if(modifiedDate instanceof Date)
+ {
+ logger.debug("srcModified: " + SDF.format(modifiedDate));
+ }
+
+ NodeRef destinationNodeRef = testNodeFactory.getMappedNodeRef(contentNodeRef);
+ savedDestinationNodeRef = destinationNodeRef;
+ assertTrue("content node (dest) does not exist", nodeService.exists(destinationNodeRef));
+
+ ContentReader reader = contentService.getReader(destinationNodeRef, ContentModel.PROP_CONTENT);
+ assertNull("content reader not null", reader);
+ Map props = nodeService.getProperties(destinationNodeRef);
+ assertTrue(props.containsKey(ContentModel.PROP_CONTENT));
+
+ }
+ finally
+ {
+ endTransaction();
+ }
+
+ /**
+ * Step 2: replace empty content with new content
+ */
+ logger.debug("testEmptyContent : Second transfer - replace empty content with some content");
+
+ startNewTransaction();
+ try
+ {
+ Serializable modifiedDate = nodeService.getProperty(contentNodeRef, ContentModel.PROP_MODIFIED);
+ if(modifiedDate instanceof Date)
+ {
+ logger.debug("srcModified: " + SDF.format(modifiedDate));
+ }
+
+ ContentWriter writer = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true);
+ writer.setLocale(CONTENT_LOCALE);
+ writer.setEncoding(CONTENT_ENCODING);
+ writer.putContent(CONTENT_STRING);
+ }
+ finally
+ {
+ endTransaction();
+ }
+
+ startNewTransaction();
+ try
+ {
+ ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT);
+ assertNotNull("test setup content reader not null", reader);
+ Map props = nodeService.getProperties(contentNodeRef);
+ assertTrue(props.containsKey(ContentModel.PROP_CONTENT));
+
+ /**
+ * Step 2: replace empty content with new content
+ */
+ TransferDefinition definition = new TransferDefinition();
+ Setnodes = new HashSet();
+ nodes.add(contentNodeRef);
+ definition.setNodes(nodes);
+ transferService.transfer(targetName, definition);
+
+ }
+ finally
+ {
+ endTransaction();
+ }
+
+ startNewTransaction();
+ try
+ {
+ NodeRef destinationNodeRef = testNodeFactory.getMappedNodeRef(contentNodeRef);
+
+ assertEquals("test error destinationNodeRef not correct", savedDestinationNodeRef, destinationNodeRef);
+ ContentReader reader = contentService.getReader(destinationNodeRef, ContentModel.PROP_CONTENT);
+ assertNotNull("content reader is null", reader);
+ assertEquals("content encoding is wrong", reader.getEncoding(), CONTENT_ENCODING);
+ assertEquals("content locale is wrong", reader.getLocale(), CONTENT_LOCALE);
+ assertTrue("content does not exist", reader.exists());
+ String contentStr = reader.getContentString();
+ assertEquals("Content is wrong", contentStr, CONTENT_STRING);
+ }
+ finally
+ {
+ endTransaction();
+ }
+
+ /**
+ * Step 3 - transition from a content property having content to one that is empty
+ */
+ logger.debug("testEmptyContent : Third transfer - remove existing content");
+
+ startNewTransaction();
+ try
+ {
+ ContentData cd = new ContentData(null, null, 0, null);
+ nodeService.setProperty(contentNodeRef, ContentModel.PROP_CONTENT, cd);
+ }
+ finally
+ {
+ endTransaction();
+ }
+
+ startNewTransaction();
+ try
+ {
+ ContentReader reader = contentService.getReader(contentNodeRef, ContentModel.PROP_CONTENT);
+ assertNull("test setup content reader not null", reader);
+ Map props = nodeService.getProperties(contentNodeRef);
+ assertTrue(props.containsKey(ContentModel.PROP_CONTENT));
+
+ /**
+ * Step 3: Transfer our node which has empty content to over-write existing
+ * content
+ */
+ TransferDefinition definition = new TransferDefinition();
+ Setnodes = new HashSet();
+ nodes.add(contentNodeRef);
+ definition.setNodes(nodes);
+ transferService.transfer(targetName, definition);
+ }
+ finally
+ {
+ endTransaction();
+ }
+
+ startNewTransaction();
+ try
+ {
+ NodeRef destinationNodeRef = testNodeFactory.getMappedNodeRef(contentNodeRef);
+ assertTrue("content node (dest) does not exist", nodeService.exists(destinationNodeRef));
+
+ ContentReader reader = contentService.getReader(destinationNodeRef, ContentModel.PROP_CONTENT);
+ assertNull("content reader not null", reader);
+ Map props = nodeService.getProperties(destinationNodeRef);
+ assertTrue(props.containsKey(ContentModel.PROP_CONTENT));
+
+ }
+ finally
+ {
+ endTransaction();
+ }
+
+ } // end of testEmptyContent
+
+
+ /**
+ * Test the transfer method with regard to a repeated update of content.by sending one node (CRUD).
+ *
+ * This is a unit test so it does some shenanigans to send to the same instance of alfresco.
+ */
+ public void testRepeatUpdateOfContent() throws Exception
+ {
+ final RetryingTransactionHelper tran = transactionService.getRetryingTransactionHelper();
+ final String CONTENT_TITLE = "ContentTitle";
+ final Locale CONTENT_LOCALE = Locale.GERMAN;
+ final String CONTENT_ENCODING = "UTF-8";
+
+ /**
+ * For unit test
+ * - replace the HTTP transport with the in-process transport
+ * - replace the node factory with one that will map node refs, paths etc.
+ *
+ * Fake Repository Id
+ */
+ final TransferTransmitter transmitter = new UnitTestInProcessTransmitterImpl(receiver, contentService, transactionService);
+ transferServiceImpl.setTransmitter(transmitter);
+ final UnitTestTransferManifestNodeFactory testNodeFactory = new UnitTestTransferManifestNodeFactory(this.transferManifestNodeFactory);
+ transferServiceImpl.setTransferManifestNodeFactory(testNodeFactory);
+ final List> pathMap = testNodeFactory.getPathMap();
+ // Map company_home/guest_home to company_home so tranferred nodes and moved "up" one level.
+ pathMap.add(new Pair(PathHelper.stringToPath(GUEST_HOME_XPATH_QUERY), PathHelper.stringToPath(COMPANY_HOME_XPATH_QUERY)));
+
+ DescriptorService mockedDescriptorService = getMockDescriptorService(REPO_ID_A);
+ transferServiceImpl.setDescriptorService(mockedDescriptorService);
+
+ final String targetName = "testRepeatUpdateOfContent";
+
+ class TestContext
+ {
+ TransferTarget transferMe;
+ NodeRef contentNodeRef;
+ NodeRef destNodeRef;
+ String contentString;
+ };
+
+ RetryingTransactionCallback setupCB = new RetryingTransactionCallback()
+ {
+ @Override
+ public TestContext execute() throws Throwable
+ {
+ TestContext testContext = new TestContext();
+
+ /**
+ * Get guest home
+ */
+ String guestHomeQuery = "/app:company_home/app:guest_home";
+ ResultSet guestHomeResult = searchService.query(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, SearchService.LANGUAGE_XPATH, guestHomeQuery);
+ assertEquals("", 1, guestHomeResult.length());
+ NodeRef guestHome = guestHomeResult.getNodeRef(0);
+
+ /**
+ * Create a test node that we will read and write
+ */
+ String name = GUID.generate();
+ ChildAssociationRef child = nodeService.createNode(guestHome, ContentModel.ASSOC_CONTAINS, QName.createQName(name), ContentModel.TYPE_CONTENT);
+ testContext.contentNodeRef = child.getChildRef();
+ nodeService.setProperty(testContext.contentNodeRef, ContentModel.PROP_TITLE, CONTENT_TITLE);
+ nodeService.setProperty(testContext.contentNodeRef, ContentModel.PROP_NAME, name);
+
+ /**
+ * Make sure the transfer target exists and is enabled.
+ */
+ if(!transferService.targetExists(targetName))
+ {
+ testContext.transferMe = createTransferTarget(targetName);
+ }
+ else
+ {
+ testContext.transferMe = transferService.getTransferTarget(targetName);
+ }
+ transferService.enableTransferTarget(targetName, true);
+ return testContext;
+ }
+ };
+
+ final TestContext testContext = tran.doInTransaction(setupCB);
+
+ RetryingTransactionCallback updateContentCB = new RetryingTransactionCallback() {
+
+ @Override
+ public Void execute() throws Throwable
+ {
+ ContentWriter writer = contentService.getWriter(testContext.contentNodeRef, ContentModel.PROP_CONTENT, true);
+ writer.setLocale(CONTENT_LOCALE);
+ writer.setEncoding(CONTENT_ENCODING);
+ writer.putContent(testContext.contentString);
+ return null;
+ }
+ };
+
+ RetryingTransactionCallback transferCB = new RetryingTransactionCallback() {
+
+ @Override
+ public Void execute() throws Throwable
+ {
+ TransferDefinition definition = new TransferDefinition();
+ Setnodes = new HashSet();
+ nodes.add(testContext.contentNodeRef);
+ definition.setNodes(nodes);
+ transferService.transfer(targetName, definition);
+ return null;
+ }
+ };
+
+ RetryingTransactionCallback checkTransferCB = new RetryingTransactionCallback() {
+
+ @Override
+ public Void execute() throws Throwable
+ {
+ // Now validate that the target node exists and has similar properties to the source
+ NodeRef destNodeRef = testNodeFactory.getMappedNodeRef(testContext.contentNodeRef);
+
+ ContentReader reader = contentService.getReader(destNodeRef, ContentModel.PROP_CONTENT);
+ assertNotNull("content reader is null", reader);
+ assertEquals("content encoding is wrong", reader.getEncoding(), CONTENT_ENCODING);
+ assertEquals("content locale is wrong", reader.getLocale(), CONTENT_LOCALE);
+ assertTrue("content does not exist", reader.exists());
+ String contentStr = reader.getContentString();
+ assertEquals("Content is wrong", contentStr, testContext.contentString);
+
+ return null;
+ }
+ };
+
+ /**
+ * This is the test
+ */
+ for(int i = 0; i < 6 ; i++)
+ {
+ logger.debug("testRepeatUpdateContent - iteration:" + i);
+ testContext.contentString = String.valueOf(i);
+ tran.doInTransaction(updateContentCB);
+ tran.doInTransaction(transferCB);
+ tran.doInTransaction(checkTransferCB);
+ }
+ } // test repeat update content
private void createUser(String userName, String password)