Fixes to replication job status handling:

- success, error and cancelled states now correctly reported
- source and target reports now correctly provided for each of above

Changes:
- deprecated TransferService interface, replaced by TransferService2
  - introduces new sync transfer methods
  - new TransferServiceImpl2 class, old TransferServiceImpl delegates to new class
- sync transfer now returns TransferEndEvent
- sync transfer now raises TransferFailureException
- success, error and cancelled events are now end events (raised after report events)
- transfer client handling refactored to support cancel and errors appropriately
  - converted to event loop with polling of server status for all states
  - cancel request may now end with success or error (depending on when cancel requested)
  - extract transfer errors from server
  - only raise exception for errors (cancelled now returns)
  - source and destination reports written for all states
- Added TransferEndEvent interface for end events - reports attached to end event
- replication service fixed to record source and dest reports in error case
- action service fixed to record cancelled state

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@22390 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
David Caruana
2010-09-10 14:00:05 +00:00
parent 82955f3ae2
commit 35b2b7a122
25 changed files with 2176 additions and 1492 deletions

View File

@@ -10,6 +10,9 @@ transfer_service.comms.unsuccessful_response=Received unsuccessful response code
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.failed_to_get_transfer_status=Failed to retrieve transfer status from target {0}
transfer_service.target_error=Transfer target failed with {0}
transfer_service.unknown_target_error=Unknown error
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}

View File

