diff --git a/config/alfresco/messages/transfer-service.properties b/config/alfresco/messages/transfer-service.properties
index 7443992707..c2e4e0e5d9 100644
--- a/config/alfresco/messages/transfer-service.properties
+++ b/config/alfresco/messages/transfer-service.properties
@@ -8,6 +8,7 @@ transfer_service.comms.unsupported_protocol=Unsupported protocol: {0}
transfer_service.comms.unsuccessful_response=Received unsuccessful response code from target server: {0}, {1}
transfer_service.comms.http_request_failed=Failed to execute HTTP request {0} to target: {1} status: {2}
transfer_service.no_nodes=No nodes to transfer
+transfer_service.cancelled=Transfer cancelled
transfer_service.receiver.failed_to_create_staging_folder=Unable to create staging directory for transfer {0}
transfer_service.receiver.lock_folder_not_found=Unable to locate specified lock folder: {0}
@@ -20,3 +21,5 @@ transfer_service.receiver.error_staging_snapshot=
transfer_service.receiver.error_staging_content=
transfer_service.receiver.no_snapshot_received=
transfer_service.receiver.error_committing_transfer=
+transfer_service.receiver.transfer_not_found=Failed to find any record of requested transfer: {0}
+transfer_service.receiver.transfer_cancelled=Transfer has been cancelled: {0}
\ No newline at end of file
diff --git a/config/alfresco/model/transferModel.xml b/config/alfresco/model/transferModel.xml
index a428d2c9d0..76678c82b7 100644
--- a/config/alfresco/model/transferModel.xml
+++ b/config/alfresco/model/transferModel.xml
@@ -1,134 +1,192 @@
-
-
- Alfresco Transfer Application Model
- Alfresco
- 2009-12-16
- 1.0
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- http
- https
-
-
-
-
-
-
-
-
- Transfer Group
- The definition of a transfer group
- cm:folder
-
-
-
-
-
-
- Transfer Target
- The definition of a transfer target
- cm:folder
-
-
-
- Endpoint Host
- d:text
- true
-
- true
- false
- false
-
-
-
-
- Endpoint Port
- d:int
- true
-
-
-
- Endpoint Path
- d:text
- true
-
-
-
- Endpoint Protocol
- d:text
- true
-
-
-
-
-
-
- Username
- d:text
-
-
-
-
- Password
- d:any
-
- true
- false
- false
-
-
-
-
-
-
-
- Transfer Lock
- Node type used to represent the transfer lock node
- cm:content
-
-
-
- Locked Transfer Identifier
- d:text
- true
-
-
-
-
-
-
- Transfer Report
- Transfer Report
- cm:content
-
-
-
-
-
-
-
- Can this resource be enabled/disabled.
-
-
- Is this enabled.
- d:boolean
- true
-
-
-
-
-
-
+
+
+ Alfresco Transfer Application Model
+ Alfresco
+ 2009-12-16
+ 1.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ http
+ https
+
+
+
+
+
+
+
+
+ Transfer Group
+ The definition of a transfer group
+ cm:folder
+
+
+
+
+
+
+ Transfer Target
+ The definition of a transfer target
+ cm:folder
+
+
+
+ Endpoint Host
+ d:text
+ true
+
+ true
+ false
+ false
+
+
+
+
+ Endpoint Port
+ d:int
+ true
+
+
+
+ Endpoint Path
+ d:text
+ true
+
+
+
+ Endpoint Protocol
+ d:text
+ true
+
+
+
+
+
+
+ Username
+ d:text
+
+
+
+
+ Password
+ d:any
+
+ true
+ false
+ false
+
+
+
+
+
+
+
+ Transfer Lock
+ Node type used to represent the transfer lock node
+
+ cm:content
+
+ trx:transferRelated
+
+
+
+
+ Temp Transfer Store
+ Node type used for storage of temporarily orphaned incoming nodes
+ cm:content
+
+
+
+ false
+ true
+
+
+ sys:base
+ false
+ true
+
+
+
+
+
+
+ Transfer Record
+ Node type used to record transfer information
+
+ cm:content
+
+
+ Current Progress
+ d:int
+ true
+
+
+ Progress Endpoint
+ d:int
+ true
+
+
+ Transfer Status
+ d:text
+ true
+
+
+ Transfer Error Object
+ d:any
+ false
+
+
+
+
+
+
+ Transfer Report
+ Transfer Report
+ cm:content
+
+
+
+
+
+
+
+ Can this resource be enabled/disabled.
+
+
+ Is this enabled.
+ d:boolean
+ true
+
+
+
+
+
+ Nodes with this aspect are related to a particular transfer.
+
+
+
+ Transfer Identifier
+ d:text
+ true
+
+
+
+
+
+
diff --git a/config/alfresco/transfer-service-context.xml b/config/alfresco/transfer-service-context.xml
index 9e3fc7a0d6..27b79398a6 100644
--- a/config/alfresco/transfer-service-context.xml
+++ b/config/alfresco/transfer-service-context.xml
@@ -1,124 +1,224 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.transfers.childname}/${spaces.transfer_groups.childname}
-
-
- Default Group
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- /${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.transfers.childname}
- /${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.transfers.childname}/${spaces.transfer_temp.childname}
- /${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.transfers.childname}/${spaces.inbound_transfer_records.childname}
- ${transferservice.receiver.stagingDir}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- alfresco.messages.transfer-service
-
-
-
-
-
-
-
-
-
-
-
- ${server.transaction.mode.default}
-
-
-
-
-
-
-
- org.alfresco.service.cmr.transfer.TransferService
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- deployment
-
-
-
-
-
- false
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.transfers.childname}/${spaces.transfer_groups.childname}
+
+
+ Default Group
+
+
+
+
+
+
+
+
+ 2000
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.transfers.childname}
+
+
+ /${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.transfers.childname}/${spaces.transfer_temp.childname}
+
+
+ /${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.transfers.childname}/${spaces.inbound_transfer_records.childname}
+
+
+ ${transferservice.receiver.stagingDir}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ alfresco.messages.transfer-service
+
+
+
+
+
+
+
+
+
+
+
+ ${server.transaction.mode.default}
+
+
+
+
+
+
+
+ org.alfresco.service.cmr.transfer.TransferService
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${server.transaction.mode.default}
+
+
+
+
+
+
+
+ org.alfresco.service.cmr.transfer.TransferReceiver
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ deployment
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/java/org/alfresco/repo/transfer/AbstractManifestProcessorBase.java b/source/java/org/alfresco/repo/transfer/AbstractManifestProcessorBase.java
new file mode 100644
index 0000000000..3ca519fbb1
--- /dev/null
+++ b/source/java/org/alfresco/repo/transfer/AbstractManifestProcessorBase.java
@@ -0,0 +1,193 @@
+package org.alfresco.repo.transfer;
+
+import java.io.File;
+
+import javax.transaction.UserTransaction;
+
+import org.alfresco.repo.transaction.RetryingTransactionHelper;
+import org.alfresco.repo.transfer.manifest.TransferManifestDeletedNode;
+import org.alfresco.repo.transfer.manifest.TransferManifestHeader;
+import org.alfresco.repo.transfer.manifest.TransferManifestNode;
+import org.alfresco.repo.transfer.manifest.TransferManifestNormalNode;
+import org.alfresco.repo.transfer.manifest.TransferManifestProcessor;
+import org.alfresco.service.cmr.repository.ChildAssociationRef;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.transfer.TransferException;
+import org.alfresco.service.cmr.transfer.TransferProgress;
+import org.alfresco.service.cmr.transfer.TransferReceiver;
+import org.alfresco.service.namespace.NamespaceService;
+import org.alfresco.service.namespace.QName;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * This abstract class handles the progress monitoring functionality as well as providing
+ * some utility methods for sub-classes.
+ * @author Brian
+ *
+ */
+public abstract class AbstractManifestProcessorBase implements TransferManifestProcessor
+{
+ private static final Log log = LogFactory.getLog(AbstractManifestProcessorBase.class);
+ private static final String MSG_ERROR_WHILE_COMMITTING_TRANSFER = "transfer_service.receiver.error_committing_transfer";
+
+ private TransferReceiver receiver;
+ private String transferId;
+ private int targetEndProgress;
+ private int currProgress;
+
+ public AbstractManifestProcessorBase(TransferReceiver receiver, String transferId)
+ {
+ this.receiver = receiver;
+ this.transferId = transferId;
+ }
+
+ public final void endTransferManifest()
+ {
+ receiver.getProgressMonitor().updateProgress(transferId, this.targetEndProgress);
+ try
+ {
+ endManifest();
+ }
+ catch(Exception ex)
+ {
+ handleException(null, ex);
+ }
+ }
+
+ protected abstract void endManifest();
+
+ public final void processTransferManifestNode(TransferManifestNormalNode node)
+ {
+ incrementNodeCounter();
+ try
+ {
+ processNode(node);
+ }
+ catch (Exception ex)
+ {
+ handleException(node, ex);
+ }
+ }
+
+ protected abstract void processNode(TransferManifestNormalNode node) throws TransferProcessingException;
+
+ public final void processTransferManifestNode(TransferManifestDeletedNode node)
+ {
+ incrementNodeCounter();
+ try
+ {
+ processNode(node);
+ }
+ catch (Exception ex)
+ {
+ handleException(node, ex);
+ }
+ }
+
+ protected abstract void processNode(TransferManifestDeletedNode node) throws TransferProcessingException;
+
+ public final void processTransferManifiestHeader(TransferManifestHeader header)
+ {
+ TransferProgressMonitor progressMonitor = receiver.getProgressMonitor();
+ TransferProgress progress = progressMonitor.getProgress(transferId);
+ int newEndPos = progress.getEndPosition() + header.getNodeCount();
+ progressMonitor.updateProgress(transferId, progress.getCurrentPosition(), newEndPos);
+ targetEndProgress = newEndPos;
+ currProgress = progress.getCurrentPosition();
+ try
+ {
+ processHeader(header);
+ }
+ catch (Exception ex)
+ {
+ handleException(null, ex);
+ }
+ }
+
+ protected abstract void processHeader(TransferManifestHeader header);
+
+ public final void startTransferManifest()
+ {
+ try
+ {
+ startManifest();
+ }
+ catch (Exception ex)
+ {
+ handleException(null, ex);
+ }
+ }
+
+ protected abstract void startManifest();
+
+ private void incrementNodeCounter()
+ {
+ currProgress++;
+ if (currProgress % 20 == 0)
+ {
+ receiver.getProgressMonitor().updateProgress(transferId, currProgress);
+ }
+ }
+
+ /**
+ * Given the node ref, this method constructs the appropriate ChildAssociationRef that would place this node in the
+ * transfer's temporary folder. Useful when handling orphans.
+ *
+ * @param nodeRef
+ * @return
+ */
+ protected ChildAssociationRef getTemporaryLocation(NodeRef nodeRef)
+ {
+ NodeRef parentNodeRef = receiver.getTempFolder(transferId);
+ QName parentAssocType = TransferModel.ASSOC_TRANSFER_ORPHAN;
+ QName parentAssocName = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, nodeRef.getId());
+ return new ChildAssociationRef(parentAssocType, parentNodeRef, parentAssocName, nodeRef, true, -1);
+ }
+
+ protected File getStagingFolder()
+ {
+ return receiver.getStagingFolder(transferId);
+ }
+
+ private void handleException(TransferManifestNode node, Exception ex)
+ {
+ try
+ {
+ UserTransaction tx = RetryingTransactionHelper.getActiveUserTransaction();
+ if (tx != null)
+ {
+ tx.setRollbackOnly();
+ log.debug("Successfully marked transaction for rollback.");
+ }
+ }
+ catch (Exception e)
+ {
+ //Nothing really to be done here
+ log.warn("Failed to mark transaction as rollback-only in response to an error", e);
+ }
+ TransferProgressMonitor monitor = receiver.getProgressMonitor();
+ String message = (node != null) ? "Error while processing incoming node " + node.getNodeRef() :
+ "Error processing commit";
+
+ monitor.log(transferId, message, ex);
+ //Any non-fatal transfer exception is logged and then skipped - the transfer continues
+ //(albeit with a guaranteed rollback at the end).
+ //A fatal transfer exception is rethrown and causes the transfer to end immediately.
+ //Any non-transfer exception is assumed to be fatal, so is wrapped in a fatal exception
+ //and thrown.
+ if (TransferFatalException.class.isAssignableFrom(ex.getClass()))
+ {
+ throw (TransferFatalException)ex;
+ }
+ else if (!TransferException.class.isAssignableFrom(ex.getClass()))
+ {
+ throw new TransferFatalException(MSG_ERROR_WHILE_COMMITTING_TRANSFER, ex);
+ }
+ }
+
+ protected void logProgress(String message)
+ {
+ receiver.getProgressMonitor().log(transferId, message);
+ }
+}
diff --git a/source/java/org/alfresco/repo/transfer/CreateTransferTargetActionExecuter.java b/source/java/org/alfresco/repo/transfer/CreateTransferTargetActionExecuter.java
new file mode 100644
index 0000000000..9edde5e3d2
--- /dev/null
+++ b/source/java/org/alfresco/repo/transfer/CreateTransferTargetActionExecuter.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2009-2010 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program 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 General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have received a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+
+package org.alfresco.repo.transfer;
+
+import java.util.List;
+
+import org.alfresco.repo.action.executer.ActionExecuterAbstractBase;
+import org.alfresco.service.cmr.action.Action;
+import org.alfresco.service.cmr.action.ParameterDefinition;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.transfer.TransferService;
+
+/**
+ * @author brian
+ *
+ */
+public class CreateTransferTargetActionExecuter extends ActionExecuterAbstractBase
+{
+ public static final String NAME = "create-transfer-target";
+ private TransferService transferService;
+
+ /**
+ * @param transferService the transferService to set
+ */
+ public void setTransferService(TransferService transferService)
+ {
+ this.transferService = transferService;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef)
+ */
+ @Override
+ protected void executeImpl(Action action, NodeRef actionedUponNodeRef)
+ {
+ TransferTestUtil.getTestTarget(transferService);
+ }
+
+ @Override
+ protected void addParameterDefinitions(List paramList)
+ {
+ }
+}
diff --git a/source/java/org/alfresco/repo/transfer/DefaultManifestProcessorFactoryImpl.java b/source/java/org/alfresco/repo/transfer/DefaultManifestProcessorFactoryImpl.java
index dd0c65ae7a..e2ae2a3c9a 100644
--- a/source/java/org/alfresco/repo/transfer/DefaultManifestProcessorFactoryImpl.java
+++ b/source/java/org/alfresco/repo/transfer/DefaultManifestProcessorFactoryImpl.java
@@ -59,7 +59,7 @@ public class DefaultManifestProcessorFactoryImpl implements ManifestProcessorFac
primaryProcessor.setNodeService(nodeService);
processors.add(primaryProcessor);
- RepoSecondaryManifestProcessorImpl secondaryProcessor = new RepoSecondaryManifestProcessorImpl(transferId);
+ RepoSecondaryManifestProcessorImpl secondaryProcessor = new RepoSecondaryManifestProcessorImpl(receiver, transferId);
secondaryProcessor.setNodeResolver(nodeResolver);
secondaryProcessor.setNodeService(nodeService);
processors.add(secondaryProcessor);
diff --git a/source/java/org/alfresco/repo/transfer/HttpClientTransmitterImpl.java b/source/java/org/alfresco/repo/transfer/HttpClientTransmitterImpl.java
index 031239eaa7..ffd1df1176 100644
--- a/source/java/org/alfresco/repo/transfer/HttpClientTransmitterImpl.java
+++ b/source/java/org/alfresco/repo/transfer/HttpClientTransmitterImpl.java
@@ -34,6 +34,7 @@ import java.util.TreeMap;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.transfer.TransferException;
+import org.alfresco.service.cmr.transfer.TransferProgress;
import org.alfresco.service.cmr.transfer.TransferTarget;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
@@ -554,6 +555,59 @@ public class HttpClientTransmitterImpl implements TransferTransmitter
messagesRequest.releaseConnection();
}
}
+
+ /**
+ *
+ */
+ public TransferProgress getStatus(Transfer transfer) throws TransferException
+ {
+ TransferTarget target = transfer.getTransferTarget();
+ HttpMethod statusRequest = new PostMethod();
+ try
+ {
+ HostConfiguration hostConfig = getHostConfig(target);
+ HttpState httpState = getHttpState(target);
+
+ statusRequest.setPath(target.getEndpointPath() + "/status");
+ //Put the transferId on the query string
+ statusRequest.setQueryString(
+ new NameValuePair[] {new NameValuePair("transferId", transfer.getTransferId())});
+
+ try
+ {
+ int responseStatus = httpClient.executeMethod(hostConfig, statusRequest, httpState);
+ checkResponseStatus("status", responseStatus, statusRequest);
+ //If we get here then we've received a 200 response
+ String statusPayload = statusRequest.getResponseBodyAsString();
+ JSONObject statusObj = new JSONObject(statusPayload);
+ //We're expecting the transfer progress encoded in a JSON object...
+ int currentPosition = statusObj.getInt("currentPosition");
+ int endPosition = statusObj.getInt("endPosition");
+ String statusStr= statusObj.getString("status");
+ //We're expecting the transfer progress encoded in a JSON object...
+ TransferProgress p = new TransferProgress();
+ p.setStatus(TransferProgress.Status.valueOf(statusStr));
+ p.setCurrentPosition(currentPosition);
+ p.setEndPosition(endPosition);
+ return p;
+ }
+ catch (RuntimeException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ String error = "Failed to execute HTTP request to target";
+ log.debug(error, e);
+ throw new TransferException(MSG_HTTP_REQUEST_FAILED, new Object[]{"status", target.toString(), e.toString()}, e);
+ }
+ }
+ finally
+ {
+ statusRequest.releaseConnection();
+ }
+ }
+
public void setContentService(ContentService contentService)
{
@@ -566,4 +620,6 @@ public class HttpClientTransmitterImpl implements TransferTransmitter
}
+
+
} // end of class
diff --git a/source/java/org/alfresco/repo/transfer/LoggingTransferProgressMonitorImpl.java b/source/java/org/alfresco/repo/transfer/LoggingTransferProgressMonitorImpl.java
new file mode 100644
index 0000000000..1118e8f747
--- /dev/null
+++ b/source/java/org/alfresco/repo/transfer/LoggingTransferProgressMonitorImpl.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2009-2010 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program 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 General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have received a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+
+package org.alfresco.repo.transfer;
+
+import org.alfresco.service.cmr.transfer.TransferException;
+import org.alfresco.service.cmr.transfer.TransferProgress;
+import org.alfresco.service.cmr.transfer.TransferProgress.Status;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * @author brian
+ *
+ */
+public class LoggingTransferProgressMonitorImpl implements TransferProgressMonitor
+{
+ private static final Log log = LogFactory.getLog(LoggingTransferProgressMonitorImpl.class);
+ private TransferProgressMonitor delegate;
+
+ /**
+ * @param delegate the delegate to set
+ */
+ public void setDelegate(TransferProgressMonitor delegate)
+ {
+ this.delegate = delegate;
+ }
+
+ /**
+ * @param transferId
+ * @return
+ * @throws TransferException
+ * @see org.alfresco.repo.transfer.TransferProgressMonitor#getProgress(java.lang.String)
+ */
+ public TransferProgress getProgress(String transferId) throws TransferException
+ {
+ return delegate.getProgress(transferId);
+ }
+
+ /**
+ * @param transferId
+ * @param obj
+ * @param ex
+ * @throws TransferException
+ * @see org.alfresco.repo.transfer.TransferProgressMonitor#log(java.lang.String, java.lang.Object, java.lang.Throwable)
+ */
+ public void log(String transferId, Object obj, Throwable ex) throws TransferException
+ {
+ localLog(transferId, obj, ex);
+ delegate.log(transferId, obj, ex);
+ }
+
+ /**
+ * @param transferId
+ * @param obj
+ * @throws TransferException
+ * @see org.alfresco.repo.transfer.TransferProgressMonitor#log(java.lang.String, java.lang.Object)
+ */
+ public void log(String transferId, Object obj) throws TransferException
+ {
+ localLog(transferId, obj, null);
+ delegate.log(transferId, obj);
+ }
+
+ /**
+ * @param transferId
+ * @param currPos
+ * @param endPos
+ * @throws TransferException
+ * @see org.alfresco.repo.transfer.TransferProgressMonitor#updateProgress(java.lang.String, int, int)
+ */
+ public void updateProgress(String transferId, int currPos, int endPos) throws TransferException
+ {
+ if (loggingEnabled())
+ {
+ localLog(transferId, "Progress update: " + currPos + " out of " + endPos, null);
+ }
+ delegate.updateProgress(transferId, currPos, endPos);
+ }
+
+ /**
+ * @param transferId
+ * @param currPos
+ * @throws TransferException
+ * @see org.alfresco.repo.transfer.TransferProgressMonitor#updateProgress(java.lang.String, int)
+ */
+ public void updateProgress(String transferId, int currPos) throws TransferException
+ {
+ if (loggingEnabled())
+ {
+ localLog(transferId, "Progress update: current position = " + currPos, null);
+ }
+ delegate.updateProgress(transferId, currPos);
+ }
+
+ /**
+ * @param transferId
+ * @param status
+ * @throws TransferException
+ * @see org.alfresco.repo.transfer.TransferProgressMonitor#updateStatus(java.lang.String, org.alfresco.service.cmr.transfer.TransferProgress.Status)
+ */
+ public void updateStatus(String transferId, Status status) throws TransferException
+ {
+ if (loggingEnabled())
+ {
+ localLog(transferId, "Status update: " + status, null);
+ }
+ delegate.updateStatus(transferId, status);
+ }
+
+ private boolean loggingEnabled()
+ {
+ return log.isInfoEnabled();
+ }
+
+ private void localLog(String transferId, Object obj, Throwable ex)
+ {
+ if (loggingEnabled())
+ {
+ String message = "Transfer Log (" + transferId +"): " + obj.toString();
+ if (ex == null)
+ {
+ log.info(message);
+ }
+ else
+ {
+ log.info(message, ex);
+ }
+ }
+ }
+}
diff --git a/source/java/org/alfresco/repo/transfer/NodeCrawlerTest.java b/source/java/org/alfresco/repo/transfer/NodeCrawlerTest.java
index 6e5708a0fc..0a0f1505ec 100644
--- a/source/java/org/alfresco/repo/transfer/NodeCrawlerTest.java
+++ b/source/java/org/alfresco/repo/transfer/NodeCrawlerTest.java
@@ -38,6 +38,7 @@ import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchService;
+import org.alfresco.service.cmr.transfer.NodeCrawler;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.BaseAlfrescoSpringTest;
@@ -171,7 +172,7 @@ public class NodeCrawlerTest extends BaseAlfrescoSpringTest
nodeService.addChild(node8, node15, ContentModel.ASSOC_THUMBNAILS, QName.createQName(
NamespaceService.APP_MODEL_1_0_URI, "temp"));
- StandardNodeCrawlerImpl crawler = new StandardNodeCrawlerImpl(serviceRegistry);
+ NodeCrawler crawler = new StandardNodeCrawlerImpl(serviceRegistry);
crawler.setNodeFinders(new ChildAssociatedNodeFinder(ContentModel.ASSOC_CONTAINS));
Set crawledNodes = crawler.crawl(node8);
diff --git a/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java b/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java
index 2309e14c8a..0a1f08594a 100644
--- a/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java
+++ b/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java
@@ -40,7 +40,6 @@ import org.alfresco.repo.transfer.manifest.TransferManifestDeletedNode;
import org.alfresco.repo.transfer.manifest.TransferManifestHeader;
import org.alfresco.repo.transfer.manifest.TransferManifestNode;
import org.alfresco.repo.transfer.manifest.TransferManifestNormalNode;
-import org.alfresco.repo.transfer.manifest.TransferManifestProcessor;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.ContentService;
@@ -49,7 +48,6 @@ 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.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -58,7 +56,7 @@ import org.apache.commons.logging.LogFactory;
* @author brian
*
*/
-public class RepoPrimaryManifestProcessorImpl implements TransferManifestProcessor
+public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorBase
{
private static final Log log = LogFactory.getLog(RepoPrimaryManifestProcessorImpl.class);
@@ -78,8 +76,6 @@ public class RepoPrimaryManifestProcessorImpl implements TransferManifestProcess
DEFAULT_LOCAL_PROPERTIES.add(ContentModel.PROP_NODE_UUID);
}
- private TransferReceiver receiver;
- private String transferId;
private NodeService nodeService;
private ContentService contentService;
private CorrespondingNodeResolver nodeResolver;
@@ -91,16 +87,15 @@ public class RepoPrimaryManifestProcessorImpl implements TransferManifestProcess
*/
public RepoPrimaryManifestProcessorImpl(TransferReceiver receiver, String transferId)
{
- this.receiver = receiver;
- this.transferId = transferId;
+ super(receiver, transferId);
}
/*
* (non-Javadoc)
*
- * @see org.alfresco.repo.transfer.manifest.TransferManifestProcessor#endTransferManifest()
+ * @seeorg.alfresco.repo.transfer.manifest.TransferManifestProcessor# endTransferManifest()
*/
- public void endTransferManifest()
+ protected void endManifest()
{
if (!orphans.isEmpty())
{
@@ -111,7 +106,7 @@ public class RepoPrimaryManifestProcessorImpl implements TransferManifestProcess
/**
*
*/
- public void processTransferManifestNode(TransferManifestDeletedNode node)
+ protected void processNode(TransferManifestDeletedNode node)
{
// This is a deleted node. First we need to check whether it has already been deleted in this repo
// too by looking in the local archive store. If we find it then we need not do anything.
@@ -119,10 +114,11 @@ public class RepoPrimaryManifestProcessorImpl implements TransferManifestProcess
// store in which its old parent lives.
// If we can find a corresponding node then we'll delete it.
// If we can't find a corresponding node then we'll do nothing.
-
+ logProgress("Processing incoming deleted node: " + node.getNodeRef());
if (!nodeService.exists(node.getNodeRef()))
{
- // It's not in our archive store. Check to see if we can find it in its original store...
+ // It's not in our archive store. Check to see if we can find it in
+ // its original store...
ChildAssociationRef origPrimaryParent = node.getPrimaryParentAssoc();
NodeRef origNodeRef = new NodeRef(origPrimaryParent.getParentRef().getStoreRef(), node.getNodeRef().getId());
@@ -135,112 +131,99 @@ public class RepoPrimaryManifestProcessorImpl implements TransferManifestProcess
// Yes, it does. Delete it.
if (log.isDebugEnabled())
{
- log.debug("Incoming deleted noderef " + node.getNodeRef() +
- " has been resolved to existing local noderef " + resolvedNodes.resolvedChild +
- " - deleting");
+ log.debug("Incoming deleted noderef " + node.getNodeRef()
+ + " has been resolved to existing local noderef " + resolvedNodes.resolvedChild
+ + " - deleting");
}
+ logProgress("Deleting local node: " + resolvedNodes.resolvedChild);
nodeService.deleteNode(resolvedNodes.resolvedChild);
}
else
{
+ logProgress("Unable to find corresponding node for incoming deleted node: " + node.getNodeRef());
if (log.isDebugEnabled())
{
- log.debug("Incoming deleted noderef has no corresponding local noderef: " + node.getNodeRef() +
- " - ignoring");
+ log.debug("Incoming deleted noderef has no corresponding local noderef: " + node.getNodeRef()
+ + " - ignoring");
}
}
}
+ else
+ {
+ logProgress("Incoming deleted node is already in the local archive store - ignoring: " + node.getNodeRef());
+ }
}
/*
* (non-Javadoc)
*
- * @see
- * org.alfresco.repo.transfer.manifest.TransferManifestProcessor#processTransferManifestNode(org.alfresco.repo.transfer
- * .manifest.TransferManifestNode)
+ * @seeorg.alfresco.repo.transfer.manifest.TransferManifestProcessor#
+ * processTransferManifestNode(org.alfresco.repo.transfer .manifest.TransferManifestNode)
*/
- public void processTransferManifestNode(TransferManifestNormalNode node)
+ protected void processNode(TransferManifestNormalNode node)
{
- try
+ 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();
+ if (primaryParentAssoc == null)
+ {
+ error(node, MSG_NO_PRIMARY_PARENT_SUPPLIED);
+ }
+
+ CorrespondingNodeResolver.ResolvedParentChildPair resolvedNodes = nodeResolver.resolveCorrespondingNode(node
+ .getNodeRef(), primaryParentAssoc, node.getParentPath());
+
+ // Does a corresponding node exist in this repo?
+ if (resolvedNodes.resolvedChild != null)
+ {
+ // Yes, it does. Update it.
if (log.isDebugEnabled())
{
- log.debug("Processing node with incoming noderef of " + node.getNodeRef());
+ log.debug("Incoming noderef " + node.getNodeRef() + " has been resolved to existing local noderef "
+ + resolvedNodes.resolvedChild);
}
- ChildAssociationRef primaryParentAssoc = getPrimaryParent(node);
- if (primaryParentAssoc == null)
- {
- error(node, MSG_NO_PRIMARY_PARENT_SUPPLIED);
- }
-
- CorrespondingNodeResolver.ResolvedParentChildPair resolvedNodes = nodeResolver.resolveCorrespondingNode(
- node.getNodeRef(), primaryParentAssoc, node.getParentPath());
-
- // Does a corresponding node exist in this repo?
- if (resolvedNodes.resolvedChild != null)
- {
- // Yes, it does. Update it.
- if (log.isDebugEnabled())
- {
- log.debug("Incoming noderef " + node.getNodeRef() +
- " has been resolved to existing local noderef " + resolvedNodes.resolvedChild);
- }
- update(node, resolvedNodes, primaryParentAssoc);
- }
- else
- {
- // No, there is no corresponding node. Worth just quickly checking the archive store...
- NodeRef archiveNodeRef = new NodeRef(StoreRef.STORE_REF_ARCHIVE_SPACESSTORE, node.getNodeRef().getId());
- if (nodeService.exists(archiveNodeRef))
- {
- // We have found a node in the archive store that has the same UUID as the one that we've
- // been sent. We'll restore that archived node to a temporary location and then try
- // processing this node again
- if (log.isInfoEnabled())
- {
- log.info("Located an archived node with UUID matching transferred node: " + archiveNodeRef);
- log.info("Attempting to restore " + archiveNodeRef);
- }
- ChildAssociationRef tempLocation = getTemporaryLocation(node.getNodeRef());
- NodeRef restoredNodeRef = nodeService.restoreNode(archiveNodeRef, tempLocation.getParentRef(),
- tempLocation.getTypeQName(), tempLocation.getQName());
- if (log.isInfoEnabled())
- {
- log.info("Successfully restored node as " + restoredNodeRef + " - retrying transferred node");
- }
- processTransferManifestNode(node);
- return;
- }
-
- if (log.isDebugEnabled())
- {
- log.debug("Incoming noderef has no corresponding local noderef: " + node.getNodeRef());
- }
- create(node, resolvedNodes, primaryParentAssoc);
- }
-
+ update(node, resolvedNodes, primaryParentAssoc);
}
- catch (TransferProcessingException ex)
+ else
{
- log.error("transfer processing exception" + ex.toString(), ex);
- //TODO MER BUGBUG - What to do here? probably can't just swallow it
- // does this mean that the manifest is stuffed?
- }
- }
+ // No, there is no corresponding node. Worth just quickly checking
+ // the archive store...
+ NodeRef archiveNodeRef = new NodeRef(StoreRef.STORE_REF_ARCHIVE_SPACESSTORE, node.getNodeRef().getId());
+ if (nodeService.exists(archiveNodeRef))
+ {
+ // We have found a node in the archive store that has the same
+ // UUID as the one that we've
+ // been sent. We'll restore that archived node to a temporary
+ // location and then try
+ // processing this node again
+ if (log.isInfoEnabled())
+ {
+ log.info("Located an archived node with UUID matching transferred node: " + archiveNodeRef);
+ log.info("Attempting to restore " + archiveNodeRef);
+ }
+ logProgress("Restoring node from archive: " + archiveNodeRef);
- /**
- * Given the node ref, this method constructs the appropriate ChildAssociationRef that would place this node in the
- * transfer's temporary folder. Useful when handling orphans.
- *
- * @param nodeRef
- * @return
- */
- private ChildAssociationRef getTemporaryLocation(NodeRef nodeRef)
- {
- NodeRef parentNodeRef = receiver.getTempFolder(transferId);
- QName parentAssocType = ContentModel.ASSOC_CONTAINS;
- QName parentAssocName = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, nodeRef.getId());
- return new ChildAssociationRef(parentAssocType, parentNodeRef, parentAssocName, nodeRef, true, -1);
+ ChildAssociationRef tempLocation = getTemporaryLocation(node.getNodeRef());
+ NodeRef restoredNodeRef = nodeService.restoreNode(archiveNodeRef, tempLocation.getParentRef(),
+ tempLocation.getTypeQName(), tempLocation.getQName());
+ if (log.isInfoEnabled())
+ {
+ log.info("Successfully restored node as " + restoredNodeRef + " - retrying transferred node");
+ }
+ processTransferManifestNode(node);
+ return;
+ }
+
+ if (log.isDebugEnabled())
+ {
+ log.debug("Incoming noderef has no corresponding local noderef: " + node.getNodeRef());
+ }
+ create(node, resolvedNodes, primaryParentAssoc);
+ }
}
/**
@@ -253,6 +236,8 @@ public class RepoPrimaryManifestProcessorImpl implements TransferManifestProcess
ChildAssociationRef primaryParentAssoc)
{
log.info("Creating new node with noderef " + node.getNodeRef());
+ logProgress("Creating new node to correspond to incoming node: " + node.getNodeRef());
+
QName parentAssocType = primaryParentAssoc.getTypeQName();
QName parentAssocName = primaryParentAssoc.getQName();
NodeRef parentNodeRef = resolvedNodes.resolvedParent;
@@ -260,20 +245,23 @@ public class RepoPrimaryManifestProcessorImpl implements TransferManifestProcess
{
if (log.isDebugEnabled())
{
- log.debug("Unable to resolve parent for inbound noderef " + node.getNodeRef() +
- ".\n Supplied parent noderef is " + primaryParentAssoc.getParentRef() +
- ".\n Supplied parent path is " + node.getParentPath().toString());
+ log.debug("Unable to resolve parent for inbound noderef " + node.getNodeRef()
+ + ".\n Supplied parent noderef is " + primaryParentAssoc.getParentRef()
+ + ".\n Supplied parent path is " + node.getParentPath().toString());
}
// We can't find the node's parent.
- // We'll store the node in a temporary location and record it for later processing
+ // We'll store the node in a temporary location and record it for
+ // later processing
ChildAssociationRef tempLocation = getTemporaryLocation(node.getNodeRef());
parentNodeRef = tempLocation.getParentRef();
parentAssocType = tempLocation.getTypeQName();
parentAssocName = tempLocation.getQName();
log.info("Recording orphaned transfer node: " + node.getNodeRef());
+ logProgress("Unable to resolve parent for new incoming node. Storing it in temp folder: " + node.getNodeRef());
storeOrphanNode(primaryParentAssoc);
}
- // We now know that this is a new node, and we have found the appropriate parent node in the
+ // We now know that this is a new node, and we have found the
+ // appropriate parent node in the
// local repository.
log.info("Resolved parent node to " + parentNodeRef);
@@ -285,8 +273,8 @@ public class RepoPrimaryManifestProcessorImpl implements TransferManifestProcess
Map contentProps = processProperties(null, props, true);
// Create the corresponding node...
- ChildAssociationRef newNode = nodeService.createNode(parentNodeRef, parentAssocType, parentAssocName,
- node.getType(), props);
+ ChildAssociationRef newNode = nodeService.createNode(parentNodeRef, parentAssocType, parentAssocName, node
+ .getType(), props);
if (log.isDebugEnabled())
{
@@ -296,7 +284,8 @@ public class RepoPrimaryManifestProcessorImpl implements TransferManifestProcess
// Deal with the content properties
writeContent(newNode.getChildRef(), contentProps);
- // Apply any aspects that are needed but haven't automatically been applied
+ // Apply any aspects that are needed but haven't automatically been
+ // applied
Set aspects = new HashSet(node.getAspects());
aspects.removeAll(nodeService.getAspects(newNode.getChildRef()));
for (QName aspect : aspects)
@@ -304,17 +293,20 @@ public class RepoPrimaryManifestProcessorImpl implements TransferManifestProcess
nodeService.addAspect(newNode.getChildRef(), aspect, null);
}
- // Is the node that we've just added the parent of any orphans that we've found earlier?
+ // Is the node that we've just added the parent of any orphans that
+ // we've found earlier?
List orphansToClaim = orphans.get(newNode.getChildRef());
if (orphansToClaim != null)
{
// Yes, it is...
for (ChildAssociationRef orphan : orphansToClaim)
{
- nodeService.moveNode(orphan.getChildRef(), orphan.getParentRef(), orphan.getTypeQName(),
- orphan.getQName());
+ logProgress("Re-parenting previously orphaned node (" + orphan.getChildRef() + ") with found parent " + orphan.getParentRef());
+ nodeService.moveNode(orphan.getChildRef(), orphan.getParentRef(), orphan.getTypeQName(), orphan
+ .getQName());
}
- // We can now remove the record of these orphans, as their parent has been found
+ // We can now remove the record of these orphans, as their parent
+ // has been found
orphans.remove(newNode.getChildRef());
}
}
@@ -330,28 +322,32 @@ public class RepoPrimaryManifestProcessorImpl implements TransferManifestProcess
{
NodeRef nodeToUpdate = resolvedNodes.resolvedChild;
+ logProgress("Updating local node: " + node.getNodeRef());
QName parentAssocType = primaryParentAssoc.getTypeQName();
QName parentAssocName = primaryParentAssoc.getQName();
NodeRef parentNodeRef = resolvedNodes.resolvedParent;
if (parentNodeRef == null)
{
// We can't find the node's parent.
- // We'll store the node in a temporary location and record it for later processing
+ // We'll store the node in a temporary location and record it for
+ // later processing
ChildAssociationRef tempLocation = getTemporaryLocation(node.getNodeRef());
parentNodeRef = tempLocation.getParentRef();
parentAssocType = tempLocation.getTypeQName();
parentAssocName = tempLocation.getQName();
storeOrphanNode(primaryParentAssoc);
}
- // First of all, do we need to move the node? If any aspect of the primary parent association has changed
+ // First of all, do we need to move the node? If any aspect of the
+ // primary parent association has changed
// then the answer is "yes"
ChildAssociationRef currentParent = nodeService.getPrimaryParent(nodeToUpdate);
- if (!currentParent.getParentRef().equals(parentNodeRef) ||
- !currentParent.getTypeQName().equals(parentAssocType) ||
- !currentParent.getQName().equals(parentAssocName))
+ if (!currentParent.getParentRef().equals(parentNodeRef)
+ || !currentParent.getTypeQName().equals(parentAssocType)
+ || !currentParent.getQName().equals(parentAssocName))
{
// Yes, we need to move the node
nodeService.moveNode(nodeToUpdate, parentNodeRef, parentAssocType, parentAssocName);
+ logProgress("Moved node " + nodeToUpdate + " to be under parent node " + parentNodeRef);
}
log.info("Resolved parent node to " + parentNodeRef);
@@ -415,13 +411,22 @@ public class RepoPrimaryManifestProcessorImpl implements TransferManifestProcess
// ...and copy any supplied content properties into this new map...
for (Map.Entry propEntry : props.entrySet())
{
- if (ContentData.class.isAssignableFrom(propEntry.getValue().getClass()))
+ 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()))
{
contentProps.put(propEntry.getKey(), propEntry.getValue());
}
}
- // Now we can remove the content properties from amongst the other kinds of properties
+ // Now we can remove the content properties from amongst the other kinds
+ // of properties
// (no removeAll on a Map...)
for (QName contentPropertyName : contentProps.keySet())
{
@@ -430,7 +435,8 @@ public class RepoPrimaryManifestProcessorImpl implements TransferManifestProcess
if (!isNew)
{
- // Finally, overlay the repo-specific properties from the existing node (if there is one)
+ // Finally, overlay the repo-specific properties from the existing
+ // node (if there is one)
Map existingProps = (nodeToUpdate == null) ? new HashMap()
: nodeService.getProperties(nodeToUpdate);
@@ -457,7 +463,7 @@ public class RepoPrimaryManifestProcessorImpl implements TransferManifestProcess
*/
private void writeContent(NodeRef nodeToUpdate, Map contentProps)
{
- File stagingDir = receiver.getStagingFolder(transferId);
+ File stagingDir = getStagingFolder();
for (Map.Entry contentEntry : contentProps.entrySet())
{
ContentData contentData = (ContentData) contentEntry.getValue();
@@ -476,32 +482,30 @@ public class RepoPrimaryManifestProcessorImpl implements TransferManifestProcess
}
}
- protected boolean updateNeeded(TransferManifestNode node, NodeRef nodeToUpdate)
+ protected boolean updateNeeded(TransferManifestNormalNode node, NodeRef nodeToUpdate)
{
- return true;
- // TODO MER - Temp commenting out.
- // //Assumption: if the modified and modifier properties haven't changed, and the cm:content property
- // //(if it exists) hasn't changed size then we can assume that properties don't need to be updated...
- // Map suppliedProps = node.getProperties();
- // Date suppliedModifiedDate = (Date)suppliedProps.get(ContentModel.PROP_MODIFIED);
- // String suppliedModifier = (String)suppliedProps.get(ContentModel.PROP_MODIFIER);
- // ContentData suppliedContent = (ContentData)suppliedProps.get(ContentModel.PROP_CONTENT);
- //
- // Map existingProps = nodeService.getProperties(nodeToUpdate);
- // Date existingModifiedDate = (Date)existingProps.get(ContentModel.PROP_MODIFIED);
- // String existingModifier = (String)existingProps.get(ContentModel.PROP_MODIFIER);
- // ContentData existingContent = (ContentData)existingProps.get(ContentModel.PROP_CONTENT);
- //
- // boolean updateNeeded = false;
- // updateNeeded |= ((suppliedModifiedDate != null && !suppliedModifiedDate.equals(existingModifiedDate)) ||
- // (existingModifiedDate != null && !existingModifiedDate.equals(suppliedModifiedDate)));
- // updateNeeded |= ((suppliedContent != null && existingContent == null) ||
- // (suppliedContent == null && existingContent != null) ||
- // (suppliedContent != null && existingContent != null && suppliedContent.getSize() !=
- // existingContent.getSize()));
- // updateNeeded |= ((suppliedModifier != null && !suppliedModifier.equals(existingModifier)) ||
- // (existingModifier != null && !existingModifier.equals(suppliedModifier)));
- // return updateNeeded;
+ boolean updateNeeded = true;
+ // Assumption: if the modified and modifier properties haven't changed, and the cm:content property
+ // (if it exists) hasn't changed size then we can assume that properties don't need to be updated...
+// Map suppliedProps = node.getProperties();
+// Date suppliedModifiedDate = (Date) suppliedProps.get(ContentModel.PROP_MODIFIED);
+// String suppliedModifier = (String) suppliedProps.get(ContentModel.PROP_MODIFIER);
+// ContentData suppliedContent = (ContentData) suppliedProps.get(ContentModel.PROP_CONTENT);
+//
+// Map existingProps = nodeService.getProperties(nodeToUpdate);
+// Date existingModifiedDate = (Date) existingProps.get(ContentModel.PROP_MODIFIED);
+// String existingModifier = (String) existingProps.get(ContentModel.PROP_MODIFIER);
+// ContentData existingContent = (ContentData) existingProps.get(ContentModel.PROP_CONTENT);
+//
+// updateNeeded = false;
+// updateNeeded |= ((suppliedModifiedDate != null && !suppliedModifiedDate.equals(existingModifiedDate)) ||
+// (existingModifiedDate != null && !existingModifiedDate.equals(suppliedModifiedDate)));
+// updateNeeded |= ((suppliedContent != null && existingContent == null)
+// || (suppliedContent == null && existingContent != null) || (suppliedContent != null
+// && existingContent != null && suppliedContent.getSize() != existingContent.getSize()));
+// updateNeeded |= ((suppliedModifier != null && !suppliedModifier.equals(existingModifier)) ||
+// (existingModifier != null && !existingModifier.equals(suppliedModifier)));
+ return updateNeeded;
}
/**
@@ -547,38 +551,16 @@ public class RepoPrimaryManifestProcessorImpl implements TransferManifestProcess
throw ex;
}
- /**
- * @param node
- * @return
- */
- private ChildAssociationRef getPrimaryParent(TransferManifestNormalNode node)
- {
- List parents = node.getParentAssocs();
- for (ChildAssociationRef parent : parents)
- {
- if (parent.isPrimary())
- return parent;
- }
- return null;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see
- * org.alfresco.repo.transfer.manifest.TransferManifestProcessor#processTransferManifiestHeader(org.alfresco.repo
- * .transfer.manifest.TransferManifestHeader)
- */
- public void processTransferManifiestHeader(TransferManifestHeader header)
+ protected void processHeader(TransferManifestHeader header)
{
}
/*
* (non-Javadoc)
*
- * @see org.alfresco.repo.transfer.manifest.TransferManifestProcessor#startTransferManifest()
+ * @seeorg.alfresco.repo.transfer.manifest.TransferManifestProcessor# startTransferManifest()
*/
- public void startTransferManifest()
+ protected void startManifest()
{
}
diff --git a/source/java/org/alfresco/repo/transfer/RepoSecondaryManifestProcessorImpl.java b/source/java/org/alfresco/repo/transfer/RepoSecondaryManifestProcessorImpl.java
index 301f6875fa..1d0d488fb4 100644
--- a/source/java/org/alfresco/repo/transfer/RepoSecondaryManifestProcessorImpl.java
+++ b/source/java/org/alfresco/repo/transfer/RepoSecondaryManifestProcessorImpl.java
@@ -34,57 +34,42 @@ 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.manifest.TransferManifestProcessor;
import org.alfresco.service.cmr.repository.AssociationRef;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
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.RegexQNamePattern;
/**
* @author brian
*
*/
-public class RepoSecondaryManifestProcessorImpl implements TransferManifestProcessor
+public class RepoSecondaryManifestProcessorImpl extends AbstractManifestProcessorBase
{
private NodeService nodeService;
private CorrespondingNodeResolver nodeResolver;
- private String transferId;
/**
+ * @param receiver
* @param transferId
*/
- public RepoSecondaryManifestProcessorImpl(String transferId)
+ public RepoSecondaryManifestProcessorImpl(TransferReceiver receiver, String transferId)
{
- this.transferId = transferId;
+ super(receiver, transferId);
}
- /*
- * (non-Javadoc)
- *
- * @see org.alfresco.repo.transfer.manifest.TransferManifestProcessor#endTransferManifest()
- */
- public void endTransferManifest()
+ protected void endManifest()
{
- // TODO Auto-generated method stub
-
+ //NOOP
}
- /**
- *
- */
- public void processTransferManifestNode(TransferManifestDeletedNode node)
+ protected void processNode(TransferManifestDeletedNode node)
{
+ //NOOP
}
- /*
- * (non-Javadoc)
- *
- * @see
- * org.alfresco.repo.transfer.manifest.TransferManifestProcessor#processTransferManifestNode(org.alfresco.repo.transfer
- * .manifest.TransferManifestNode)
- */
- public void processTransferManifestNode(TransferManifestNormalNode node)
+ protected void processNode(TransferManifestNormalNode node)
{
NodeRef correspondingNodeRef = nodeResolver.resolveCorrespondingNode(node.getNodeRef(),
TransferManifestNodeHelper.getPrimaryParentAssoc(node), node.getParentPath()).resolvedChild;
@@ -245,17 +230,9 @@ public class RepoSecondaryManifestProcessorImpl implements TransferManifestProce
}
- /*
- * (non-Javadoc)
- *
- * @see
- * org.alfresco.repo.transfer.manifest.TransferManifestProcessor#processTransferManifiestHeader(org.alfresco.repo
- * .transfer.manifest.TransferManifestHeader)
- */
- public void processTransferManifiestHeader(TransferManifestHeader header)
+ protected void processHeader(TransferManifestHeader header)
{
- // TODO Auto-generated method stub
-
+ //NOOP
}
/*
@@ -263,10 +240,9 @@ public class RepoSecondaryManifestProcessorImpl implements TransferManifestProce
*
* @see org.alfresco.repo.transfer.manifest.TransferManifestProcessor#startTransferManifest()
*/
- public void startTransferManifest()
+ protected void startManifest()
{
- // TODO Auto-generated method stub
-
+ //NOOP
}
/**
@@ -286,7 +262,4 @@ public class RepoSecondaryManifestProcessorImpl implements TransferManifestProce
{
this.nodeResolver = nodeResolver;
}
-
-
-
}
diff --git a/source/java/org/alfresco/repo/transfer/RepoTransferProgressMonitorImpl.java b/source/java/org/alfresco/repo/transfer/RepoTransferProgressMonitorImpl.java
new file mode 100644
index 0000000000..dc8a3fac48
--- /dev/null
+++ b/source/java/org/alfresco/repo/transfer/RepoTransferProgressMonitorImpl.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2009-2010 Alfresco Software Limited.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program 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 General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ * As a special exception to the terms and conditions of version 2.0 of
+ * the GPL, you may redistribute this Program in connection with Free/Libre
+ * and Open Source Software ("FLOSS") applications as described in Alfresco's
+ * FLOSS exception. You should have received a copy of the text describing
+ * the FLOSS exception, and it is also available here:
+ * http://www.alfresco.com/legal/licensing"
+ */
+
+package org.alfresco.repo.transfer;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.ByteBuffer;
+import java.nio.channels.WritableByteChannel;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.repo.transaction.RetryingTransactionHelper;
+import org.alfresco.service.cmr.repository.ContentService;
+import org.alfresco.service.cmr.repository.ContentWriter;
+import org.alfresco.service.cmr.repository.NodeRef;
+import org.alfresco.service.cmr.repository.NodeService;
+import org.alfresco.service.cmr.transfer.TransferException;
+import org.alfresco.service.cmr.transfer.TransferProgress;
+import org.alfresco.service.cmr.transfer.TransferProgress.Status;
+import org.alfresco.service.transaction.TransactionService;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * @author brian
+ *
+ */
+public class RepoTransferProgressMonitorImpl implements TransferProgressMonitor
+{
+ private static final Log log = LogFactory.getLog(RepoTransferProgressMonitorImpl.class);
+
+ private static final String MSG_TRANSFER_NOT_FOUND = "transfer_service.receiver.transfer_not_found";
+ private static final String MSG_TRANSFER_CANCELLED = "transfer_service.receiver.transfer_cancelled";
+
+ private NodeService nodeService;
+ private ContentService contentService;
+ private TransactionService transactionService;
+ private Map transferLogWriters = new TreeMap();
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.alfresco.repo.transfer.TransferProgressMonitor#getProgress(java.lang.String)
+ */
+ public TransferProgress getProgress(final String transferId)
+ {
+ return transactionService.getRetryingTransactionHelper().doInTransaction(
+ new RetryingTransactionHelper.RetryingTransactionCallback()
+ {
+ public TransferProgress execute() throws Throwable
+ {
+ NodeRef nodeRef = getTransferRecord(transferId);
+
+ TransferProgress progress = new TransferProgress();
+ progress.setStatus(TransferProgress.Status.valueOf((String) nodeService.getProperty(nodeRef,
+ TransferModel.PROP_TRANSFER_STATUS)));
+ progress.setCurrentPosition((Integer) nodeService.getProperty(nodeRef,
+ TransferModel.PROP_PROGRESS_POSITION));
+ progress.setEndPosition((Integer) nodeService.getProperty(nodeRef,
+ TransferModel.PROP_PROGRESS_ENDPOINT));
+ progress.setError((Throwable) nodeService.getProperty(nodeRef,
+ TransferModel.PROP_TRANSFER_ERROR));
+ return progress;
+ }
+ }, false, true);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.alfresco.repo.transfer.TransferProgressMonitor#log(java.lang.String, java.lang.Object)
+ */
+ public void log(final String transferId, final Object obj)
+ {
+ log(transferId, obj, null);
+ }
+
+ public void log(final String transferId, final Object obj, final Throwable ex)
+ {
+ transactionService.getRetryingTransactionHelper().doInTransaction(
+ new RetryingTransactionHelper.RetryingTransactionCallback