diff --git a/source/java/org/alfresco/repo/transfer/HttpClientTransmitterImpl.java b/source/java/org/alfresco/repo/transfer/HttpClientTransmitterImpl.java index c50a7337eb..a46e7e1279 100644 --- a/source/java/org/alfresco/repo/transfer/HttpClientTransmitterImpl.java +++ b/source/java/org/alfresco/repo/transfer/HttpClientTransmitterImpl.java @@ -307,22 +307,22 @@ public class HttpClientTransmitterImpl implements TransferTransmitter int responseStatus = httpClient.executeMethod(hostConfig, postSnapshotRequest, httpState); checkResponseStatus("sendManifest", responseStatus, postSnapshotRequest); - InputStream is = postSnapshotRequest.getResponseBodyAsStream(); - InputStreamReader reader = new InputStreamReader(is); - BufferedReader br = new BufferedReader(reader); - BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(result)); - - String s = br.readLine(); - while(s != null) + final ReadableByteChannel inputChannel = Channels.newChannel(is); + final WritableByteChannel outputChannel = Channels.newChannel(result); + try { - bw.write(s); - s = br.readLine(); + // copy the channels + channelCopy(inputChannel, outputChannel); } - bw.close(); - + finally + { + inputChannel.close(); + outputChannel.close(); + } + return; } catch (RuntimeException e) diff --git a/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java b/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java index 8801f03ab1..dcf697ce46 100644 --- a/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java +++ b/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java @@ -780,17 +780,26 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB { ContentData contentData = (ContentData) contentEntry.getValue(); String contentUrl = contentData.getContentUrl(); - String fileName = TransferCommons.URLToPartName(contentUrl); - File stagedFile = new File(stagingDir, fileName); - if (!stagedFile.exists()) + if(contentUrl == null || contentUrl.isEmpty()) { - error(MSG_REFERENCED_CONTENT_FILE_MISSING); + log.debug("content data is null or empty:" + nodeToUpdate); + ContentData cd = new ContentData(null, null, 0, null); + nodeService.setProperty(nodeToUpdate, contentEntry.getKey(), cd); + } + else + { + String fileName = TransferCommons.URLToPartName(contentUrl); + File stagedFile = new File(stagingDir, fileName); + if (!stagedFile.exists()) + { + error(MSG_REFERENCED_CONTENT_FILE_MISSING); + } + ContentWriter writer = contentService.getWriter(nodeToUpdate, contentEntry.getKey(), true); + writer.setEncoding(contentData.getEncoding()); + writer.setMimetype(contentData.getMimetype()); + writer.setLocale(contentData.getLocale()); + writer.putContent(stagedFile); } - ContentWriter writer = contentService.getWriter(nodeToUpdate, contentEntry.getKey(), true); - writer.setEncoding(contentData.getEncoding()); - writer.setMimetype(contentData.getMimetype()); - writer.setLocale(contentData.getLocale()); - writer.putContent(stagedFile); } } diff --git a/source/java/org/alfresco/repo/transfer/RepoRequisiteManifestProcessorImpl.java b/source/java/org/alfresco/repo/transfer/RepoRequisiteManifestProcessorImpl.java index 9b9bce2303..20a505f3ed 100644 --- a/source/java/org/alfresco/repo/transfer/RepoRequisiteManifestProcessorImpl.java +++ b/source/java/org/alfresco/repo/transfer/RepoRequisiteManifestProcessorImpl.java @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2009-2010 Alfresco Software Limited. * * This file is part of Alfresco @@ -14,208 +14,207 @@ * 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.OutputStream; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.alfresco.model.ContentModel; -import org.alfresco.repo.transfer.manifest.TransferManifestDeletedNode; -import org.alfresco.repo.transfer.manifest.TransferManifestHeader; -import org.alfresco.repo.transfer.manifest.TransferManifestNodeHelper; -import org.alfresco.repo.transfer.manifest.TransferManifestNormalNode; -import org.alfresco.repo.transfer.requisite.TransferRequsiteWriter; -import org.alfresco.service.cmr.repository.AssociationRef; -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.ContentData; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.NodeService; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.transfer.TransferReceiver; -import org.alfresco.service.namespace.QName; -import org.alfresco.service.namespace.RegexQNamePattern; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.xml.sax.SAXParseException; - -/** - * @author mrogers - * - * The requsite manifest processor performs a parse of the manifest file to determine which - * resources are required. - * - */ -public class RepoRequisiteManifestProcessorImpl extends AbstractManifestProcessorBase -{ - private NodeService nodeService; - private CorrespondingNodeResolver nodeResolver; - private TransferRequsiteWriter out; - - - private static final Log log = LogFactory.getLog(RepoRequisiteManifestProcessorImpl.class); - - /** - * @param receiver - * @param transferId - */ - public RepoRequisiteManifestProcessorImpl(TransferReceiver receiver, String transferId, TransferRequsiteWriter out) - { - super(receiver, transferId); - this.out = out; - } - - protected void endManifest() - { - log.debug("End Requsite"); - out.endTransferRequsite(); - } - - protected void processNode(TransferManifestDeletedNode node) - { - //NOOP - } - - protected void processNode(TransferManifestNormalNode node) - { - - if (log.isDebugEnabled()) - { - log.debug("Processing node with incoming noderef of " + node.getNodeRef()); - } - logComment("Primary Processing incoming node: " + node.getNodeRef() + " -- Source path = " + node.getParentPath() + "/" + node.getPrimaryParentAssoc().getQName()); - - ChildAssociationRef primaryParentAssoc = node.getPrimaryParentAssoc(); - - CorrespondingNodeResolver.ResolvedParentChildPair resolvedNodes = nodeResolver.resolveCorrespondingNode(node - .getNodeRef(), primaryParentAssoc, node.getParentPath()); - - // Does a corresponding node exist in this repo? - if (resolvedNodes.resolvedChild != null) - { - /** - * there is a corresponding node so we need to check whether we already - * have the content item - */ - NodeRef destinationNode = resolvedNodes.resolvedChild; - - Map destProps = nodeService.getProperties(destinationNode); - - - - for (Map.Entry propEntry : node.getProperties().entrySet()) - { - Serializable value = propEntry.getValue(); - if (log.isDebugEnabled()) - { - if (value == null) - { - log.debug("Received a null value for property " + propEntry.getKey()); - } - } - if ((value != null) && ContentData.class.isAssignableFrom(value.getClass())) - { - ContentData srcContent = (ContentData)value; - Serializable destSer = destProps.get(propEntry.getKey()); - if(destSer != null && ContentData.class.isAssignableFrom(destSer.getClass())) - { - ContentData destContent = (ContentData)destProps.get(propEntry.getKey()); - - /** - * If the modification dates for the node are different - */ - Serializable srcModified = node.getProperties().get(ContentModel.PROP_MODIFIED); - Serializable destModified = destProps.get(ContentModel.PROP_MODIFIED); - - log.debug ("srcModified :" + srcModified + "destModified :" + destModified); - - if(srcModified != null && - destModified != null && - srcModified instanceof Date && - destModified instanceof Date && - ((Date)srcModified).getTime() <= ((Date)destModified).getTime()) - { - if(log.isDebugEnabled()) - { - log.debug("the modified date is the same - no need to send it:" + destContent.getContentUrl()); - } - } - else - { - out.missingContent(node.getNodeRef(), propEntry.getKey(), TransferCommons.URLToPartName(srcContent.getContentUrl())); - } - } - else - { - // We don't have the property on the destination node - out.missingContent(node.getNodeRef(), propEntry.getKey(), TransferCommons.URLToPartName(srcContent.getContentUrl())); - } - } - } - } - else - { - /** - * there is no corresponding node so all content properties are "missing." - */ - for (Map.Entry propEntry : node.getProperties().entrySet()) - { - Serializable value = propEntry.getValue(); - if (log.isDebugEnabled()) - { - if (value == null) - { - log.debug("Received a null value for property " + propEntry.getKey()); - } - } - if ((value != null) && ContentData.class.isAssignableFrom(value.getClass())) - { - ContentData content = (ContentData)value; - // - out.missingContent(node.getNodeRef(), propEntry.getKey(), TransferCommons.URLToPartName(content.getContentUrl())); - } - } - } - } - - protected void processHeader(TransferManifestHeader header) - { - // T.B.D - } - - /* - * (non-Javadoc) - * - * @see org.alfresco.repo.transfer.manifest.TransferManifestProcessor#startTransferManifest() - */ - protected void startManifest() - { - log.debug("Start Requsite"); - out.startTransferRequsite(); - } - - /** - * @param nodeService - * the nodeService to set - */ - public void setNodeService(NodeService nodeService) - { - this.nodeService = nodeService; - } - - /** - * @param nodeResolver - * the nodeResolver to set - */ - public void setNodeResolver(CorrespondingNodeResolver nodeResolver) - { - this.nodeResolver = nodeResolver; - } -} + * along with Alfresco. If not, see . + */ + +package org.alfresco.repo.transfer; + +import java.io.Serializable; +import java.util.Date; +import java.util.Map; + +import org.alfresco.model.ContentModel; +import org.alfresco.repo.transfer.manifest.TransferManifestDeletedNode; +import org.alfresco.repo.transfer.manifest.TransferManifestHeader; +import org.alfresco.repo.transfer.manifest.TransferManifestNormalNode; +import org.alfresco.repo.transfer.requisite.TransferRequsiteWriter; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.transfer.TransferReceiver; +import org.alfresco.service.namespace.QName; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * @author mrogers + * + * The requisite manifest processor performs a parse of the manifest file to determine which + * resources are required. In particular it returns a list of nodes which require content to be transferred. + * + */ +public class RepoRequisiteManifestProcessorImpl extends AbstractManifestProcessorBase +{ + private NodeService nodeService; + private CorrespondingNodeResolver nodeResolver; + private TransferRequsiteWriter out; + + + private static final Log log = LogFactory.getLog(CopyRepoRequisiteManifestProcessorImpl.class); + + /** + * @param receiver + * @param transferId + */ + public RepoRequisiteManifestProcessorImpl(TransferReceiver receiver, String transferId, TransferRequsiteWriter out) + { + super(receiver, transferId); + this.out = out; + } + + protected void endManifest() + { + log.debug("End Requsite"); + out.endTransferRequsite(); + } + + protected void processNode(TransferManifestDeletedNode node) + { + //NOOP + } + + protected void processNode(TransferManifestNormalNode node) + { + + if (log.isDebugEnabled()) + { + log.debug("Processing node with incoming noderef of " + node.getNodeRef()); + } + logComment("Primary Processing incoming node: " + node.getNodeRef() + " -- Source path = " + node.getParentPath() + "/" + node.getPrimaryParentAssoc().getQName()); + + ChildAssociationRef primaryParentAssoc = node.getPrimaryParentAssoc(); + + CorrespondingNodeResolver.ResolvedParentChildPair resolvedNodes = nodeResolver.resolveCorrespondingNode(node + .getNodeRef(), primaryParentAssoc, node.getParentPath()); + + // Does a corresponding node exist in this repo? + if (resolvedNodes.resolvedChild != null) + { + /** + * there is a corresponding node so we need to check whether we already + * have the content item + */ + NodeRef destinationNode = resolvedNodes.resolvedChild; + + Map destProps = nodeService.getProperties(destinationNode); + + + + for (Map.Entry propEntry : node.getProperties().entrySet()) + { + Serializable value = propEntry.getValue(); + if (log.isDebugEnabled()) + { + if (value == null) + { + log.debug("Received a null value for property " + propEntry.getKey()); + } + } + if ((value != null) && ContentData.class.isAssignableFrom(value.getClass())) + { + ContentData srcContent = (ContentData)value; + + if(srcContent.getContentUrl() != null && !srcContent.getContentUrl().isEmpty() ) + { + Serializable destSer = destProps.get(propEntry.getKey()); + if(destSer != null && ContentData.class.isAssignableFrom(destSer.getClass())) + { + ContentData destContent = (ContentData)destProps.get(propEntry.getKey()); + /** + * If the modification dates for the node are different + */ + Serializable srcModified = node.getProperties().get(ContentModel.PROP_MODIFIED); + Serializable destModified = destProps.get(ContentModel.PROP_MODIFIED); + + log.debug ("srcModified :" + srcModified + "destModified :" + destModified); + + if(srcModified != null && + destModified != null && + srcModified instanceof Date && + destModified instanceof Date && + ((Date)srcModified).getTime() <= ((Date)destModified).getTime()) + { + if(log.isDebugEnabled()) + { + log.debug("the modified date is the same or before - no need to send it:" + destContent.getContentUrl()); + } + } + else + { + log.debug("require content for node : " + node.getNodeRef()); + out.missingContent(node.getNodeRef(), propEntry.getKey(), TransferCommons.URLToPartName(srcContent.getContentUrl())); + } + } + else + { + // We don't have the property on the destination node + out.missingContent(node.getNodeRef(), propEntry.getKey(), TransferCommons.URLToPartName(srcContent.getContentUrl())); + } + } // content url not null + } // value is content data + } + } + else + { + log.debug("Node does not exist on destination"); + /** + * there is no corresponding node so all content properties are "missing." + */ + for (Map.Entry propEntry : node.getProperties().entrySet()) + { + Serializable value = propEntry.getValue(); + if (log.isDebugEnabled()) + { + if (value == null) + { + log.debug("Received a null value for property " + propEntry.getKey()); + } + } + if ((value != null) && ContentData.class.isAssignableFrom(value.getClass())) + { + ContentData srcContent = (ContentData)value; + if(srcContent.getContentUrl() != null && !srcContent.getContentUrl().isEmpty()) + { + // + out.missingContent(node.getNodeRef(), propEntry.getKey(), TransferCommons.URLToPartName(srcContent.getContentUrl())); + } + } + } + } + } + + protected void processHeader(TransferManifestHeader header) + { + // T.B.D + } + + /* + * (non-Javadoc) + * + * @see org.alfresco.repo.transfer.manifest.TransferManifestProcessor#startTransferManifest() + */ + protected void startManifest() + { + log.debug("Start Requsite"); + out.startTransferRequsite(); + } + + /** + * @param nodeService + * the nodeService to set + */ + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + /** + * @param nodeResolver + * the nodeResolver to set + */ + public void setNodeResolver(CorrespondingNodeResolver nodeResolver) + { + this.nodeResolver = nodeResolver; + } +} diff --git a/source/java/org/alfresco/repo/transfer/TransferServiceImplTest.java b/source/java/org/alfresco/repo/transfer/TransferServiceImplTest.java index 3b6cdde494..0e4e0e9826 100644 --- a/source/java/org/alfresco/repo/transfer/TransferServiceImplTest.java +++ b/source/java/org/alfresco/repo/transfer/TransferServiceImplTest.java @@ -21,15 +21,23 @@ package org.alfresco.repo.transfer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Queue; import java.util.Set; +import javax.transaction.Status; import javax.transaction.UserTransaction; import javax.xml.XMLConstants; import javax.xml.transform.Source; @@ -47,6 +55,7 @@ import org.alfresco.service.cmr.action.ActionService; import org.alfresco.service.cmr.lock.LockService; import org.alfresco.service.cmr.lock.LockType; import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.ContentData; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.ContentWriter; @@ -614,18 +623,20 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest * Step 2: Update Node title property * transfer * - * Step 3: Update Content property + * Step 3: Update Content property (add content) * transfer * * Step 4: Transfer again * transfer (Should transfer but not request the content item) - * - * Step 5: Delete the node * - * Step 6: Negative test : transfer no nodes + * Step 5: Update Content property (update content) + * + * Step 6: Delete the node + * + * Step 7: Negative test : transfer no nodes * transfer (should throw exception) * - * Step 7: Negative test : transfer to a disabled transfer target + * Step 8: Negative test : transfer to a disabled transfer target * transfer (should throw exception) * * This is a unit test so it does some shenanigans to send to the same instance of alfresco. @@ -637,7 +648,8 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest String CONTENT_TITLE = "ContentTitle"; String CONTENT_TITLE_UPDATED = "ContentTitleUpdated"; Locale CONTENT_LOCALE = Locale.GERMAN; - String CONTENT_STRING = "Hello"; + String CONTENT_STRING = "Hello World"; + String CONTENT_UPDATE_STRING = "Foo Bar"; /** * For unit test @@ -801,17 +813,28 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest // Check injected transferred aspect. assertNotNull("transferredAspect", (String)nodeService.getProperty(destNodeRef, TransferModel.PROP_REPOSITORY_ID)); - ContentWriter writer = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true); - writer.setLocale(CONTENT_LOCALE); - writer.putContent(CONTENT_STRING); - } finally { endTransaction(); } - logger.debug("Transfer again - this is an update with new content"); + /** + * Step 3 - update to add content + */ + startNewTransaction(); + try + { + ContentWriter writer = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true); + writer.setLocale(CONTENT_LOCALE); + writer.putContent(CONTENT_STRING); + } + finally + { + endTransaction(); + } + + logger.debug("Transfer again - this is an update to add new content"); startNewTransaction(); try { @@ -831,7 +854,20 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest { endTransaction(); } - + + startNewTransaction(); + try + { + ContentReader reader = contentService.getReader(destNodeRef, ContentModel.PROP_CONTENT); + assertNotNull("reader is null", reader); + String contentStr = reader.getContentString(); + assertEquals("Content is wrong", contentStr, CONTENT_STRING); + } + finally + { + endTransaction(); + } + /** * Step 4: * Now transfer nothing - content items do not need to be transferred since its already on @@ -861,6 +897,11 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest assertEquals("title is wrong", (String)nodeService.getProperty(destNodeRef, ContentModel.PROP_TITLE), CONTENT_TITLE_UPDATED); assertEquals("type is wrong", nodeService.getType(contentNodeRef), nodeService.getType(destNodeRef)); + ContentReader reader = contentService.getReader(destNodeRef, ContentModel.PROP_CONTENT); + assertNotNull("reader is null", reader); + String contentStr = reader.getContentString(); + assertEquals("Content is wrong", contentStr, CONTENT_STRING); + // Check injected transferred aspect. assertNotNull("transferredAspect", (String)nodeService.getProperty(destNodeRef, TransferModel.PROP_REPOSITORY_ID)); @@ -869,12 +910,61 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest { endTransaction(); } + + /** + * Step 5 - update content through transfer + */ + startNewTransaction(); + try + { + ContentWriter writer = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true); + writer.setLocale(CONTENT_LOCALE); + writer.putContent(CONTENT_UPDATE_STRING); + } + finally + { + endTransaction(); + } + + logger.debug("Transfer again - this is an update to add new content"); + startNewTransaction(); + try + { + /** + * Step 3: + * Transfer our node again - so this is an update + */ + { + TransferDefinition definition = new TransferDefinition(); + Setnodes = new HashSet(); + nodes.add(contentNodeRef); + definition.setNodes(nodes); + transferService.transfer(targetName, definition); + } + } + finally + { + endTransaction(); + } + + startNewTransaction(); + try + { + ContentReader reader = contentService.getReader(destNodeRef, ContentModel.PROP_CONTENT); + assertNotNull("reader is null", reader); + String contentStr = reader.getContentString(); + assertEquals("Content is wrong", CONTENT_UPDATE_STRING, contentStr); + } + finally + { + endTransaction(); + } /** - * Step 5 + * Step 6 * Delete the node through transfer of the archive node */ - logger.debug("Transfer again - with no new content"); + logger.debug("Transfer again - to delete a node through transferring an archive node"); startNewTransaction(); try { @@ -912,7 +1002,7 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest } /** - * Step 6 + * Step 7 * Negative test transfer nothing */ logger.debug("Transfer again - with no content - should throw exception"); @@ -1882,6 +1972,8 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest } finally { + int status = trx.getStatus(); + trx.commit(); } } @@ -2022,7 +2114,7 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest } // test async cancel - /** + /** * Test the transfer report. * * This is a unit test so it does some shenanigans to send to the same instance of alfresco. @@ -2294,6 +2386,24 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest endTransaction(); } } // test transfer report + + + private void dumpToSystemOut(NodeRef nodeRef) throws IOException + { + ContentReader reader2 = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT); + assertNotNull("transfer reader is null", reader2); + InputStream is = reader2.getContentInputStream(); + + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + + String s = br.readLine(); + while(s != null) + { + System.out.println(s); + s = br.readLine(); + } + } + // /** // * Test the transfer method with big content - commented out since it takes a long time to run. @@ -6746,8 +6856,247 @@ 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 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.CANADA; + String CONTENT_STRING = "Hello"; + /** + * 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 destNodeRef; + + 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(); + } + + logger.debug("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)); + + /** + * Step 1: Transfer our node which has empty 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(); + } + + /** + * Step 2 + */ + logger.debug("Second transfer - replace empty content"); + + startNewTransaction(); + try + { + ContentWriter writer = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true); + writer.setLocale(CONTENT_LOCALE); + 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); + ContentReader reader = contentService.getReader(destinationNodeRef, ContentModel.PROP_CONTENT); + assertNotNull("content reader is null", reader); + assertTrue("content does not exist", reader.exists()); + } + finally + { + endTransaction(); + } + + /** + * Step 3 + */ + logger.debug("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(); + } + + } private void createUser(String userName, String password) {