mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
transfer service : work in progress.
implementation of transfer requsite. API change isComplete to isSync git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@21130 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -151,7 +151,7 @@ public class ReplicationActionExecutor extends ActionExecuterAbstractBase {
|
|||||||
TransferDefinition transferDefinition =
|
TransferDefinition transferDefinition =
|
||||||
new TransferDefinition();
|
new TransferDefinition();
|
||||||
transferDefinition.setNodes(toTransfer);
|
transferDefinition.setNodes(toTransfer);
|
||||||
transferDefinition.setComplete(true);
|
transferDefinition.setSync(true);
|
||||||
|
|
||||||
return transferDefinition;
|
return transferDefinition;
|
||||||
}
|
}
|
||||||
|
@@ -632,7 +632,7 @@ public class ReplicationServiceIntegrationTest extends BaseAlfrescoSpringTest
|
|||||||
nodes.add(content1_1);
|
nodes.add(content1_1);
|
||||||
|
|
||||||
TransferDefinition td = replicationActionExecutor.buildTransferDefinition(rd, nodes);
|
TransferDefinition td = replicationActionExecutor.buildTransferDefinition(rd, nodes);
|
||||||
assertEquals(true, td.isComplete());
|
assertEquals(true, td.isSync());
|
||||||
assertEquals(2, td.getNodes().size());
|
assertEquals(2, td.getNodes().size());
|
||||||
assertEquals(true, td.getNodes().contains(folder1));
|
assertEquals(true, td.getNodes().contains(folder1));
|
||||||
assertEquals(true, td.getNodes().contains(content1_1));
|
assertEquals(true, td.getNodes().contains(content1_1));
|
||||||
|
@@ -23,6 +23,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.alfresco.repo.transfer.manifest.TransferManifestProcessor;
|
import org.alfresco.repo.transfer.manifest.TransferManifestProcessor;
|
||||||
|
import org.alfresco.repo.transfer.requisite.TransferRequsiteWriter;
|
||||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
import org.alfresco.service.cmr.repository.ContentService;
|
import org.alfresco.service.cmr.repository.ContentService;
|
||||||
import org.alfresco.service.cmr.repository.NodeService;
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
@@ -102,4 +103,20 @@ public class DefaultManifestProcessorFactoryImpl implements ManifestProcessorFac
|
|||||||
this.nodeResolverFactory = nodeResolverFactory;
|
this.nodeResolverFactory = nodeResolverFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public TransferManifestProcessor getRequsiteProcessor(
|
||||||
|
TransferReceiver receiver, String transferId, TransferRequsiteWriter out)
|
||||||
|
{
|
||||||
|
RepoRequsiteManifestProcessorImpl processor = new RepoRequsiteManifestProcessorImpl(receiver, transferId, out);
|
||||||
|
|
||||||
|
CorrespondingNodeResolver nodeResolver = nodeResolverFactory.getResolver();
|
||||||
|
|
||||||
|
processor.setNodeResolver(nodeResolver);
|
||||||
|
processor.setNodeService(nodeService);
|
||||||
|
|
||||||
|
return processor;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -18,12 +18,31 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.transfer;
|
package org.alfresco.repo.transfer;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Details back from the manifest to say which nodes the remote server already has.
|
* Details back from reading the manifest to say what is required to fulfill the manifest.
|
||||||
*
|
*
|
||||||
* @author Mark Rogers
|
* @author Mark Rogers
|
||||||
*/
|
*/
|
||||||
public class DeltaList
|
public class DeltaList
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* The set of requiredURLs
|
||||||
|
*/
|
||||||
|
|
||||||
|
private TreeSet<String> requiredURLs = new TreeSet<String>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the list of URLs reqired by the manifest.
|
||||||
|
* @return the list of required URLs
|
||||||
|
*/
|
||||||
|
public Set<String> getRequiredURLs()
|
||||||
|
{
|
||||||
|
return requiredURLs;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -19,7 +19,13 @@
|
|||||||
|
|
||||||
package org.alfresco.repo.transfer;
|
package org.alfresco.repo.transfer;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
@@ -254,7 +260,7 @@ public class HttpClientTransmitterImpl implements TransferTransmitter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeltaList sendManifest(Transfer transfer, File manifest) throws TransferException
|
public void sendManifest(Transfer transfer, File manifest, OutputStream result) throws TransferException
|
||||||
{
|
{
|
||||||
TransferTarget target = transfer.getTransferTarget();
|
TransferTarget target = transfer.getTransferTarget();
|
||||||
PostMethod postSnapshotRequest = new PostMethod();
|
PostMethod postSnapshotRequest = new PostMethod();
|
||||||
@@ -288,7 +294,23 @@ public class HttpClientTransmitterImpl implements TransferTransmitter
|
|||||||
|
|
||||||
int responseStatus = httpClient.executeMethod(hostConfig, postSnapshotRequest, httpState);
|
int responseStatus = httpClient.executeMethod(hostConfig, postSnapshotRequest, httpState);
|
||||||
checkResponseStatus("sendManifest", responseStatus, postSnapshotRequest);
|
checkResponseStatus("sendManifest", responseStatus, postSnapshotRequest);
|
||||||
return null;
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
bw.write(s);
|
||||||
|
s = br.readLine();
|
||||||
|
}
|
||||||
|
bw.close();
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
catch (RuntimeException e)
|
catch (RuntimeException e)
|
||||||
{
|
{
|
||||||
@@ -453,7 +475,6 @@ public class HttpClientTransmitterImpl implements TransferTransmitter
|
|||||||
int index = 0;
|
int index = 0;
|
||||||
for(ContentData content : data)
|
for(ContentData content : data)
|
||||||
{
|
{
|
||||||
// TODO Encapsulate the URL to FileName algorithm
|
|
||||||
String contentUrl = content.getContentUrl();
|
String contentUrl = content.getContentUrl();
|
||||||
String fileName = TransferCommons.URLToPartName(contentUrl);
|
String fileName = TransferCommons.URLToPartName(contentUrl);
|
||||||
log.debug("content partName: " + fileName);
|
log.debug("content partName: " + fileName);
|
||||||
|
@@ -22,13 +22,29 @@ package org.alfresco.repo.transfer;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.alfresco.repo.transfer.manifest.TransferManifestProcessor;
|
import org.alfresco.repo.transfer.manifest.TransferManifestProcessor;
|
||||||
|
import org.alfresco.repo.transfer.requisite.TransferRequsiteWriter;
|
||||||
import org.alfresco.service.cmr.transfer.TransferReceiver;
|
import org.alfresco.service.cmr.transfer.TransferReceiver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author brian
|
* @author brian
|
||||||
*
|
*
|
||||||
|
* This is a factory class for the processors of the transfer manifest file.
|
||||||
*/
|
*/
|
||||||
public interface ManifestProcessorFactory
|
public interface ManifestProcessorFactory
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* The requisite processor
|
||||||
|
* @param receiver
|
||||||
|
* @param transferId
|
||||||
|
* @return the requisite processor
|
||||||
|
*/
|
||||||
|
TransferManifestProcessor getRequsiteProcessor(TransferReceiver receiver, String transferId, TransferRequsiteWriter out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The commit processors
|
||||||
|
* @param receiver
|
||||||
|
* @param transferId
|
||||||
|
* @return the requsite processor
|
||||||
|
*/
|
||||||
List<TransferManifestProcessor> getCommitProcessors(TransferReceiver receiver, String transferId);
|
List<TransferManifestProcessor> getCommitProcessors(TransferReceiver receiver, String transferId);
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,213 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.alfresco.repo.transfer;
|
||||||
|
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
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 RepoRequsiteManifestProcessorImpl extends AbstractManifestProcessorBase
|
||||||
|
{
|
||||||
|
private NodeService nodeService;
|
||||||
|
private CorrespondingNodeResolver nodeResolver;
|
||||||
|
private TransferRequsiteWriter out;
|
||||||
|
|
||||||
|
|
||||||
|
private static final Log log = LogFactory.getLog(RepoRequsiteManifestProcessorImpl.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param receiver
|
||||||
|
* @param transferId
|
||||||
|
*/
|
||||||
|
public RepoRequsiteManifestProcessorImpl(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());
|
||||||
|
}
|
||||||
|
logProgress("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;
|
||||||
|
|
||||||
|
// Serializable yy = node.getProperties().get(ContentModel.PROP_MODIFIED);
|
||||||
|
Map<QName, Serializable> destProps = nodeService.getProperties(destinationNode);
|
||||||
|
// Serializable xx = destProps.get(ContentModel.PROP_MODIFIED);
|
||||||
|
|
||||||
|
for (Map.Entry<QName, Serializable> 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 URLs are the same then the content is already on the server
|
||||||
|
*/
|
||||||
|
if(TransferCommons.URLToPartName(destContent.getContentUrl()).equalsIgnoreCase(
|
||||||
|
TransferCommons.URLToPartName(srcContent.getContentUrl())))
|
||||||
|
{
|
||||||
|
if(log.isDebugEnabled())
|
||||||
|
{
|
||||||
|
log.debug("the url is the same - no need to send it:" + destContent.getContentUrl());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We need to diff the property
|
||||||
|
out.missingContent(node.getNodeRef(), propEntry.getKey(), srcContent.getContentUrl());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We don't have the property on the destination node
|
||||||
|
out.missingContent(node.getNodeRef(), propEntry.getKey(), srcContent.getContentUrl());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* there is no corresponding node so all content properties are "missing."
|
||||||
|
*/
|
||||||
|
for (Map.Entry<QName, Serializable> 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(), 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;
|
||||||
|
}
|
||||||
|
}
|
@@ -56,9 +56,9 @@ public class RepoTertiaryManifestProcessorImpl extends AbstractManifestProcessor
|
|||||||
private static final Log log = LogFactory.getLog(RepoTertiaryManifestProcessorImpl.class);
|
private static final Log log = LogFactory.getLog(RepoTertiaryManifestProcessorImpl.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this a "complete" transfer. If not then does nothing.
|
* Is this a "sync" transfer. If not then does nothing.
|
||||||
*/
|
*/
|
||||||
boolean isComplete = false;
|
boolean isSync = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param receiver
|
* @param receiver
|
||||||
@@ -84,7 +84,7 @@ public class RepoTertiaryManifestProcessorImpl extends AbstractManifestProcessor
|
|||||||
NodeRef nodeRef = node.getNodeRef();
|
NodeRef nodeRef = node.getNodeRef();
|
||||||
log.debug("processNode " + nodeRef);
|
log.debug("processNode " + nodeRef);
|
||||||
|
|
||||||
if(isComplete)
|
if(isSync)
|
||||||
{
|
{
|
||||||
|
|
||||||
List<ChildAssociationRef> expectedChildren = node.getChildAssocs();
|
List<ChildAssociationRef> expectedChildren = node.getChildAssocs();
|
||||||
@@ -144,8 +144,8 @@ public class RepoTertiaryManifestProcessorImpl extends AbstractManifestProcessor
|
|||||||
|
|
||||||
protected void processHeader(TransferManifestHeader header)
|
protected void processHeader(TransferManifestHeader header)
|
||||||
{
|
{
|
||||||
isComplete = header.isComplete();
|
isSync = header.isSync();
|
||||||
log.debug("isComplete :" + isComplete);
|
log.debug("isSync :" + isSync);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -23,7 +23,10 @@ import java.io.BufferedOutputStream;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
import java.io.Writer;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -45,6 +48,7 @@ import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
|||||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
import org.alfresco.repo.transfer.manifest.TransferManifestProcessor;
|
import org.alfresco.repo.transfer.manifest.TransferManifestProcessor;
|
||||||
import org.alfresco.repo.transfer.manifest.XMLTransferManifestReader;
|
import org.alfresco.repo.transfer.manifest.XMLTransferManifestReader;
|
||||||
|
import org.alfresco.repo.transfer.requisite.XMLTransferRequsiteWriter;
|
||||||
import org.alfresco.service.cmr.action.Action;
|
import org.alfresco.service.cmr.action.Action;
|
||||||
import org.alfresco.service.cmr.action.ActionService;
|
import org.alfresco.service.cmr.action.ActionService;
|
||||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
@@ -127,6 +131,7 @@ public class RepoTransferReceiverImpl implements TransferReceiver
|
|||||||
private static final String MSG_ERROR_WHILE_STAGING_CONTENT = "transfer_service.receiver.error_staging_content";
|
private static final String MSG_ERROR_WHILE_STAGING_CONTENT = "transfer_service.receiver.error_staging_content";
|
||||||
private static final String MSG_NO_SNAPSHOT_RECEIVED = "transfer_service.receiver.no_snapshot_received";
|
private static final String MSG_NO_SNAPSHOT_RECEIVED = "transfer_service.receiver.no_snapshot_received";
|
||||||
private static final String MSG_ERROR_WHILE_COMMITTING_TRANSFER = "transfer_service.receiver.error_committing_transfer";
|
private static final String MSG_ERROR_WHILE_COMMITTING_TRANSFER = "transfer_service.receiver.error_committing_transfer";
|
||||||
|
private static final String MSG_ERROR_WHILE_GENERATING_REQUISITE = "transfer_service.receiver.error_generating_requsite";
|
||||||
|
|
||||||
private static final String LOCK_FILE_NAME = ".lock";
|
private static final String LOCK_FILE_NAME = ".lock";
|
||||||
private static final QName LOCK_QNAME = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, LOCK_FILE_NAME);
|
private static final QName LOCK_QNAME = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, LOCK_FILE_NAME);
|
||||||
@@ -846,4 +851,55 @@ public class RepoTransferReceiverImpl implements TransferReceiver
|
|||||||
return this.ruleService;
|
return this.ruleService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate the requsite
|
||||||
|
*/
|
||||||
|
public void generateRequsite(String transferId, OutputStream out) throws TransferException
|
||||||
|
{
|
||||||
|
log.debug("Generate Requsite for transfer:" + transferId);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File snapshotFile = getSnapshotFile(transferId);
|
||||||
|
|
||||||
|
if (snapshotFile.exists())
|
||||||
|
{
|
||||||
|
log.debug("snapshot does exist");
|
||||||
|
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
|
||||||
|
SAXParser parser = saxParserFactory.newSAXParser();
|
||||||
|
OutputStreamWriter dest = new OutputStreamWriter(out, "UTF-8");
|
||||||
|
|
||||||
|
XMLTransferRequsiteWriter writer = new XMLTransferRequsiteWriter(dest);
|
||||||
|
TransferManifestProcessor processor = manifestProcessorFactory.getRequsiteProcessor(
|
||||||
|
RepoTransferReceiverImpl.this,
|
||||||
|
transferId,
|
||||||
|
writer);
|
||||||
|
|
||||||
|
XMLTransferManifestReader reader = new XMLTransferManifestReader(processor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Now run the parser
|
||||||
|
*/
|
||||||
|
parser.parse(snapshotFile, reader);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* And flush the destination in case any content remains in the writer.
|
||||||
|
*/
|
||||||
|
dest.flush();
|
||||||
|
|
||||||
|
}
|
||||||
|
log.debug("Generate Requsite done transfer:" + transferId);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (TransferException.class.isAssignableFrom(ex.getClass()))
|
||||||
|
{
|
||||||
|
throw (TransferException) ex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new TransferException(MSG_ERROR_WHILE_GENERATING_REQUISITE, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,6 +20,7 @@ package org.alfresco.repo.transfer;
|
|||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -57,6 +58,8 @@ import org.alfresco.repo.transfer.manifest.TransferManifestWriter;
|
|||||||
import org.alfresco.repo.transfer.manifest.XMLTransferManifestReader;
|
import org.alfresco.repo.transfer.manifest.XMLTransferManifestReader;
|
||||||
import org.alfresco.repo.transfer.manifest.XMLTransferManifestWriter;
|
import org.alfresco.repo.transfer.manifest.XMLTransferManifestWriter;
|
||||||
import org.alfresco.repo.transfer.report.TransferReporter;
|
import org.alfresco.repo.transfer.report.TransferReporter;
|
||||||
|
import org.alfresco.repo.transfer.requisite.DeltaListRequsiteProcessor;
|
||||||
|
import org.alfresco.repo.transfer.requisite.XMLTransferRequsiteReader;
|
||||||
import org.alfresco.service.cmr.action.Action;
|
import org.alfresco.service.cmr.action.Action;
|
||||||
import org.alfresco.service.cmr.action.ActionService;
|
import org.alfresco.service.cmr.action.ActionService;
|
||||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||||
@@ -530,6 +533,8 @@ public class TransferServiceImpl implements TransferService
|
|||||||
eventProcessor.addObserver(reportCallback);
|
eventProcessor.addObserver(reportCallback);
|
||||||
|
|
||||||
File snapshotFile = null;
|
File snapshotFile = null;
|
||||||
|
File reqFile = null;
|
||||||
|
|
||||||
TransferTarget target = null;
|
TransferTarget target = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -555,6 +560,8 @@ public class TransferServiceImpl implements TransferService
|
|||||||
// where to put snapshot ?
|
// where to put snapshot ?
|
||||||
File tempDir = TempFileProvider.getLongLifeTempDir("transfer");
|
File tempDir = TempFileProvider.getLongLifeTempDir("transfer");
|
||||||
snapshotFile = TempFileProvider.createTempFile(prefix, suffix, tempDir);
|
snapshotFile = TempFileProvider.createTempFile(prefix, suffix, tempDir);
|
||||||
|
reqFile = TempFileProvider.createTempFile("TRX-REQ", suffix, tempDir);
|
||||||
|
FileOutputStream reqOutput = new FileOutputStream(reqFile);
|
||||||
|
|
||||||
FileWriter snapshotWriter = new FileWriter(snapshotFile);
|
FileWriter snapshotWriter = new FileWriter(snapshotFile);
|
||||||
|
|
||||||
@@ -565,7 +572,7 @@ public class TransferServiceImpl implements TransferService
|
|||||||
header.setRepositoryId(descriptor.getId());
|
header.setRepositoryId(descriptor.getId());
|
||||||
header.setCreatedDate(new Date());
|
header.setCreatedDate(new Date());
|
||||||
header.setNodeCount(nodes.size());
|
header.setNodeCount(nodes.size());
|
||||||
header.setComplete(definition.isComplete());
|
header.setSync(definition.isSync());
|
||||||
formatter.startTransferManifest(snapshotWriter);
|
formatter.startTransferManifest(snapshotWriter);
|
||||||
formatter.writeTransferManifestHeader(header);
|
formatter.writeTransferManifestHeader(header);
|
||||||
for(NodeRef nodeRef : nodes)
|
for(NodeRef nodeRef : nodes)
|
||||||
@@ -612,13 +619,42 @@ public class TransferServiceImpl implements TransferService
|
|||||||
checkCancel(transferId);
|
checkCancel(transferId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* send Manifest
|
* send Manifest, get the requsite back.
|
||||||
*/
|
*/
|
||||||
eventProcessor.sendSnapshot(1,1);
|
eventProcessor.sendSnapshot(1,1);
|
||||||
transmitter.sendManifest(transfer, snapshotFile);
|
transmitter.sendManifest(transfer, snapshotFile, reqOutput);
|
||||||
|
|
||||||
|
if(logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("requsite file written to local filesystem");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
outputFile(reqFile);
|
||||||
|
}
|
||||||
|
catch (IOException error)
|
||||||
|
{
|
||||||
|
// This is debug code - so an exception thrown while debugging
|
||||||
|
logger.debug("error while outputting snapshotFile");
|
||||||
|
error.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
logger.debug("manifest sent");
|
logger.debug("manifest sent");
|
||||||
|
|
||||||
|
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
|
||||||
|
SAXParser parser;
|
||||||
|
parser = saxParserFactory.newSAXParser();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the requsite file to generate the delta list
|
||||||
|
*/
|
||||||
|
DeltaListRequsiteProcessor reqProcessor = new DeltaListRequsiteProcessor();
|
||||||
|
XMLTransferRequsiteReader reqReader = new XMLTransferRequsiteReader(reqProcessor);
|
||||||
|
parser.parse(reqFile, reqReader);
|
||||||
|
|
||||||
|
final DeltaList deltaList = reqProcessor.getDeltaList();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the manifest file and transfer chunks over
|
* Parse the manifest file and transfer chunks over
|
||||||
*
|
*
|
||||||
@@ -657,9 +693,25 @@ public class TransferServiceImpl implements TransferService
|
|||||||
{
|
{
|
||||||
checkCancel(transfer.getTransferId());
|
checkCancel(transfer.getTransferId());
|
||||||
logger.debug("add content to chunker");
|
logger.debug("add content to chunker");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check with the deltaList whether we need to send the content item
|
||||||
|
*/
|
||||||
|
if(deltaList != null)
|
||||||
|
{
|
||||||
|
if(deltaList.getRequiredURLs().contains(d.getContentUrl()))
|
||||||
|
{
|
||||||
|
logger.debug("content is required :" + d.getContentUrl());
|
||||||
chunker.addContent(d);
|
chunker.addContent(d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No delta list - so send all content items
|
||||||
|
chunker.addContent(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void processTransferManifiestHeader(TransferManifestHeader header){/* NO-OP */ }
|
public void processTransferManifiestHeader(TransferManifestHeader header){/* NO-OP */ }
|
||||||
public void startTransferManifest(){ /* NO-OP */ }
|
public void startTransferManifest(){ /* NO-OP */ }
|
||||||
@@ -672,13 +724,11 @@ public class TransferServiceImpl implements TransferService
|
|||||||
/**
|
/**
|
||||||
* Step 3: wire up the manifest reader to a manifest processor
|
* Step 3: wire up the manifest reader to a manifest processor
|
||||||
*/
|
*/
|
||||||
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
|
|
||||||
SAXParser parser;
|
|
||||||
parser = saxParserFactory.newSAXParser();
|
|
||||||
XMLTransferManifestReader reader = new XMLTransferManifestReader(processor);
|
XMLTransferManifestReader reader = new XMLTransferManifestReader(processor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Step 4: start the magic Give the manifest file to the manifest reader
|
* Step 4: start the magic - Give the manifest file to the manifest reader
|
||||||
*/
|
*/
|
||||||
parser.parse(snapshotFile, reader);
|
parser.parse(snapshotFile, reader);
|
||||||
chunker.flush();
|
chunker.flush();
|
||||||
@@ -821,6 +871,13 @@ public class TransferServiceImpl implements TransferService
|
|||||||
snapshotFile.delete();
|
snapshotFile.delete();
|
||||||
}
|
}
|
||||||
logger.debug("snapshot file deleted");
|
logger.debug("snapshot file deleted");
|
||||||
|
|
||||||
|
if(reqFile != null)
|
||||||
|
{
|
||||||
|
reqFile.delete();
|
||||||
|
}
|
||||||
|
logger.debug("req file deleted");
|
||||||
|
|
||||||
}
|
}
|
||||||
} // end of transferImpl
|
} // end of transferImpl
|
||||||
|
|
||||||
|
@@ -724,6 +724,45 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
|
|||||||
endTransaction();
|
endTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
startNewTransaction();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transfer our node again - so this is an update
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
TransferDefinition definition = new TransferDefinition();
|
||||||
|
Set<NodeRef>nodes = new HashSet<NodeRef>();
|
||||||
|
nodes.add(contentNodeRef);
|
||||||
|
definition.setNodes(nodes);
|
||||||
|
transferService.transfer(targetName, definition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
endTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Now transfer nothing - content items do not need to be transferred since its alrady on
|
||||||
|
* the destination.
|
||||||
|
*/
|
||||||
|
startNewTransaction();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TransferDefinition definition = new TransferDefinition();
|
||||||
|
Set<NodeRef>nodes = new HashSet<NodeRef>();
|
||||||
|
nodes.add(contentNodeRef);
|
||||||
|
definition.setNodes(nodes);
|
||||||
|
transferService.transfer(targetName, definition);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
endTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Negative test transfer nothing
|
* Negative test transfer nothing
|
||||||
*/
|
*/
|
||||||
@@ -1865,19 +1904,29 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
|
|||||||
*
|
*
|
||||||
* A1
|
* A1
|
||||||
* | | |
|
* | | |
|
||||||
* A2 A3 (Content) B6
|
* A2 A3 (Content Node) B6
|
||||||
* |
|
* |
|
||||||
* A4 A5 B7 (content)
|
* A4 A5 B7 (Content Node)
|
||||||
*
|
*
|
||||||
* Test steps -
|
* Test steps -
|
||||||
* 1 add A1
|
* 1 add A1
|
||||||
|
* transfer(sync)
|
||||||
* 2 add A2, A3, A4, A5
|
* 2 add A2, A3, A4, A5
|
||||||
* 3 remove A2 (A4 and A5 should cascade delete on source)
|
* transfer(sync)
|
||||||
|
* 3 remove A2
|
||||||
|
* transfer(sync) A4 and A5 should cascade delete on source
|
||||||
* 4 remove A3
|
* 4 remove A3
|
||||||
* 5 add back A3
|
* transfer(sync)
|
||||||
|
* 5 add back A3 - new node ref
|
||||||
|
* transfer(sync)
|
||||||
* 6 add A2, A4, A5
|
* 6 add A2, A4, A5
|
||||||
* 7 add B6 and B7 directly to target (so not transferred) transfer again.
|
* transfer(sync)
|
||||||
*
|
* 7 add B6 and B7 directly to target (so not transferred)
|
||||||
|
* transfer again, B6 and B7 should not be removed.
|
||||||
|
* 8 remove A2 (A2, A5, B7) should go. TODO is it correct that B7 goes?
|
||||||
|
* transfer
|
||||||
|
* restore node A2
|
||||||
|
* transfer
|
||||||
*/
|
*/
|
||||||
public void testTransferSyncNodes() throws Exception
|
public void testTransferSyncNodes() throws Exception
|
||||||
{
|
{
|
||||||
@@ -2011,7 +2060,7 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
|
|||||||
Set<NodeRef>nodes = new HashSet<NodeRef>();
|
Set<NodeRef>nodes = new HashSet<NodeRef>();
|
||||||
nodes.add(A1NodeRef);
|
nodes.add(A1NodeRef);
|
||||||
definition.setNodes(nodes);
|
definition.setNodes(nodes);
|
||||||
definition.setComplete(true);
|
definition.setSync(true);
|
||||||
transferService.transfer(targetName, definition);
|
transferService.transfer(targetName, definition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2056,7 +2105,7 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
|
|||||||
nodes.add(A4NodeRef);
|
nodes.add(A4NodeRef);
|
||||||
nodes.add(A5NodeRef);
|
nodes.add(A5NodeRef);
|
||||||
definition.setNodes(nodes);
|
definition.setNodes(nodes);
|
||||||
definition.setComplete(true);
|
definition.setSync(true);
|
||||||
transferService.transfer(targetName, definition);
|
transferService.transfer(targetName, definition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2113,7 +2162,7 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
|
|||||||
//nodes.add(A4NodeRef);
|
//nodes.add(A4NodeRef);
|
||||||
//nodes.add(A5NodeRef);
|
//nodes.add(A5NodeRef);
|
||||||
definition.setNodes(nodes);
|
definition.setNodes(nodes);
|
||||||
definition.setComplete(true);
|
definition.setSync(true);
|
||||||
transferService.transfer(targetName, definition);
|
transferService.transfer(targetName, definition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2169,7 +2218,7 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
|
|||||||
//nodes.add(A4NodeRef);
|
//nodes.add(A4NodeRef);
|
||||||
//nodes.add(A5NodeRef);
|
//nodes.add(A5NodeRef);
|
||||||
definition.setNodes(nodes);
|
definition.setNodes(nodes);
|
||||||
definition.setComplete(true);
|
definition.setSync(true);
|
||||||
transferService.transfer(targetName, definition);
|
transferService.transfer(targetName, definition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2232,7 +2281,7 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
|
|||||||
//nodes.add(A4NodeRef);
|
//nodes.add(A4NodeRef);
|
||||||
//nodes.add(A5NodeRef);
|
//nodes.add(A5NodeRef);
|
||||||
definition.setNodes(nodes);
|
definition.setNodes(nodes);
|
||||||
definition.setComplete(true);
|
definition.setSync(true);
|
||||||
transferService.transfer(targetName, definition);
|
transferService.transfer(targetName, definition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2319,7 +2368,7 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
|
|||||||
nodes.add(A4NodeRef);
|
nodes.add(A4NodeRef);
|
||||||
nodes.add(A5NodeRef);
|
nodes.add(A5NodeRef);
|
||||||
definition.setNodes(nodes);
|
definition.setNodes(nodes);
|
||||||
definition.setComplete(true);
|
definition.setSync(true);
|
||||||
transferService.transfer(targetName, definition);
|
transferService.transfer(targetName, definition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2397,7 +2446,7 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
|
|||||||
nodes.add(A4NodeRef);
|
nodes.add(A4NodeRef);
|
||||||
nodes.add(A5NodeRef);
|
nodes.add(A5NodeRef);
|
||||||
definition.setNodes(nodes);
|
definition.setNodes(nodes);
|
||||||
definition.setComplete(true);
|
definition.setSync(true);
|
||||||
transferService.transfer(targetName, definition);
|
transferService.transfer(targetName, definition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2425,6 +2474,123 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
|
|||||||
{
|
{
|
||||||
endTransaction();
|
endTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO BUGBUG - test fails
|
||||||
|
// /** Step 8
|
||||||
|
// * remove A2 (A2, A5, B7) should go. TODO is it correct that B7 goes?
|
||||||
|
// * transfer
|
||||||
|
// * restore node A2
|
||||||
|
// * transfer
|
||||||
|
// */
|
||||||
|
// /**
|
||||||
|
// * Step 3 - remove folder node A2
|
||||||
|
// */
|
||||||
|
// startNewTransaction();
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// nodeService.deleteNode(A2NodeRef);
|
||||||
|
// }
|
||||||
|
// finally
|
||||||
|
// {
|
||||||
|
// endTransaction();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// startNewTransaction();
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// /**
|
||||||
|
// * Transfer Node A 1-5
|
||||||
|
// */
|
||||||
|
// {
|
||||||
|
// TransferDefinition definition = new TransferDefinition();
|
||||||
|
// Set<NodeRef>nodes = new HashSet<NodeRef>();
|
||||||
|
// nodes.add(A1NodeRef);
|
||||||
|
// //nodes.add(A2NodeRef);
|
||||||
|
// nodes.add(A3NodeRef);
|
||||||
|
// //nodes.add(A4NodeRef);
|
||||||
|
// //nodes.add(A5NodeRef);
|
||||||
|
// definition.setNodes(nodes);
|
||||||
|
// definition.setSync(true);
|
||||||
|
// transferService.transfer(targetName, definition);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// finally
|
||||||
|
// {
|
||||||
|
// endTransaction();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// startNewTransaction();
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// // Now validate that the target node exists and has similar properties to the source
|
||||||
|
// destNodeRef = testNodeFactory.getMappedNodeRef(A1NodeRef);
|
||||||
|
// assertFalse("unit test stuffed up - comparing with self", destNodeRef.equals(transferMe.getNodeRef()));
|
||||||
|
// assertTrue("dest node ref A1 does not exist", nodeService.exists(testNodeFactory.getMappedNodeRef(A1NodeRef)));
|
||||||
|
// assertFalse("dest node ref A2 has not been deleted", nodeService.exists(testNodeFactory.getMappedNodeRef(A2NodeRef)));
|
||||||
|
// assertTrue("dest node ref A3 does not exist", nodeService.exists(testNodeFactory.getMappedNodeRef(A3NodeRef)));
|
||||||
|
// assertFalse("dest node ref A4 has not been deleted", nodeService.exists(testNodeFactory.getMappedNodeRef(A4NodeRef)));
|
||||||
|
// assertFalse("dest node ref A5 has not been deleted", nodeService.exists(testNodeFactory.getMappedNodeRef(A5NodeRef)));
|
||||||
|
// // assertFalse("dest node B6 has not been deleted", nodeService.exists(B6NodeRef));
|
||||||
|
// // assertTrue("dest node B7 does not exist", nodeService.exists(B7NodeRef));
|
||||||
|
// }
|
||||||
|
// finally
|
||||||
|
// {
|
||||||
|
// endTransaction();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// startNewTransaction();
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// NodeRef archivedNode = new NodeRef(StoreRef.STORE_REF_ARCHIVE_SPACESSTORE, A2NodeRef.getId());
|
||||||
|
// nodeService.restoreNode(archivedNode, A1NodeRef, ContentModel.ASSOC_CONTAINS, QName.createQName("A2"));
|
||||||
|
// }
|
||||||
|
// finally
|
||||||
|
// {
|
||||||
|
// endTransaction();
|
||||||
|
// }
|
||||||
|
// startNewTransaction();
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// /**
|
||||||
|
// * Transfer Node A 1-5, B6 and B7 should remain untouched.
|
||||||
|
// */
|
||||||
|
// {
|
||||||
|
// TransferDefinition definition = new TransferDefinition();
|
||||||
|
// Set<NodeRef>nodes = new HashSet<NodeRef>();
|
||||||
|
// nodes.add(A1NodeRef);
|
||||||
|
// nodes.add(A2NodeRef);
|
||||||
|
// nodes.add(A3NodeRef);
|
||||||
|
// nodes.add(A4NodeRef);
|
||||||
|
// nodes.add(A5NodeRef);
|
||||||
|
// definition.setNodes(nodes);
|
||||||
|
// definition.setSync(true);
|
||||||
|
// transferService.transfer(targetName, definition);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// finally
|
||||||
|
// {
|
||||||
|
// endTransaction();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// startNewTransaction();
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// // Now validate that the target node exists and has similar properties to the source
|
||||||
|
// destNodeRef = testNodeFactory.getMappedNodeRef(A1NodeRef);
|
||||||
|
// assertFalse("unit test stuffed up - comparing with self", destNodeRef.equals(transferMe.getNodeRef()));
|
||||||
|
// assertTrue("dest node ref A1 does not exist", nodeService.exists(testNodeFactory.getMappedNodeRef(A1NodeRef)));
|
||||||
|
// assertTrue("dest node ref A2 does not exist", nodeService.exists(testNodeFactory.getMappedNodeRef(A2NodeRef)));
|
||||||
|
// assertTrue("dest node ref A3 does not exist", nodeService.exists(testNodeFactory.getMappedNodeRef(A3NodeRef)));
|
||||||
|
// assertTrue("dest node ref A4 does not exist", nodeService.exists(testNodeFactory.getMappedNodeRef(A4NodeRef)));
|
||||||
|
// assertTrue("dest node ref A5 does not exist", nodeService.exists(testNodeFactory.getMappedNodeRef(A5NodeRef)));
|
||||||
|
// // assertFalse("dest node B6 has not been deleted", nodeService.exists(B6NodeRef));
|
||||||
|
// // assertTrue("dest node B7 does not exist", nodeService.exists(B7NodeRef));
|
||||||
|
// }
|
||||||
|
// finally
|
||||||
|
// {
|
||||||
|
// endTransaction();
|
||||||
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private TransferTarget createTransferTarget(String name)
|
private TransferTarget createTransferTarget(String name)
|
||||||
@@ -2433,7 +2599,7 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
|
|||||||
String description = "description";
|
String description = "description";
|
||||||
String endpointProtocol = "http";
|
String endpointProtocol = "http";
|
||||||
String endpointHost = "MARKR02";
|
String endpointHost = "MARKR02";
|
||||||
int endpointPort = 6080;
|
int endpointPort = 7080;
|
||||||
String endpointPath = "/alfresco/service/api/transfer";
|
String endpointPath = "/alfresco/service/api/transfer";
|
||||||
String username = "admin";
|
String username = "admin";
|
||||||
char[] password = "admin".toCharArray();
|
char[] password = "admin".toCharArray();
|
||||||
@@ -2444,5 +2610,4 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
|
|||||||
TransferTarget target = transferService.createAndSaveTransferTarget(name, title, description, endpointProtocol, endpointHost, endpointPort, endpointPath, username, password);
|
TransferTarget target = transferService.createAndSaveTransferTarget(name, title, description, endpointProtocol, endpointHost, endpointPort, endpointPath, username, password);
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
package org.alfresco.repo.transfer;
|
package org.alfresco.repo.transfer;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.alfresco.service.cmr.repository.ContentData;
|
import org.alfresco.service.cmr.repository.ContentData;
|
||||||
@@ -53,10 +54,12 @@ public interface TransferTransmitter
|
|||||||
/**
|
/**
|
||||||
* @param manifest, the transfer manifest file
|
* @param manifest, the transfer manifest file
|
||||||
* @param transfer the transfer object returned by an earlier call to begin
|
* @param transfer the transfer object returned by an earlier call to begin
|
||||||
* @return the delta list.
|
* @param results - where to write the results, probably a temporary file the output steam should be
|
||||||
|
* open and will be closed before the method returns.
|
||||||
|
* @return the transfer requisite.
|
||||||
* @throws TransferException
|
* @throws TransferException
|
||||||
*/
|
*/
|
||||||
DeltaList sendManifest(Transfer transfer, File manifest) throws TransferException;
|
void sendManifest(Transfer transfer, File manifest, OutputStream results) throws TransferException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send the content of the specified urls
|
* Send the content of the specified urls
|
||||||
|
@@ -21,7 +21,9 @@ package org.alfresco.repo.transfer;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||||
@@ -32,6 +34,8 @@ import org.alfresco.service.cmr.transfer.TransferProgress;
|
|||||||
import org.alfresco.service.cmr.transfer.TransferReceiver;
|
import org.alfresco.service.cmr.transfer.TransferReceiver;
|
||||||
import org.alfresco.service.cmr.transfer.TransferTarget;
|
import org.alfresco.service.cmr.transfer.TransferTarget;
|
||||||
import org.alfresco.service.transaction.TransactionService;
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class delegates transfer service to the transfer receiver without
|
* This class delegates transfer service to the transfer receiver without
|
||||||
@@ -44,6 +48,8 @@ import org.alfresco.service.transaction.TransactionService;
|
|||||||
*/
|
*/
|
||||||
public class UnitTestInProcessTransmitterImpl implements TransferTransmitter
|
public class UnitTestInProcessTransmitterImpl implements TransferTransmitter
|
||||||
{
|
{
|
||||||
|
private static final Log log = LogFactory.getLog(UnitTestInProcessTransmitterImpl.class);
|
||||||
|
|
||||||
private TransferReceiver receiver;
|
private TransferReceiver receiver;
|
||||||
|
|
||||||
private ContentService contentService;
|
private ContentService contentService;
|
||||||
@@ -118,20 +124,34 @@ public class UnitTestInProcessTransmitterImpl implements TransferTransmitter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DeltaList sendManifest(Transfer transfer, File manifest) throws TransferException
|
public void sendManifest(Transfer transfer, File manifest, OutputStream result) throws TransferException
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
String transferId = transfer.getTransferId();
|
String transferId = transfer.getTransferId();
|
||||||
FileInputStream fs = new FileInputStream(manifest);
|
FileInputStream fs = new FileInputStream(manifest);
|
||||||
receiver.saveSnapshot(transferId, fs);
|
receiver.saveSnapshot(transferId, fs);
|
||||||
|
|
||||||
|
// Now get the requsite
|
||||||
|
try
|
||||||
|
{
|
||||||
|
receiver.generateRequsite(transferId, result);
|
||||||
|
result.close();
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
catch(IOException ie)
|
||||||
|
{
|
||||||
|
log.error("Error in unit test code: should not get this", ie);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (FileNotFoundException error)
|
catch (FileNotFoundException error)
|
||||||
{
|
{
|
||||||
throw new TransferException("test error", error);
|
throw new TransferException("test error", error);
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void verifyTarget(TransferTarget target) throws TransferException
|
public void verifyTarget(TransferTarget target) throws TransferException
|
||||||
@@ -160,5 +180,4 @@ public class UnitTestInProcessTransmitterImpl implements TransferTransmitter
|
|||||||
return contentService;
|
return contentService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,7 @@ public interface ManifestModel extends TransferModel
|
|||||||
static final String LOCALNAME_TRANSFER_HEADER = "transferManifestHeader";
|
static final String LOCALNAME_TRANSFER_HEADER = "transferManifestHeader";
|
||||||
static final String LOCALNAME_HEADER_CREATED_DATE = "createdDate";
|
static final String LOCALNAME_HEADER_CREATED_DATE = "createdDate";
|
||||||
static final String LOCALNAME_HEADER_NODE_COUNT = "nodeCount";
|
static final String LOCALNAME_HEADER_NODE_COUNT = "nodeCount";
|
||||||
static final String LOCALNAME_HEADER_COMPLETE = "complete";
|
static final String LOCALNAME_HEADER_SYNC = "sync";
|
||||||
static final String LOCALNAME_HEADER_REPOSITORY_ID = "repositoryId";
|
static final String LOCALNAME_HEADER_REPOSITORY_ID = "repositoryId";
|
||||||
static final String LOCALNAME_ELEMENT_NODES = "nodes";
|
static final String LOCALNAME_ELEMENT_NODES = "nodes";
|
||||||
static final String LOCALNAME_ELEMENT_NODE = "node";
|
static final String LOCALNAME_ELEMENT_NODE = "node";
|
||||||
|
@@ -31,7 +31,7 @@ public class TransferManifestHeader
|
|||||||
private Date createdDate;
|
private Date createdDate;
|
||||||
private int nodeCount;
|
private int nodeCount;
|
||||||
private String repositoryId;
|
private String repositoryId;
|
||||||
private boolean isComplete;
|
private boolean isSync;
|
||||||
|
|
||||||
public void setCreatedDate(Date createDate)
|
public void setCreatedDate(Date createDate)
|
||||||
{
|
{
|
||||||
@@ -77,14 +77,14 @@ public class TransferManifestHeader
|
|||||||
return repositoryId;
|
return repositoryId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setComplete(boolean isComplete)
|
public void setSync(boolean isSync)
|
||||||
{
|
{
|
||||||
this.isComplete = isComplete;
|
this.isSync = isSync;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isComplete()
|
public boolean isSync()
|
||||||
{
|
{
|
||||||
return isComplete;
|
return isSync;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -387,10 +387,10 @@ public class XMLTransferManifestReader extends DefaultHandler implements Content
|
|||||||
header.setNodeCount(Integer.parseInt(buffer.toString()));
|
header.setNodeCount(Integer.parseInt(buffer.toString()));
|
||||||
buffer = null;
|
buffer = null;
|
||||||
}
|
}
|
||||||
else if(elementName.equals(ManifestModel.LOCALNAME_HEADER_COMPLETE))
|
else if(elementName.equals(ManifestModel.LOCALNAME_HEADER_SYNC))
|
||||||
{
|
{
|
||||||
TransferManifestHeader header = (TransferManifestHeader)props.get("header");
|
TransferManifestHeader header = (TransferManifestHeader)props.get("header");
|
||||||
header.setComplete(true);
|
header.setSync(true);
|
||||||
}
|
}
|
||||||
else if(elementName.equals(ManifestModel.LOCALNAME_HEADER_REPOSITORY_ID))
|
else if(elementName.equals(ManifestModel.LOCALNAME_HEADER_REPOSITORY_ID))
|
||||||
{
|
{
|
||||||
|
@@ -158,15 +158,15 @@ public class XMLTransferManifestWriter implements TransferManifestWriter
|
|||||||
+ ManifestModel.LOCALNAME_HEADER_REPOSITORY_ID);
|
+ ManifestModel.LOCALNAME_HEADER_REPOSITORY_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(header.isComplete())
|
if(header.isSync())
|
||||||
{
|
{
|
||||||
// Is this a complete transfer
|
// Is this a complete transfer
|
||||||
writer.startElement(TransferModel.TRANSFER_MODEL_1_0_URI,
|
writer.startElement(TransferModel.TRANSFER_MODEL_1_0_URI,
|
||||||
ManifestModel.LOCALNAME_HEADER_COMPLETE, PREFIX + ":"
|
ManifestModel.LOCALNAME_HEADER_SYNC, PREFIX + ":"
|
||||||
+ ManifestModel.LOCALNAME_HEADER_COMPLETE, EMPTY_ATTRIBUTES);
|
+ ManifestModel.LOCALNAME_HEADER_SYNC, EMPTY_ATTRIBUTES);
|
||||||
writer.endElement(TransferModel.TRANSFER_MODEL_1_0_URI,
|
writer.endElement(TransferModel.TRANSFER_MODEL_1_0_URI,
|
||||||
ManifestModel.LOCALNAME_HEADER_COMPLETE, PREFIX + ":"
|
ManifestModel.LOCALNAME_HEADER_SYNC, PREFIX + ":"
|
||||||
+ ManifestModel.LOCALNAME_HEADER_COMPLETE);
|
+ ManifestModel.LOCALNAME_HEADER_SYNC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.transfer.requisite;
|
||||||
|
|
||||||
|
import org.alfresco.repo.transfer.DeltaList;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A processor of the XML Transfer Requsite file to populate a DeltaList object
|
||||||
|
*
|
||||||
|
* The requsite is parsed once and the delta list is available from getDeltaList at the end.
|
||||||
|
*
|
||||||
|
* @author mrogers
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class DeltaListRequsiteProcessor implements TransferRequsiteProcessor
|
||||||
|
{
|
||||||
|
|
||||||
|
DeltaList deltaList = null;
|
||||||
|
|
||||||
|
public void missingContent(NodeRef node, QName qname, String name)
|
||||||
|
{
|
||||||
|
deltaList.getRequiredURLs().add(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startTransferRequsite()
|
||||||
|
{
|
||||||
|
deltaList = new DeltaList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endTransferRequsite()
|
||||||
|
{
|
||||||
|
// No op
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the delta list
|
||||||
|
* @return the delta list or null if the XML provided does not contain the data.
|
||||||
|
*/
|
||||||
|
public DeltaList getDeltaList()
|
||||||
|
{
|
||||||
|
return deltaList;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.transfer.requisite;
|
||||||
|
|
||||||
|
import org.alfresco.repo.transfer.TransferModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The transfer model - extended for XML Manifest Model
|
||||||
|
*/
|
||||||
|
public interface RequsiteModel extends TransferModel
|
||||||
|
{
|
||||||
|
static final String LOCALNAME_TRANSFER_REQUSITE = "transferRequsite";
|
||||||
|
|
||||||
|
static final String LOCALNAME_ELEMENT_NODES = "nodes";
|
||||||
|
static final String LOCALNAME_ELEMENT_NODE = "node";
|
||||||
|
static final String LOCALNAME_ELEMENT_CONTENT = "requiredContent";
|
||||||
|
static final String LOCALNAME_ELEMENT_GROUPS = "groups";
|
||||||
|
static final String LOCALNAME_ELEMENT_GROUP = "group";
|
||||||
|
static final String LOCALNAME_ELEMENT_USERS = "users";
|
||||||
|
static final String LOCALNAME_ELEMENT_USER = "user";
|
||||||
|
|
||||||
|
|
||||||
|
// Manifest file prefix
|
||||||
|
static final String REQUSITE_PREFIX = "xferreq";
|
||||||
|
}
|
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.transfer.requisite;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processor for transfer requsite file
|
||||||
|
* @author mrogers
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface TransferRequsiteProcessor
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Called at the start of a transfer requsite
|
||||||
|
*/
|
||||||
|
public void startTransferRequsite();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called at the end of a transfer requsite
|
||||||
|
*/
|
||||||
|
public void endTransferRequsite();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a missing content property is found
|
||||||
|
* @param node
|
||||||
|
* @param qname
|
||||||
|
* @param name
|
||||||
|
*/
|
||||||
|
public void missingContent(NodeRef node, QName qname, String name);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.transfer.requisite;
|
||||||
|
|
||||||
|
import java.io.Writer;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transfer Requsite Writer
|
||||||
|
*
|
||||||
|
* This class formats the transfer requsite and prints it to the specified writer
|
||||||
|
*
|
||||||
|
* It is a statefull object and writes one requsite at a time.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface TransferRequsiteWriter
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param writer
|
||||||
|
*/
|
||||||
|
void startTransferRequsite() ;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void endTransferRequsite() ;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void missingContent(NodeRef nodeRef, QName qName, String name);
|
||||||
|
}
|
@@ -0,0 +1,247 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.transfer.requisite;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.namespace.NamespaceException;
|
||||||
|
import org.alfresco.service.namespace.NamespacePrefixResolver;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.xml.sax.Attributes;
|
||||||
|
import org.xml.sax.ContentHandler;
|
||||||
|
import org.xml.sax.Locator;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
import org.xml.sax.helpers.DefaultHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SAX XML Content Handler to read a transfer manifest XML Stream and
|
||||||
|
* delegate processing of the manifest to the specified TransferRequsiteProcessor
|
||||||
|
*
|
||||||
|
* @author Mark Rogers
|
||||||
|
*/
|
||||||
|
public class XMLTransferRequsiteReader extends DefaultHandler implements ContentHandler, NamespacePrefixResolver
|
||||||
|
{
|
||||||
|
private TransferRequsiteProcessor processor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* These are the namespaces used within the document - there may be a different mapping to
|
||||||
|
* the namespaces of the Data Dictionary.
|
||||||
|
*/
|
||||||
|
LinkedList<HashMap<String, String>> namespaces = new LinkedList<HashMap<String, String>>();
|
||||||
|
|
||||||
|
final String TRANSFER_URI = RequsiteModel.TRANSFER_MODEL_1_0_URI;
|
||||||
|
final String XMLNS_URI = "http://www.w3.org/XML/1998/namespace";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Current State of the parser
|
||||||
|
*/
|
||||||
|
private StringBuffer buffer;
|
||||||
|
private Map<String, Object>props = new HashMap<String, Object>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param processor
|
||||||
|
*/
|
||||||
|
public XMLTransferRequsiteReader(TransferRequsiteProcessor processor)
|
||||||
|
{
|
||||||
|
this.processor = processor;
|
||||||
|
|
||||||
|
// prefix to uri map
|
||||||
|
HashMap<String, String> namespace = new HashMap<String, String>();
|
||||||
|
namespace.put("xmlns", XMLNS_URI);
|
||||||
|
namespaces.add(namespace);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startPrefixMapping(String prefix, String uri) throws SAXException
|
||||||
|
{
|
||||||
|
HashMap<String, String> namespace = namespaces.get(0);
|
||||||
|
// prefix is key, URI is value
|
||||||
|
namespace.put(prefix, uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endPrefixMapping(String prefix) throws SAXException
|
||||||
|
{
|
||||||
|
HashMap<String, String> namespace = namespaces.get(0);
|
||||||
|
// prefix is key, URI is value
|
||||||
|
namespace.remove(prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Namespace Prefix Resolver implementation below
|
||||||
|
|
||||||
|
/**
|
||||||
|
* lookup the prefix for a URI e.g. TRANSFER_URI for xfer
|
||||||
|
*/
|
||||||
|
public String getNamespaceURI(String prefix) throws NamespaceException
|
||||||
|
{
|
||||||
|
for(HashMap<String, String> namespace : namespaces)
|
||||||
|
{
|
||||||
|
String uri = namespace.get(prefix);
|
||||||
|
if(uri != null)
|
||||||
|
{
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param uri
|
||||||
|
* @return the prefix
|
||||||
|
*/
|
||||||
|
public Collection<String> getPrefixes(String namespaceURI) throws NamespaceException
|
||||||
|
{
|
||||||
|
Collection<String> prefixes = new HashSet<String>();
|
||||||
|
|
||||||
|
for(HashMap<String, String> namespace : namespaces)
|
||||||
|
{
|
||||||
|
for(Entry<String, String> entry : namespace.entrySet())
|
||||||
|
{
|
||||||
|
if (namespaceURI.equals(entry.getValue()))
|
||||||
|
{
|
||||||
|
prefixes.add(entry.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return prefixes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<String> getPrefixes()
|
||||||
|
{
|
||||||
|
Collection<String> prefixes = new HashSet<String>();
|
||||||
|
|
||||||
|
for(HashMap<String, String> namespace : namespaces)
|
||||||
|
{
|
||||||
|
prefixes.addAll(namespace.keySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
return prefixes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<String> getURIs()
|
||||||
|
{
|
||||||
|
Collection<String> uris = new HashSet<String>();
|
||||||
|
|
||||||
|
for(HashMap<String, String> namespace : namespaces)
|
||||||
|
{
|
||||||
|
uris.addAll(namespace.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
return uris;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void startDocument() throws SAXException
|
||||||
|
{
|
||||||
|
processor.startTransferRequsite();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endDocument() throws SAXException
|
||||||
|
{
|
||||||
|
processor.endTransferRequsite();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start Element
|
||||||
|
*/
|
||||||
|
public void startElement(String uri, String localName, String prefixName, Attributes atts)
|
||||||
|
throws SAXException
|
||||||
|
{
|
||||||
|
QName elementQName = QName.resolveToQName(this, prefixName);
|
||||||
|
|
||||||
|
HashMap<String, String> namespace = new HashMap<String, String>();
|
||||||
|
namespaces.addFirst(namespace);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look for any namespace attributes
|
||||||
|
*/
|
||||||
|
for(int i = 0; i < atts.getLength(); i++)
|
||||||
|
{
|
||||||
|
QName attributeQName = QName.resolveToQName(this, atts.getQName(i));
|
||||||
|
if(attributeQName.getNamespaceURI().equals(XMLNS_URI))
|
||||||
|
{
|
||||||
|
namespace.put(attributeQName.getLocalName(), atts.getValue(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(elementQName == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(elementQName.getNamespaceURI().equals(TRANSFER_URI));
|
||||||
|
{
|
||||||
|
// This is one of the transfer manifest elements
|
||||||
|
String elementName = elementQName.getLocalName();
|
||||||
|
|
||||||
|
// Simple and stupid parser for now
|
||||||
|
if(elementName.equals(RequsiteModel.LOCALNAME_TRANSFER_REQUSITE))
|
||||||
|
{
|
||||||
|
// Good we got this
|
||||||
|
}
|
||||||
|
else if(elementName.equals(RequsiteModel.LOCALNAME_ELEMENT_CONTENT))
|
||||||
|
{
|
||||||
|
NodeRef nodeRef = new NodeRef(atts.getValue("", "nodeRef"));
|
||||||
|
QName qname = QName.createQName(atts.getValue("", "qname"));
|
||||||
|
String name = atts.getValue("", "name");
|
||||||
|
|
||||||
|
processor.missingContent(nodeRef, qname, name);
|
||||||
|
}
|
||||||
|
} // if transfer URI
|
||||||
|
} // startElement
|
||||||
|
|
||||||
|
/**
|
||||||
|
* End Element
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void endElement(String uri, String localName, String prefixName) throws SAXException
|
||||||
|
{
|
||||||
|
namespaces.removeFirst();
|
||||||
|
|
||||||
|
} // end element
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException
|
||||||
|
{
|
||||||
|
//NO-OP
|
||||||
|
}
|
||||||
|
|
||||||
|
public void processingInstruction(String target, String data) throws SAXException
|
||||||
|
{
|
||||||
|
//NO-OP
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDocumentLocator(Locator locator)
|
||||||
|
{
|
||||||
|
//NO-OP
|
||||||
|
}
|
||||||
|
|
||||||
|
public void skippedEntity(String name) throws SAXException
|
||||||
|
{
|
||||||
|
//NO-OP
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.transfer.requisite;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import org.alfresco.repo.transfer.RepoRequsiteManifestProcessorImpl;
|
||||||
|
import org.alfresco.repo.transfer.TransferModel;
|
||||||
|
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.MLText;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.cmr.repository.Path;
|
||||||
|
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||||
|
import org.alfresco.service.cmr.repository.datatype.TypeConversionException;
|
||||||
|
import org.alfresco.service.cmr.transfer.TransferException;
|
||||||
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.dom4j.io.OutputFormat;
|
||||||
|
import org.dom4j.io.XMLWriter;
|
||||||
|
import org.springframework.extensions.surf.util.Base64;
|
||||||
|
import org.springframework.extensions.surf.util.ISO8601DateFormat;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
import org.xml.sax.helpers.AttributesImpl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the transfer requsite out in XML format to the specified writer.
|
||||||
|
*
|
||||||
|
* XMLTransferRequsiteWriter is a statefull object used for writing out a single transfer requsite
|
||||||
|
* file in XML format to the writer passed in via startTransferRequsite.
|
||||||
|
*
|
||||||
|
* @author Mark Rogers
|
||||||
|
*/
|
||||||
|
public class XMLTransferRequsiteWriter implements TransferRequsiteWriter
|
||||||
|
{
|
||||||
|
private static final Log log = LogFactory.getLog(XMLTransferRequsiteWriter.class);
|
||||||
|
|
||||||
|
public XMLTransferRequsiteWriter(Writer out)
|
||||||
|
{
|
||||||
|
OutputFormat format = OutputFormat.createPrettyPrint();
|
||||||
|
format.setNewLineAfterDeclaration(false);
|
||||||
|
format.setIndentSize(3);
|
||||||
|
format.setEncoding("UTF-8");
|
||||||
|
|
||||||
|
this.writer = new XMLWriter(out, format);
|
||||||
|
}
|
||||||
|
|
||||||
|
private XMLWriter writer;
|
||||||
|
|
||||||
|
final AttributesImpl EMPTY_ATTRIBUTES = new AttributesImpl();
|
||||||
|
|
||||||
|
final String PREFIX = RequsiteModel.REQUSITE_PREFIX;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the transfer manifest
|
||||||
|
*/
|
||||||
|
public void startTransferRequsite()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.writer.startDocument();
|
||||||
|
|
||||||
|
this.writer.startPrefixMapping(PREFIX, TransferModel.TRANSFER_MODEL_1_0_URI);
|
||||||
|
this.writer.startPrefixMapping("cm", NamespaceService.CONTENT_MODEL_1_0_URI);
|
||||||
|
|
||||||
|
// Start Transfer Manifest // uri, name, prefix
|
||||||
|
this.writer.startElement(TransferModel.TRANSFER_MODEL_1_0_URI,
|
||||||
|
RequsiteModel.LOCALNAME_TRANSFER_REQUSITE, PREFIX + ":"
|
||||||
|
+ RequsiteModel.LOCALNAME_TRANSFER_REQUSITE, EMPTY_ATTRIBUTES);
|
||||||
|
}
|
||||||
|
catch (SAXException se)
|
||||||
|
{
|
||||||
|
log.debug("error", se);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* End the transfer manifest
|
||||||
|
*/
|
||||||
|
public void endTransferRequsite()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// End Transfer Manifest
|
||||||
|
writer.endElement(TransferModel.TRANSFER_MODEL_1_0_URI,
|
||||||
|
RequsiteModel.LOCALNAME_TRANSFER_REQUSITE, PREFIX + ":"
|
||||||
|
+ RequsiteModel.LOCALNAME_TRANSFER_REQUSITE);
|
||||||
|
writer.endPrefixMapping(PREFIX);
|
||||||
|
|
||||||
|
writer.endDocument();
|
||||||
|
}
|
||||||
|
catch (SAXException se)
|
||||||
|
{
|
||||||
|
log.debug("error", se);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void missingContent(NodeRef node, QName qname, String name)
|
||||||
|
{
|
||||||
|
log.debug("write missing content");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
AttributesImpl attributes = new AttributesImpl();
|
||||||
|
attributes.addAttribute("uri", "nodeRef", "nodeRef", "String", node.toString());
|
||||||
|
attributes.addAttribute("uri", "qname", "qname", "String", qname.toString());
|
||||||
|
attributes.addAttribute("uri", "name", "name", "String", name.toString());
|
||||||
|
|
||||||
|
// Start Missing Content
|
||||||
|
this.writer.startElement(TransferModel.TRANSFER_MODEL_1_0_URI,
|
||||||
|
RequsiteModel.LOCALNAME_ELEMENT_CONTENT, PREFIX + ":"
|
||||||
|
+ RequsiteModel.LOCALNAME_ELEMENT_CONTENT, attributes);
|
||||||
|
|
||||||
|
// Missing Content
|
||||||
|
writer.endElement(TransferModel.TRANSFER_MODEL_1_0_URI,
|
||||||
|
RequsiteModel.LOCALNAME_ELEMENT_CONTENT, PREFIX + ":"
|
||||||
|
+ RequsiteModel.LOCALNAME_ELEMENT_CONTENT);
|
||||||
|
}
|
||||||
|
catch (SAXException se)
|
||||||
|
{
|
||||||
|
log.debug("error", se);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,9 @@
|
|||||||
|
/**
|
||||||
|
* Provides the implementation of the transfer requsite which is used by the transfer service.
|
||||||
|
* <p>
|
||||||
|
* XMLTransferRequsiteWriter writes the transfer requsite. XMLTransferRequsiteReader reads the transfer requsite and calls the
|
||||||
|
* TransferRequsiteProcessor as the read progresses. These classes are designed to stream content through, processing each node at a time,
|
||||||
|
* and not hold a large data objects in memory.
|
||||||
|
* @since 3.4
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.transfer.requisite;
|
@@ -31,10 +31,11 @@ import org.alfresco.service.cmr.repository.NodeRef;
|
|||||||
*
|
*
|
||||||
* nodes Specifies which node to transfer
|
* nodes Specifies which node to transfer
|
||||||
* <p>
|
* <p>
|
||||||
* isComplete specifies whether the list of nodes is complete. If complete then the transfer
|
* isSync specifies whether the list of nodes is to be sync'ed. If sync then the transfer
|
||||||
* machinery can determine by the absence of a node that the missing node should be deleted.
|
* machinery can determine by the absence of a node or association in the transfer that the missing
|
||||||
* if the transfer is not complete (a partial transfer) then the archive node ref is required
|
* nodes should be deleted on the destination.
|
||||||
* to delete a remote node.
|
* Else with a non sync transfer then the archive node ref is required to remote a node on the destination.
|
||||||
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class TransferDefinition implements Serializable
|
public class TransferDefinition implements Serializable
|
||||||
@@ -48,7 +49,7 @@ public class TransferDefinition implements Serializable
|
|||||||
private Set<NodeRef> nodes;
|
private Set<NodeRef> nodes;
|
||||||
|
|
||||||
// is complete
|
// is complete
|
||||||
private boolean isComplete = false;
|
private boolean isSync = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set which nodes to transfer
|
* Set which nodes to transfer
|
||||||
@@ -74,23 +75,25 @@ public class TransferDefinition implements Serializable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* isComplete specifies whether the list of nodes is complete. If complete then the transfer
|
* isSync specifies whether the list of nodes is to be sync'ed. If sync then the transfer
|
||||||
* machinery can determine by the absence of a node in the transfer that the missing node should be deleted.
|
* machinery can determine by the absence of a node or association in the transfer that the missing
|
||||||
* Else with a partial transfer then the archive node ref is required to delete a remote node.
|
* nodes should be deleted on the destination.
|
||||||
|
* Else with a non sync transfer then the archive node ref is required to remote a node on the destination.
|
||||||
*/
|
*/
|
||||||
public void setComplete(boolean isComplete)
|
public void setSync(boolean isSync)
|
||||||
{
|
{
|
||||||
this.isComplete = isComplete;
|
this.isSync = isSync;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* isComplete specifies whether the list of nodes is complete. If complete then the transfer
|
* isSync specifies whether the list of nodes is to be sync'ed. If sync then the transfer
|
||||||
* machinery can determine by the absence of a node in the transfer that the missing node should be deleted.
|
* machinery can determine by the absence of a node or association in the transfer that missing
|
||||||
* Else with a partial transfer then the archive node ref is required to delete a remote node.
|
* nodes should be deleted on the destination.
|
||||||
* @return true if the transfer contains a full list of dependent nodes.
|
* Else with a non sync transfer then the archive node ref is required to remote a node on the destination.
|
||||||
|
* @return true if the transfer is in "sync" mode.
|
||||||
*/
|
*/
|
||||||
public boolean isComplete()
|
public boolean isSync()
|
||||||
{
|
{
|
||||||
return isComplete;
|
return isSync;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,7 @@ package org.alfresco.service.cmr.transfer;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
import org.alfresco.repo.transfer.TransferProgressMonitor;
|
import org.alfresco.repo.transfer.TransferProgressMonitor;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
@@ -77,8 +78,22 @@ public interface TransferReceiver
|
|||||||
*/
|
*/
|
||||||
void saveSnapshot(String transferId, InputStream snapshotStream) throws TransferException;
|
void saveSnapshot(String transferId, InputStream snapshotStream) throws TransferException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save a content item
|
||||||
|
* @param transferId
|
||||||
|
* @param contentId
|
||||||
|
* @param contentStream
|
||||||
|
* @throws TransferException
|
||||||
|
*/
|
||||||
void saveContent(String transferId, String contentId, InputStream contentStream) throws TransferException;
|
void saveContent(String transferId, String contentId, InputStream contentStream) throws TransferException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write the requsite (the bits required to support the Manifest) to the output stream.
|
||||||
|
* @param requsiteStream an open stream to receive the requisite
|
||||||
|
* @throws TransferException
|
||||||
|
*/
|
||||||
|
void generateRequsite(String transferId, OutputStream requsiteStream) throws TransferException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare
|
* Prepare
|
||||||
* @param transferId
|
* @param transferId
|
||||||
|
Reference in New Issue
Block a user