@@ -41,10 +41,7 @@
<!-- Replication Service base bean -->
<bean id="replicationService" class="org.alfresco.repo.replication.ReplicationServiceImpl" >
<property name="nodeService" ref="NodeService" />
<property name="actionService" ref="ActionService"/>
<property name="dictionaryService" ref="dictionaryService" />
<property name="transferService" ref="TransferService" />
<property name="scheduledPersistedActionService" ref="scheduledPersistedActionService" />
<property name="replicationDefinitionPersister" ref="replicationDefinitionPersister" />
</bean>
@@ -68,14 +65,14 @@
<value>{http://www.alfresco.org/model/content/1.0}folder</value>
</list>
</property>
<property name="jobLockService" ref="JobLockService" />
<property name="transferService" ref="TransferService" />
<property name="replicationService" ref="ReplicationService" />
<property name="nodeCrawlerFactory" ref="NodeCrawlerFactory" />
<property name="actionTrackingService" ref="actionTrackingService" />
<property name="jobLockService" ref="JobLockService" />
<property name="transferService" ref="TransferService2" />
<property name="nodeCrawlerFactory" ref="NodeCrawlerFactory" />
<property name="actionTrackingService" ref="actionTrackingService" />
<property name="transactionService" ref="transactionService" />
<property name="replicationDefinitionPersister" ref="replicationDefinitionPersister" />
</bean>
<!-- JavaScript API support -->
<bean id="replicationServiceScript" parent="baseJavaScriptExtension"
class="org.alfresco.repo.replication.script.ScriptReplicationService">

View File

@@ -1,8 +1,14 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
<!-- Transfer Service Configuration -->
<bean id="transferService" class="org.alfresco.repo.transfer.TransferServiceImpl"
<!-- Transfer Service Configuration -->
<bean id="transferService" class="org.alfresco.repo.transfer.TransferServiceImpl">
<property name="transferServiceImpl2">
<ref bean="transferService2" />
</property>
</bean>
<bean id="transferService2" class="org.alfresco.repo.transfer.TransferServiceImpl2"
init-method="init">
<property name="actionService">
<ref bean="ActionService" />
@@ -146,24 +152,41 @@
</props>
</property>
</bean>
<!-- Transfer service bean -->
<bean id="TransferService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.transfer.TransferService</value>
</property>
<property name="target">
<ref bean="transferService" />
</property>
<property name="interceptorNames">
<list>
<idref local="TransferService_transaction" />
<idref bean="AuditMethodInterceptor" />
<idref bean="exceptionTranslator" />
<idref local="TransferService_security" />
</list>
</property>
</bean>
<!-- Transfer service bean -->
<bean id="TransferService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.transfer.TransferService</value>
</property>
<property name="target">
<ref bean="transferService" />
</property>
<property name="interceptorNames">
<list>
<idref local="TransferService_transaction" />
<idref bean="AuditMethodInterceptor" />
<idref bean="exceptionTranslator" />
<idref local="TransferService_security" />
</list>
</property>
</bean>
<bean id="TransferService2" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>org.alfresco.service.cmr.transfer.TransferService2</value>
</property>
<property name="target">
<ref bean="transferService2" />
</property>
<property name="interceptorNames">
<list>
<idref local="TransferService_transaction" />
<idref bean="AuditMethodInterceptor" />
<idref bean="exceptionTranslator" />
<idref local="TransferService_security" />
</list>
</property>
</bean>
<bean id="TransferReceiver_security"
class="org.alfresco.repo.security.permissions.impl.AlwaysProceedMethodInterceptor" />
@@ -180,6 +203,7 @@
</property>
</bean>
<!-- Transfer service bean -->
<bean id="TransferReceiver" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
@@ -198,7 +222,6 @@
</property>
</bean>
<bean id="transfer-async" class="org.alfresco.repo.transfer.TransferAsyncAction"
parent="action-executer">

View File

@@ -244,7 +244,7 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
* Schedule the recording of the action failure to occur in another
* transaction
*/
public void recordActionFailure(Action action, Throwable exception)
public void recordActionFailure(Action action, final Throwable exception)
{
if (logger.isDebugEnabled() == true)
{
@@ -313,10 +313,18 @@ public class ActionTrackingServiceImpl implements ActionTrackingService
.createAction(actionNode);
// Update it
if (exception instanceof ActionCancelledException)
{
action.setExecutionStatus(ActionStatus.Cancelled);
action.setExecutionFailureMessage(null);
}
else
{
action.setExecutionStatus(ActionStatus.Failed);
action.setExecutionFailureMessage(exception.getMessage());
}
action.setExecutionStartDate(startedAt);
action.setExecutionEndDate(endedAt);
action.setExecutionStatus(ActionStatus.Failed);
action.setExecutionFailureMessage(message);
runtimeActionService.saveActionImpl(actionNode, action);
if (logger.isDebugEnabled() == true)

View File

@@ -27,25 +27,28 @@ import org.alfresco.repo.action.ActionCancelledException;
import org.alfresco.repo.action.executer.ActionExecuterAbstractBase;
import org.alfresco.repo.lock.JobLockService;
import org.alfresco.repo.lock.LockAcquisitionException;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transfer.ChildAssociatedNodeFinder;
import org.alfresco.repo.transfer.ContentClassFilter;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ActionTrackingService;
import org.alfresco.service.cmr.action.ParameterDefinition;
import org.alfresco.service.cmr.replication.ReplicationDefinition;
import org.alfresco.service.cmr.replication.ReplicationService;
import org.alfresco.service.cmr.replication.ReplicationServiceException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.transfer.NodeCrawler;
import org.alfresco.service.cmr.transfer.NodeCrawlerFactory;
import org.alfresco.service.cmr.transfer.TransferCallback;
import org.alfresco.service.cmr.transfer.TransferCancelledException;
import org.alfresco.service.cmr.transfer.TransferDefinition;
import org.alfresco.service.cmr.transfer.TransferEndEvent;
import org.alfresco.service.cmr.transfer.TransferEvent;
import org.alfresco.service.cmr.transfer.TransferEventBegin;
import org.alfresco.service.cmr.transfer.TransferEventCancelled;
import org.alfresco.service.cmr.transfer.TransferEventEnterState;
import org.alfresco.service.cmr.transfer.TransferEventReport;
import org.alfresco.service.cmr.transfer.TransferService;
import org.alfresco.service.cmr.transfer.TransferEventError;
import org.alfresco.service.cmr.transfer.TransferFailureException;
import org.alfresco.service.cmr.transfer.TransferService2;
import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -60,10 +63,11 @@ public class ReplicationActionExecutor extends ActionExecuterAbstractBase {
private static Log logger = LogFactory.getLog(ReplicationActionExecutor.class);
private JobLockService jobLockService;
private TransferService transferService;
private ReplicationService replicationService;
private TransferService2 transferService;
private NodeCrawlerFactory nodeCrawlerFactory;
private ActionTrackingService actionTrackingService;
private TransactionService transactionService;
private ReplicationDefinitionPersisterImpl replicationDefinitionPersister;
/**
* By default, we lock for 30 minutes
@@ -80,22 +84,12 @@ public class ReplicationActionExecutor extends ActionExecuterAbstractBase {
this.jobLockService = jobLockService;
}
/**
* Injects the ReplicationService bean.
*
* @param nodeService the ReplicationService.
*/
public void setReplicationService(ReplicationService replicationService)
{
this.replicationService = replicationService;
}
/**
* Injects the TransferService bean.
*
* @param transferService the TransferService.
*/
public void setTransferService(TransferService transferService)
public void setTransferService(TransferService2 transferService)
{
this.transferService = transferService;
}
@@ -120,6 +114,25 @@ public class ReplicationActionExecutor extends ActionExecuterAbstractBase {
this.actionTrackingService = actionTrackingService;
}
/**
* Injects the TransactionService bean.
*
* @param transactionService the TransactionService.
*/
public void setTransactionService(TransactionService transactionService)
{
this.transactionService = transactionService;
}
/**
* Injects the ReplicationDefinitionPersister bean.
* @param replicationDefinitionPersister
*/
public void setReplicationDefinitionPersister(ReplicationDefinitionPersisterImpl replicationDefinitionPersister)
{
this.replicationDefinitionPersister = replicationDefinitionPersister;
}
@Override
protected void addParameterDefinitions(List<ParameterDefinition> paramList) {
// Not used - our definitions hold everything on them
@@ -197,8 +210,8 @@ public class ReplicationActionExecutor extends ActionExecuterAbstractBase {
}
// Clear the previous transfer report references
replicationDef.setLocalTransferReport(null);
replicationDef.setRemoteTransferReport(null);
// replicationDef.setLocalTransferReport(null);
// replicationDef.setRemoteTransferReport(null);
// Lock the service - only one instance of the replication
// should occur at a time
@@ -215,43 +228,78 @@ public class ReplicationActionExecutor extends ActionExecuterAbstractBase {
throw new ReplicationServiceException("Error processing payload list - " + e.getMessage(), e);
}
// Holder for reports generated by the transfer
ReplicationReportCollector reports = new ReplicationReportCollector();
// Ask the transfer service to do the replication
// work for us
try {
// Build the definition
TransferDefinition transferDefinition =
buildTransferDefinition(replicationDef, toTransfer);
// Off we go
transferService.transfer(
TransferEndEvent endEvent = null;
try
{
// Build the definition
TransferDefinition transferDefinition =
buildTransferDefinition(replicationDef, toTransfer);
// Off we go
endEvent = transferService.transfer(
replicationDef.getTargetName(),
transferDefinition,
lock, reports
);
lock);
// Record the details of the transfer reports
replicationDef.setLocalTransferReport(reports.getLocalReport());
replicationDef.setRemoteTransferReport(reports.getRemoteReport());
} catch(Exception e) {
if(! (e instanceof TransferCancelledException))
{
lock.close();
throw new ReplicationServiceException("Error executing transfer - " + e.getMessage(), e);
}
if (endEvent instanceof TransferEventCancelled)
{
if (logger.isDebugEnabled())
logger.debug("Cancelling replication job");
// If we were cancelled, throw the magic exception so
// that this is correctly recorded
throw new ActionCancelledException(replicationDef);
}
// Record details of the transfer reports (in success case)
replicationDef.setLocalTransferReport(endEvent.getSourceReport());
replicationDef.setRemoteTransferReport(endEvent.getDestinationReport());
}
// All done, release our lock
lock.close();
// If we were cancelled, throw the magic exception so
// that this is correctly recorded
if(actionTrackingService.isCancellationRequested(replicationDef))
catch(Exception e)
{
throw new ActionCancelledException(replicationDef);
if (e instanceof ActionCancelledException)
{
writeDefinitionReports(replicationDef, endEvent.getSourceReport(), endEvent.getDestinationReport());
throw (ActionCancelledException)e;
}
if (e instanceof TransferFailureException)
{
TransferEventError failureEndEvent = ((TransferFailureException)e).getErrorEvent();
writeDefinitionReports(replicationDef, failureEndEvent.getSourceReport(), failureEndEvent.getDestinationReport());
throw new ReplicationServiceException("Error executing transfer - " + e.getCause().getMessage(), e);
}
writeDefinitionReports(replicationDef, null, null);
throw new ReplicationServiceException("Error executing transfer - " + e.getMessage(), e);
}
finally
{
lock.close();
}
}
private void writeDefinitionReports(final ReplicationDefinition replicationDef, NodeRef sourceReport, NodeRef destinationReport)
{
replicationDef.setLocalTransferReport(sourceReport);
replicationDef.setRemoteTransferReport(destinationReport);
if (replicationDef.getNodeRef() != null)
{
// Record details of the transfer reports
transactionService.getRetryingTransactionHelper().doInTransaction(
new RetryingTransactionHelper.RetryingTransactionCallback<Object>()
{
public Object execute() throws Throwable
{
if (logger.isDebugEnabled())
logger.debug("Exception - writing replication def reports");
replicationDefinitionPersister.saveReplicationDefinition(replicationDef);
return null;
}
}, false, true);
}
}
/**
@@ -367,53 +415,4 @@ public class ReplicationActionExecutor extends ActionExecuterAbstractBase {
);
}
}
/**
* A {@link TransferCallback} which collects the various reports generated by
* the transfer.
*/
protected class ReplicationReportCollector implements TransferCallback
{
private NodeRef localReport;
private NodeRef remoteReport;
protected ReplicationReportCollector()
{
}
/**
* Collect source and destination repository target reports
*/
public void processEvent(TransferEvent event)
{
if(event instanceof TransferEventReport)
{
TransferEventReport reportEvent = (TransferEventReport)event;
if (reportEvent.getReportType().equals(TransferEventReport.ReportType.SOURCE))
{
localReport = reportEvent.getNodeRef();
}
else if (reportEvent.getReportType().equals(TransferEventReport.ReportType.DESTINATION))
{
remoteReport = reportEvent.getNodeRef();
}
}
}
/**
* @return local transfer report
*/
public NodeRef getLocalReport()
{
return localReport;
}
/**
* @return target transfer report
*/
public NodeRef getRemoteReport()
{
return remoteReport;
}
}
}

View File

@@ -23,11 +23,8 @@ import java.util.List;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.action.scheduled.ScheduledPersistedAction;
import org.alfresco.service.cmr.action.scheduled.ScheduledPersistedActionService;
import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.replication.ReplicationDefinition;
import org.alfresco.service.cmr.replication.ReplicationService;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.transfer.TransferService;
import org.alfresco.util.GUID;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -40,9 +37,6 @@ public class ReplicationServiceImpl implements ReplicationService, ReplicationDe
private static final Log log = LogFactory.getLog(ReplicationServiceImpl.class);
private ActionService actionService;
private DictionaryService dictionaryService;
private TransferService transferService;
private NodeService nodeService;
private ScheduledPersistedActionService scheduledPersistedActionService;
private ReplicationDefinitionPersisterImpl replicationDefinitionPersister;
@@ -56,24 +50,6 @@ public class ReplicationServiceImpl implements ReplicationService, ReplicationDe
this.replicationDefinitionPersister = replicationDefinitionPersister;
}
/**
* Injects the TransferService bean
* @param transferService
*/
public void setTransferService(TransferService transferService)
{
this.transferService = transferService;
}
/**
* Injects the NodeService bean.
* @param nodeService
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* Injects the ActionService bean.
* @param actionService
@@ -83,15 +59,6 @@ public class ReplicationServiceImpl implements ReplicationService, ReplicationDe
this.actionService = actionService;
}
/**
* Injects the DictionaryService bean.
* @param dictionaryService
*/
public void setDictionaryService(DictionaryService dictionaryService)
{
this.dictionaryService = dictionaryService;
}
/**
* Injects the Scheduled Persisted Action Service bean
* @param scheduledPersistedActionService

View File

@@ -24,7 +24,6 @@ import junit.framework.TestCase;
import org.alfresco.service.cmr.action.ActionService;
import org.alfresco.service.cmr.replication.ReplicationDefinition;
import org.alfresco.service.cmr.repository.NodeService;
/**
* @author Nick Burch
@@ -32,7 +31,6 @@ import org.alfresco.service.cmr.repository.NodeService;
public class ReplicationServiceImplTest extends TestCase
{
private ActionService actionService = mock(ActionService.class);
private NodeService nodeService = mock(NodeService.class);
private final ReplicationDefinitionPersisterImpl replicationDefinitionPersister = mock(ReplicationDefinitionPersisterImpl.class);
private ReplicationServiceImpl replicationService;
@@ -45,7 +43,6 @@ public class ReplicationServiceImplTest extends TestCase
{
replicationService = new ReplicationServiceImpl();
replicationService.setActionService(actionService);
replicationService.setNodeService(nodeService);
replicationService.setReplicationDefinitionPersister(replicationDefinitionPersister);
}

View File

@@ -39,7 +39,7 @@ import org.alfresco.repo.model.Repository;
import org.alfresco.repo.replication.script.ScriptReplicationDefinition;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.repo.transfer.TransferServiceImpl;
import org.alfresco.repo.transfer.TransferServiceImpl2;
import org.alfresco.repo.transfer.TransferTransmitter;
import org.alfresco.repo.transfer.UnitTestInProcessTransmitterImpl;
import org.alfresco.repo.transfer.UnitTestTransferManifestNodeFactory;
@@ -66,7 +66,7 @@ import org.alfresco.service.cmr.repository.ScriptService;
import org.alfresco.service.cmr.transfer.TransferDefinition;
import org.alfresco.service.cmr.transfer.TransferException;
import org.alfresco.service.cmr.transfer.TransferReceiver;
import org.alfresco.service.cmr.transfer.TransferService;
import org.alfresco.service.cmr.transfer.TransferService2;
import org.alfresco.service.cmr.transfer.TransferTarget;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
@@ -90,7 +90,7 @@ public class ReplicationServiceIntegrationTest extends TestCase
private ReplicationActionExecutor replicationActionExecutor;
private ReplicationService replicationService;
private TransactionService transactionService;
private TransferService transferService;
private TransferService2 transferService;
private ContentService contentService;
private JobLockService jobLockService;
private ScriptService scriptService;
@@ -130,7 +130,7 @@ public class ReplicationServiceIntegrationTest extends TestCase
replicationActionExecutor = (ReplicationActionExecutor) ctx.getBean("replicationActionExecutor");
replicationService = (ReplicationService) ctx.getBean("replicationService");
transactionService = (TransactionService) ctx.getBean("transactionService");
transferService = (TransferService) ctx.getBean("transferService");
transferService = (TransferService2) ctx.getBean("transferService2");
contentService = (ContentService) ctx.getBean("contentService");
jobLockService = (JobLockService) ctx.getBean("jobLockService");
actionService = (ActionService) ctx.getBean("actionService");
@@ -495,50 +495,61 @@ public class ReplicationServiceIntegrationTest extends TestCase
// First one with no target, which isn't allowed
ReplicationDefinition rd = replicationService.createReplicationDefinition(ACTION_NAME, "Test");
UserTransaction txn = transactionService.getUserTransaction();
txn.begin();
try {
actionService.executeAction(rd, replicationRoot);
fail("Shouldn't be permitted with no Target defined");
} catch(ReplicationServiceException e) {}
txn.rollback();
// Now no payload, also not allowed
rd.setTargetName(TRANSFER_TARGET);
txn = transactionService.getUserTransaction();
txn.begin();
try {
actionService.executeAction(rd, replicationRoot);
fail("Shouldn't be permitted with no payload defined");
} catch(ReplicationServiceException e) {}
txn.rollback();
// Now disabled, not allowed
assertEquals(true, rd.isEnabled());
rd.setEnabled(false);
assertEquals(false, rd.isEnabled());
txn = transactionService.getUserTransaction();
txn.begin();
try {
actionService.executeAction(rd, replicationRoot);
fail("Shouldn't be permitted when disabled");
} catch(ReplicationServiceException e) {}
txn.rollback();
// Invalid Transfer Target, not allowed
rd = replicationService.createReplicationDefinition(ACTION_NAME, "Test");
rd.setTargetName("I am an invalid target that isn't there");
rd.getPayload().add( folder1 );
txn = transactionService.getUserTransaction();
txn.begin();
try {
actionService.executeAction(rd, replicationRoot);
fail("Shouldn't be permitted with an invalid transfer target");
} catch(ReplicationServiceException e) {}
txn.rollback();
// Can't send Folder2a if Folder2 isn't there, as it
// won't have anywhere to put it
rd = replicationService.createReplicationDefinition(ACTION_NAME, "Test");
rd.setTargetName(TRANSFER_TARGET);
rd.getPayload().add( folder2a );
txn = transactionService.getUserTransaction();
txn.begin();
try {
actionService.executeAction(rd, replicationRoot);
fail("Shouldn't be able to send Folder2a when Folder2 is missing!");
} catch(ReplicationServiceException e) {}
txn.rollback();
// Next a proper one with a transient definition,
// and a sensible set of folders
@@ -547,7 +558,7 @@ public class ReplicationServiceIntegrationTest extends TestCase
rd.getPayload().add( folder1 );
// Will execute without error
UserTransaction txn = transactionService.getUserTransaction();
txn = transactionService.getUserTransaction();
txn.begin();
actionService.executeAction(rd, replicationRoot);
txn.commit();
@@ -608,7 +619,7 @@ public class ReplicationServiceIntegrationTest extends TestCase
* Take a 10 second lock on the job, then execute.
* Ensure that we really wait a little over 10 seconds.
*/
public void testReplicationExectionLocking() throws Exception
public void testReplicationExecutionLocking() throws Exception
{
// We need the test transfer target for this test
makeTransferTarget();
@@ -718,6 +729,8 @@ public class ReplicationServiceIntegrationTest extends TestCase
// Ensure it was cancelled
assertEquals(null, rd.getExecutionFailureMessage());
assertNotNull(rd.getLocalTransferReport());
assertNotNull(rd.getRemoteTransferReport());
assertEquals(ActionStatus.Cancelled, rd.getExecutionStatus());
}
@@ -1227,7 +1240,7 @@ public class ReplicationServiceIntegrationTest extends TestCase
private void makeTransferServiceLocal() {
TransferReceiver receiver = (TransferReceiver)ctx.getBean("transferReceiver");
TransferManifestNodeFactory transferManifestNodeFactory = (TransferManifestNodeFactory)ctx.getBean("transferManifestNodeFactory");
TransferServiceImpl transferServiceImpl = (TransferServiceImpl) ctx.getBean("transferService");
TransferServiceImpl2 transferServiceImpl = (TransferServiceImpl2) ctx.getBean("transferService2");
ContentService contentService = (ContentService) ctx.getBean("contentService");
TransferTransmitter transmitter =

View File

@@ -0,0 +1,67 @@
/*
* 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 org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.transfer.RangedTransferEvent;
import org.alfresco.service.cmr.transfer.TransferEndEvent;
import org.alfresco.service.cmr.transfer.TransferEvent;
/**
* An abstract implementation of TransferEndEvent.
* @see TransferEvent
* @see RangedTransferEvent
*/
public class TransferEndEventImpl extends TransferEventImpl implements TransferEndEvent
{
private NodeRef sourceReport;
private NodeRef destinationReport;
public void setSourceReport(NodeRef sourceReport)
{
this.sourceReport = sourceReport;
}
/*
* (non-Javadoc)
* @see org.alfresco.service.cmr.transfer.TransferEndEvent#getSourceReport()
*/
@Override
public NodeRef getSourceReport()
{
return sourceReport;
}
public void setDestinationReport(NodeRef destinationReport)
{
this.destinationReport = destinationReport;
}
/*
* (non-Javadoc)
* @see org.alfresco.service.cmr.transfer.TransferEndEvent#getDestinationReport()
*/
@Override
public NodeRef getDestinationReport()
{
return destinationReport;
}
}

View File

@@ -25,16 +25,15 @@ import java.util.concurrent.LinkedBlockingQueue;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.transfer.TransferCallback;
import org.alfresco.service.cmr.transfer.TransferEndEvent;
import org.alfresco.service.cmr.transfer.TransferEvent;
import org.alfresco.service.cmr.transfer.TransferEventBegin;
import org.alfresco.service.cmr.transfer.TransferEventCommittingStatus;
import org.alfresco.service.cmr.transfer.TransferEventEndState;
import org.alfresco.service.cmr.transfer.TransferEventEnterState;
import org.alfresco.service.cmr.transfer.TransferEventError;
import org.alfresco.service.cmr.transfer.TransferEventReport;
import org.alfresco.service.cmr.transfer.TransferEventSendingContent;
import org.alfresco.service.cmr.transfer.TransferEventSendingSnapshot;
import org.alfresco.service.cmr.transfer.TransferEventSuccess;
import org.alfresco.service.cmr.transfer.TransferEventReport;
/**
* Class to bring together all the transfer event stuff.
@@ -45,15 +44,15 @@ import org.alfresco.service.cmr.transfer.TransferEventReport;
*
* @author Mark Rogers
*/
public class TransferEventProcessor
{
public Set<TransferCallback> observers = new HashSet<TransferCallback>();
LinkedBlockingQueue<TransferEvent> queue = new LinkedBlockingQueue<TransferEvent>();
public TransferEventProcessor()
{
}
public void addObserver(TransferCallback observer)
{
@@ -65,14 +64,6 @@ public class TransferEventProcessor
observers.remove(observer);
}
/**
*
*/
public TransferEventProcessor()
{
}
public void begin(String transferId)
{
setState(TransferEvent.TransferState.START);
@@ -80,47 +71,23 @@ public class TransferEventProcessor
event.setTransferState(TransferEvent.TransferState.START);
event.setMessage("begin transferId:" + transferId);
queue.add(event);
event.setTransferId(transferId);
event.setTransferId(transferId);
notifyObservers();
}
public void start()
{
setState(TransferEvent.TransferState.START);
setState(TransferEvent.TransferState.START);
notifyObservers();
}
public void success()
public void end(TransferEndEvent endEvent)
{
setState(TransferEvent.TransferState.SUCCESS);
/**
* Write the success event
*/
TransferEventSuccess event = new TransferEventSuccess();
event.setTransferState(TransferEvent.TransferState.SUCCESS);
event.setLast(true);
event.setMessage("success lastEvent:true");
queue.add(event);
setState(endEvent.getTransferState());
queue.add(endEvent);
notifyObservers();
}
public void error(Exception exception)
{
setState(TransferEvent.TransferState.ERROR);
/**
* Write the error event
*/
TransferEventError event = new TransferEventError();
event.setTransferState(TransferEvent.TransferState.ERROR);
event.setLast(true);
event.setMessage("error lastEvent:true, " + exception.getMessage());
event.setException(exception);
queue.add(event);
notifyObservers();
}
/**
*
* @param data
@@ -175,6 +142,7 @@ public class TransferEventProcessor
public void writeReport(NodeRef nodeRef, TransferEventReport.ReportType reportType)
{
TransferEventReport event = new TransferEventReport();
event.setTransferState(currentState);
event.setNodeRef(nodeRef);
event.setReportType(reportType);
event.setMessage("report nodeRef:" + nodeRef + ", reportType :" + reportType );
@@ -198,13 +166,8 @@ public class TransferEventProcessor
event.setMessage("committing " + position + " of " + range);
queue.add(event);
notifyObservers();
}
public void abort()
{
}
private TransferEvent.TransferState currentState;
@@ -217,13 +180,13 @@ public class TransferEventProcessor
TransferEventImpl event = new TransferEventEndState();
event.setMessage("End State: " + currentState);
event.setTransferState(currentState);
queue.add(event);
queue.add(event);
}
TransferEventImpl event = new TransferEventEnterState();
event.setMessage("Enter State: " + state);
event.setTransferState(state);
queue.add(event);
queue.add(event);
currentState = state;
}
}

View File

@@ -18,8 +18,12 @@
*/
package org.alfresco.repo.transfer;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.File;
import java.io.OutputStream;
@@ -55,7 +59,7 @@ import org.alfresco.service.cmr.transfer.TransferEventSendingSnapshot;
import org.alfresco.service.cmr.transfer.TransferEventSuccess;
import org.alfresco.service.cmr.transfer.TransferException;
import org.alfresco.service.cmr.transfer.TransferProgress;
import org.alfresco.service.cmr.transfer.TransferService;
import org.alfresco.service.cmr.transfer.TransferService2;
import org.alfresco.service.cmr.transfer.TransferTarget;
import org.alfresco.service.cmr.transfer.TransferEvent.TransferState;
import org.alfresco.service.cmr.transfer.TransferProgress.Status;
@@ -74,10 +78,10 @@ public class TransferServiceCallbackTest extends TestCase
private static final String TRANSFER_TARGET_NAME = "TransferServiceImplUnitTest";
private ApplicationContext applicationContext;
private TransferServiceImpl transferServiceImpl;
private TransferServiceImpl2 transferServiceImpl;
private AuthenticationComponent authenticationComponent;
private TransferTransmitter mockedTransferTransmitter;
private TransferService transferService;
private TransferService2 transferService;
private TransactionService transactionService;
private UserTransaction tx;
private Repository repository;
@@ -103,7 +107,7 @@ public class TransferServiceCallbackTest extends TestCase
applicationContext = ApplicationContextHelper.getApplicationContext();
// Get the required services
transferServiceImpl = (TransferServiceImpl) this.applicationContext.getBean("transferService");
transferServiceImpl = (TransferServiceImpl2) this.applicationContext.getBean("transferService2");
transferService = transferServiceImpl;
authenticationComponent = (AuthenticationComponent) applicationContext.getBean("authenticationComponent");
transactionService = (TransactionService) applicationContext.getBean("transactionComponent");
@@ -266,6 +270,14 @@ public class TransferServiceCallbackTest extends TestCase
event.setTransferState(TransferState.COMMITTING);
expectedEvents.add(event);
event = new TransferEventReport();
event.setTransferState(TransferState.COMMITTING);
expectedEvents.add(event);
event = new TransferEventReport();
event.setTransferState(TransferState.COMMITTING);
expectedEvents.add(event);
event = new TransferEventEndState();
event.setTransferState(TransferState.COMMITTING);
expectedEvents.add(event);
@@ -278,12 +290,6 @@ public class TransferServiceCallbackTest extends TestCase
event.setTransferState(TransferState.SUCCESS);
expectedEvents.add(event);
event = new TransferEventReport();
expectedEvents.add(event);
event = new TransferEventReport();
expectedEvents.add(event);
verifyCallback(expectedEvents);
}
@@ -443,6 +449,14 @@ public class TransferServiceCallbackTest extends TestCase
event.setTransferState(TransferState.START);
expectedEvents.add(event);
event = new TransferEventReport();
event.setTransferState(TransferState.START);
expectedEvents.add(event);
event = new TransferEventReport();
event.setTransferState(TransferState.START);
expectedEvents.add(event);
event = new TransferEventEndState();
event.setTransferState(TransferState.START);
expectedEvents.add(event);
@@ -450,15 +464,12 @@ public class TransferServiceCallbackTest extends TestCase
event = new TransferEventEnterState();
event.setTransferState(TransferState.ERROR);
expectedEvents.add(event);
event = new TransferEventError();
event.setTransferState(TransferState.ERROR);
((TransferEventError)event).setException(ex);
expectedEvents.add(event);
event = new TransferEventReport();
expectedEvents.add(event);
verifyCallback(expectedEvents);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -39,6 +39,7 @@ import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transfer.manifest.TransferManifestNodeFactory;
@@ -95,7 +96,7 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
{
private TransferService transferService;
private ContentService contentService;
private TransferServiceImpl transferServiceImpl;
private TransferServiceImpl2 transferServiceImpl;
private SearchService searchService;
private TransactionService transactionService;
private TransferReceiver receiver;
@@ -130,7 +131,7 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
// Get the required services
this.transferService = (TransferService)this.applicationContext.getBean("TransferService");
this.contentService = (ContentService)this.applicationContext.getBean("ContentService");
this.transferServiceImpl = (TransferServiceImpl)this.applicationContext.getBean("transferService");
this.transferServiceImpl = (TransferServiceImpl2)this.applicationContext.getBean("transferService2");
this.searchService = (SearchService)this.applicationContext.getBean("SearchService");
this.transactionService = (TransactionService)this.applicationContext.getBean("TransactionService");
this.nodeService = (NodeService) this.applicationContext.getBean("nodeService");
@@ -1803,7 +1804,7 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
*/
assertTrue("transfer report is too small", transferReport.size() > 3);
assertTrue("transfer report does not start with START", transferReport.get(0).getTransferState().equals(TransferEvent.TransferState.START));
assertTrue("transfer report does not end with ERROR", transferReport.get(transferReport.size()-2).getTransferState().equals(TransferEvent.TransferState.ERROR));
assertTrue("transfer report does not end with CANCELLED", transferReport.get(transferReport.size()-1).getTransferState().equals(TransferEvent.TransferState.CANCELLED));
// last event is the transfer report event.
}
finally
@@ -2057,16 +2058,18 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
// Now validate the destination side transfer report against the XSD
ContentReader reader = contentService.getReader(reportNode, ContentModel.PROP_CONTENT);
assertNotNull("transfer reader is null", reader);
Source transferReportSource = new StreamSource(reader.getContentInputStream());
try
if (reader.getMimetype().equals(MimetypeMap.MIMETYPE_XML))
{
validator.validate(transferReportSource);
Source transferReportSource = new StreamSource(reader.getContentInputStream());
try
{
validator.validate(transferReportSource);
}
catch (Exception e)
{
fail("Destination Transfer Report reportNode:" + reportNode + " message :" + e.getMessage() );
}
}
catch (Exception e)
{
fail("Destination Transfer Report reportNode:" + reportNode + " message :" + e.getMessage() );
}
}
}
finally

View File

@@ -23,8 +23,6 @@ import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
@@ -38,7 +36,6 @@ import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.transfer.Transfer;
import org.alfresco.repo.transfer.TransferModel;
import org.alfresco.repo.transfer.TransferServiceImpl;
import org.alfresco.repo.transfer.manifest.TransferManifestDeletedNode;
import org.alfresco.repo.transfer.manifest.TransferManifestHeader;
import org.alfresco.repo.transfer.manifest.TransferManifestNormalNode;
@@ -99,7 +96,7 @@ public class TransferReporterImpl implements TransferReporter
{
Map<QName, Serializable> properties = new HashMap<QName, Serializable> ();
String title = transferName + " , error";
String title = transferName;
String description = "Transfer error report, " + transferName + " targetName " + target.getName();
String name = transferName;
@@ -167,7 +164,7 @@ public class TransferReporterImpl implements TransferReporter
{
Map<QName, Serializable> properties = new HashMap<QName, Serializable> ();
String title = transferName + ", success";
String title = transferName;
String description = "Transfer success report : " + transferName + " targetName: " + target.getName();
String name = transferName;
@@ -290,7 +287,7 @@ public class TransferReporterImpl implements TransferReporter
File tempFile)
{
String title = transferName + ", destination, success";
String title = transferName + " destination";
String description = "Transfer Destination Report, success, targetName : " + target.getName();
String name = transferName + " destination";

View File

@@ -0,0 +1,49 @@
/*
* Copyright (C) 2005-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.service.cmr.transfer;
import org.alfresco.service.cmr.repository.NodeRef;
/**
* TransferEvents are produced by the Transfer service during an in flight
* transfer.
*
* <p>
* The TransferCallback presents TransferEvents for processing.
*
* @see TransferCallback
*
* @author davidc
*/
public interface TransferEndEvent extends TransferEvent
{
/**
* Gets the report generated by the transfer source repository
*
* @return source transfer report
*/
public NodeRef getSourceReport();
/**
* Gets the report generated by the transfer destination repository
*
* @return destination transfer report
*/
public NodeRef getDestinationReport();
}

View File

@@ -35,7 +35,7 @@ public interface TransferEvent
/**
* The transfer events will Start with a START event and finish with either SUCCESS or ERROR
*/
enum TransferState { START, SENDING_SNAPSHOT, SENDING_CONTENT, PREPARING, COMMITTING, SUCCESS, ERROR };
enum TransferState { START, SENDING_SNAPSHOT, SENDING_CONTENT, PREPARING, COMMITTING, SUCCESS, ERROR, CANCELLED };
/**
* Get the state of this transfer

View File

@@ -0,0 +1,32 @@
/*
* Copyright (C) 2005-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.service.cmr.transfer;
import org.alfresco.repo.transfer.TransferEndEventImpl;
/**
* The cancelled event indicates a transfer was aborted
*/
public class TransferEventCancelled extends TransferEndEventImpl
{
public String toString()
{
return "TransferEventCancelled";
}
}

View File

@@ -18,12 +18,12 @@
*/
package org.alfresco.service.cmr.transfer;
import org.alfresco.repo.transfer.TransferEventImpl;
import org.alfresco.repo.transfer.TransferEndEventImpl;
/**
* Indicates the reason why a transfer failed
*/
public class TransferEventError extends TransferEventImpl implements TransferEvent
public class TransferEventError extends TransferEndEventImpl
{
private Exception exception;

View File

@@ -1,7 +1,5 @@
package org.alfresco.service.cmr.transfer;
import java.util.Date;
import org.alfresco.repo.transfer.TransferEventImpl;
import org.alfresco.service.cmr.repository.NodeRef;

View File

@@ -18,12 +18,12 @@
*/
package org.alfresco.service.cmr.transfer;
import org.alfresco.repo.transfer.TransferEventImpl;
import org.alfresco.repo.transfer.TransferEndEventImpl;
/**
* The success event indicates a successfull transfer
* The success event indicates a successful transfer
*/
public class TransferEventSuccess extends TransferEventImpl implements TransferEvent
public class TransferEventSuccess extends TransferEndEventImpl
{
public String toString()
{

View File

@@ -27,7 +27,7 @@ import org.alfresco.error.AlfrescoRuntimeException;
*/
public class TransferException extends AlfrescoRuntimeException
{
/**
/**
* Serial version UID
*/
private static final long serialVersionUID = 3257571685241467958L;

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2005-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.service.cmr.transfer;
/**
* Transfer failure exception
*
* @author davidc
*/
public class TransferFailureException extends TransferException
{
private static final long serialVersionUID = 9009938314128119981L;
private TransferEventError event;
public TransferFailureException(TransferEventError event)
{
super(event.getMessage(), event.getException());
this.event = event;
}
/**
* Gets the end event (representing the failure)
*
* @return end event
*/
public TransferEventError getErrorEvent()
{
return event;
}
}

View File

@@ -28,12 +28,15 @@ import org.alfresco.service.Auditable;
import org.alfresco.service.NotAuditable;
/**
* The transfer service is responsible for transfering nodes between one instance of Alfresco and another remote instance.
* as well as the transfer method, this interface also provides methods for managing the
* The transfer service is responsible for transferring nodes between one instance of Alfresco and another remote instance.
* as well as the transfer method, this interface also provides methods for managing transfer targets.
*
* @see TransferService2
*
* @author Mark Rogers
*/
@PublicService
@Deprecated
public interface TransferService
{

View File

@@ -0,0 +1,235 @@
/*
* 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.service.cmr.transfer;
import java.util.Collection;
import java.util.Set;
import org.alfresco.service.Auditable;
import org.alfresco.service.NotAuditable;
import org.alfresco.service.PublicService;
/**
* The transfer service is responsible for transferring nodes between one instance of Alfresco and another remote instance.
* as well as the transfer method, this interface also provides methods for managing transfer targets.
*
* @author davidc
*/
@PublicService
public interface TransferService2
{
/**
* Transfer nodes sync, with callback. This synchronous version of the transfer method waits for the transfer to complete
* before returning to the caller. Callbacks are called in the current thread context, so will be associated with the current
* transaction and user.
*
* @param targetName the name of the target to transfer to
* @param definition - the definition of the transfer. Specifies which nodes to transfer.
* The following properties must be set, nodes
* @param callback - a set of callback handlers that will be called as transfer proceeds. May be null.
* @throws TransferException
* @return transfer end event (in case of success or cancellation)
*/
@Auditable(parameters={"targetName"})
public TransferEndEvent transfer(String targetName, TransferDefinition definition, Collection<TransferCallback> callback) throws TransferFailureException;
/**
* Transfer nodes sync, with callback. This synchronous version of the transfer method waits for the transfer to complete
* before returning to the caller. Callbacks are called in the current thread context, so will be associated with the current
* transaction and user.
*
* @param targetName the name of the target to transfer to
* @param definition - the definition of the transfer. Specifies which nodes to transfer.
* The following properties must be set, nodes
* @param callbacks - a list of callback handlers that will be called as transfer proceeds. May be null.
* @throws TransferException
* @return transfer end event (in case of success or cancellation)
*/
@Auditable(parameters={"targetName"})
public TransferEndEvent transfer(String targetName, TransferDefinition definition, TransferCallback... callbacks) throws TransferFailureException;
/**
* Transfer nodes async with callback. The asynchronous version of the transfer method starts a transfer and returns as
* soon as possible.
*
* The transfer callbacks will be called by a different thread to that used to call the transferAsync method so transaction
* context will be different to the calling context. The asychronous transfer does not have access to uncommitted
* data in the calling transaction.
*
* @param targetName the name of the target to transfer to
* @param definition - the definition of the transfer. Specifies which nodes to transfer.
* The following properties must be set, nodes
* @param callback - a collection of callback handlers that will be called as transfer proceeds. May be null.
*
* @throws TransferException
*/
@Auditable(parameters={"targetName"})
public void transferAsync(String targetName, TransferDefinition definition, Collection<TransferCallback> callback) throws TransferException;
/**
* Transfer nodes async with callback. The asynchronous version of the transfer method starts a transfer and returns as
* soon as possible.
*
* The transfer callbacks will be called by a different thread to that used to call the transferAsync method so transaction
* context will be different to the calling context. The asychronous transfer does not have access to uncommitted
* data in the calling transaction.
*
* @param targetName the name of the target to transfer to
* @param definition - the definition of the transfer. Specifies which nodes to transfer.
* The following properties must be set, nodes
* @param callbacks - a collection of callback handlers that will be called as transfer proceeds. May be null.
*
* @throws TransferException
*/
@Auditable(parameters={"targetName"})
public void transferAsync(String targetName, TransferDefinition definition, TransferCallback... callbacks) throws TransferException;
/**
* Verify a target is available and that the configured credentials are valid.
* @throws TransferException
*/
@NotAuditable
public void verify(TransferTarget target) throws TransferException;
/**
* Create and save a new transfer target. Creates and saves a new transfer target with a single, but long, method call.
*
* @param name, the name of this transfer target, which must be unique
* @param title, the display name of this transfer target
* @param description,
* @param endpointProtocol, either http or https
* @param endpointHost,
* @param endpointPort,
* @param endpointPath,
* @param username,
* @param password,
* @return the newly created transfer target.
*/
@Auditable
public TransferTarget createAndSaveTransferTarget(String name, String title, String description, String endpointProtocol,
String endpointHost, int endpointPort, String endpointPath, String username, char[] password) throws TransferException;
/**
* Creates an in memory transfer target. Before it is used it must be populated with the following values and
* saved with the saveTransferTarget method. The name of the transfer target must be unique.
* <ul>
* <li>title</li>
* <li>description</li>
* <li>endpointProtocol</li>
* <li>endpointHost</li>
* <li>endpointPort</li>
* <li>endpointPath</li>
* <li>username</li>
* <li>password</li>
* </ul>
* @return an in memory transfer target
*/
@Auditable(parameters={"name"})
public TransferTarget createTransferTarget(String name);
/**
* Get all the transfer targets
*/
@NotAuditable
public Set<TransferTarget>getTransferTargets() throws TransferException;
/**
* Get All the transfer targets for a particular transfer target group.
* @param groupName, the name of the transfer group
*/
@NotAuditable
public Set<TransferTarget>getTransferTargets(String groupName) throws TransferException;
/**
* Get a transfer target by its name
* @throws TransferException - target does not exist
*/
@NotAuditable
public TransferTarget getTransferTarget(String name) throws TransferException;
/**
* Test to see if the target with the specified name exists
* @param name
* @return true if the specified target exists, and false otherwise
*/
@NotAuditable
public boolean targetExists(String name);
/**
* Delete a transfer target. After calling this method the transfer target will no longer exist.
* @throws TransferException - target does not exist
* @param name, the name of this transfer target,
*/
@Auditable(parameters={"name"})
public void deleteTransferTarget(String name) throws TransferException;
/**
* Save TransferTarget, will create a transfer target if it does not already exist or update an existing transfer target.
*
* The following properties may be updated:
* endpointHost,
* endpointPort,
* endpointProtocol,
* endpointPath,
* username,
* password,
* title,
* description
*
* The following properties may not be updated:
* name, must be specified.
* nodeRef, if specified will be ignored.
*
* @param update
*/
@Auditable
public TransferTarget saveTransferTarget(TransferTarget update) throws TransferException;
/**
* Enables/Disables the named transfer target
* @param name the name of the transfer target
* @param enable (or false=disable)
*/
@Auditable(parameters={"name", "enable"})
public void enableTransferTarget(String name, boolean enable) throws TransferException;
/**
* Asynchronously cancel an in-progress transfer
*
* This method tells an in-process transfer to give up, rollback and stop as soon as possible.
*
* Depending upon the state of the in-progress transfer, the transfer may still complete,
* despite calling this method, however in most cases the transfer will not complete.
*
* Calling this method for a transfer that does not exist, possibly because it has already finished, has no
* effect and will not throw an exception.
*
* The transfer identifier can be obtained from the TransferEventBegin event that is passed to registered callbacks when
* transfer starts.
*
* @param transferId the unique identifier of the transfer to cancel.
*
* @see TransferEventBegin;
*/
@Auditable(parameters={"transferId"})
public void cancelAsync(String transferId);
}