mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merge DM-DM_deployment to HEAD
18665 : Switch over to using new surf <formdata multipart-processing="false" /> configuration option. - now the PostContentCommandProcessor and PostSnapshotCommandProcessor handle their own MimePart processing. 18683 : SAIL-288 Implementation of TransferService client side cancelAsync. 18716 : Adding TransferEventBegin missed from asyncCancel work. 18734 : Transfer format : implementation of null properties and Serialized base64 Java objects for type d:any 18749 : SAIL-290: Added features that provide asynchronous commit on the receiver end and the ability to query commit status, as well as code that writes a progress report on the server side (currently only plain text) and the functionality to allow a transfer to be cancelled 18750 : New files that should have been checked in with previous commit but weren't... 18770 : Various transfer service work. - correction to transfer report name. - use surf Base64 Encoder - implementation of async commit to the TransferServiceImpl - implementation of the statusCommand through the HttpClientTransmitter. 18773 : transferId was null. 18780 : Changed the server-side commit to occur asynchronously. Added two test actions to transfer a single node or a tree of nodes. Tweaked TransferDefinition to provide varargs version of setNodes. 18793 : SAIL-290: Added a couple of test actions. Added varargs versions of transfer and transferAsync on TransferService. 18794 : SAIL-290: Added "targetExists" operation to the TransferService interface. 18804 : SAIL-36: Fixed an issue where transfer could fail if numerous nodes with the same cm:name value are transferred. 18805 : SAIL-36: Added model file that should have been with last commit. 18808 Continuing work on transfer report. 18825 TransferServiceImplTest green line. 18836 : Added a little more output to the server-side transfer report. 18848 : More work on transfer report. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@18865 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -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}
|
@@ -1,134 +1,192 @@
|
||||
<model name="trx:applicationmodel" xmlns="http://www.alfresco.org/model/dictionary/1.0">
|
||||
|
||||
<description>Alfresco Transfer Application Model</description>
|
||||
<author>Alfresco</author>
|
||||
<published>2009-12-16</published>
|
||||
<version>1.0</version>
|
||||
<description>Alfresco Transfer Application Model</description>
|
||||
<author>Alfresco</author>
|
||||
<published>2009-12-16</published>
|
||||
<version>1.0</version>
|
||||
|
||||
<imports>
|
||||
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
|
||||
<import uri="http://www.alfresco.org/model/system/1.0" prefix="sys"/>
|
||||
<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
|
||||
</imports>
|
||||
<imports>
|
||||
<import uri="http://www.alfresco.org/model/dictionary/1.0"
|
||||
prefix="d" />
|
||||
<import uri="http://www.alfresco.org/model/system/1.0" prefix="sys" />
|
||||
<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm" />
|
||||
</imports>
|
||||
|
||||
<namespaces>
|
||||
<namespace uri="http://www.alfresco.org/model/transfer/1.0" prefix="trx"/>
|
||||
</namespaces>
|
||||
<namespaces>
|
||||
<namespace uri="http://www.alfresco.org/model/transfer/1.0"
|
||||
prefix="trx" />
|
||||
</namespaces>
|
||||
|
||||
<constraints>
|
||||
<constraint name="trx:protocols" type="LIST">
|
||||
<parameter name="allowedValues">
|
||||
<list>
|
||||
<value>http</value>
|
||||
<value>https</value>
|
||||
</list>
|
||||
</parameter>
|
||||
</constraint>
|
||||
</constraints>
|
||||
<constraints>
|
||||
<constraint name="trx:protocols" type="LIST">
|
||||
<parameter name="allowedValues">
|
||||
<list>
|
||||
<value>http</value>
|
||||
<value>https</value>
|
||||
</list>
|
||||
</parameter>
|
||||
</constraint>
|
||||
</constraints>
|
||||
|
||||
<types>
|
||||
<types>
|
||||
|
||||
<type name="trx:transferGroup">
|
||||
<title>Transfer Group</title>
|
||||
<description>The definition of a transfer group</description>
|
||||
<parent>cm:folder</parent>
|
||||
<properties>
|
||||
</properties>
|
||||
</type>
|
||||
<type name="trx:transferGroup">
|
||||
<title>Transfer Group</title>
|
||||
<description>The definition of a transfer group</description>
|
||||
<parent>cm:folder</parent>
|
||||
<properties>
|
||||
</properties>
|
||||
</type>
|
||||
|
||||
|
||||
<type name="trx:transferTarget">
|
||||
<title>Transfer Target</title>
|
||||
<description>The definition of a transfer target</description>
|
||||
<parent>cm:folder</parent>
|
||||
<properties>
|
||||
<type name="trx:transferTarget">
|
||||
<title>Transfer Target</title>
|
||||
<description>The definition of a transfer target</description>
|
||||
<parent>cm:folder</parent>
|
||||
<properties>
|
||||
|
||||
<property name="trx:endpointhost">
|
||||
<title>Endpoint Host</title>
|
||||
<type>d:text</type>
|
||||
<mandatory enforced="true">true</mandatory>
|
||||
<index enabled="true">
|
||||
<atomic>true</atomic>
|
||||
<stored>false</stored>
|
||||
<tokenised>false</tokenised>
|
||||
</index>
|
||||
</property>
|
||||
<property name="trx:endpointhost">
|
||||
<title>Endpoint Host</title>
|
||||
<type>d:text</type>
|
||||
<mandatory enforced="true">true</mandatory>
|
||||
<index enabled="true">
|
||||
<atomic>true</atomic>
|
||||
<stored>false</stored>
|
||||
<tokenised>false</tokenised>
|
||||
</index>
|
||||
</property>
|
||||
|
||||
<property name="trx:endpointport">
|
||||
<title>Endpoint Port</title>
|
||||
<type>d:int</type>
|
||||
<mandatory enforced="true">true</mandatory>
|
||||
</property>
|
||||
<property name="trx:endpointport">
|
||||
<title>Endpoint Port</title>
|
||||
<type>d:int</type>
|
||||
<mandatory enforced="true">true</mandatory>
|
||||
</property>
|
||||
|
||||
<property name="trx:endpointpath">
|
||||
<title>Endpoint Path</title>
|
||||
<type>d:text</type>
|
||||
<mandatory enforced="true">true</mandatory>
|
||||
</property>
|
||||
<property name="trx:endpointpath">
|
||||
<title>Endpoint Path</title>
|
||||
<type>d:text</type>
|
||||
<mandatory enforced="true">true</mandatory>
|
||||
</property>
|
||||
|
||||
<property name="trx:endpointprotocol">
|
||||
<title>Endpoint Protocol</title>
|
||||
<type>d:text</type>
|
||||
<mandatory enforced="true">true</mandatory>
|
||||
<constraints>
|
||||
<constraint ref="trx:protocols" />
|
||||
</constraints>
|
||||
</property>
|
||||
<property name="trx:endpointprotocol">
|
||||
<title>Endpoint Protocol</title>
|
||||
<type>d:text</type>
|
||||
<mandatory enforced="true">true</mandatory>
|
||||
<constraints>
|
||||
<constraint ref="trx:protocols" />
|
||||
</constraints>
|
||||
</property>
|
||||
|
||||
<property name="trx:username">
|
||||
<title>Username</title>
|
||||
<type>d:text</type>
|
||||
</property>
|
||||
<property name="trx:username">
|
||||
<title>Username</title>
|
||||
<type>d:text</type>
|
||||
</property>
|
||||
|
||||
<!-- todo cleartext for now - needs encrypting -->
|
||||
<property name="trx:password">
|
||||
<title>Password</title>
|
||||
<type>d:any</type>
|
||||
<index enabled="false">
|
||||
<atomic>true</atomic>
|
||||
<stored>false</stored>
|
||||
<tokenised>false</tokenised>
|
||||
</index>
|
||||
</property>
|
||||
<!-- todo cleartext for now - needs encrypting -->
|
||||
<property name="trx:password">
|
||||
<title>Password</title>
|
||||
<type>d:any</type>
|
||||
<index enabled="false">
|
||||
<atomic>true</atomic>
|
||||
<stored>false</stored>
|
||||
<tokenised>false</tokenised>
|
||||
</index>
|
||||
</property>
|
||||
|
||||
</properties>
|
||||
</type>
|
||||
</properties>
|
||||
</type>
|
||||
|
||||
<type name="trx:transferLock">
|
||||
<title>Transfer Lock</title>
|
||||
<description>Node type used to represent the transfer lock node</description>
|
||||
<parent>cm:content</parent>
|
||||
<properties>
|
||||
<type name="trx:transferLock">
|
||||
<title>Transfer Lock</title>
|
||||
<description>Node type used to represent the transfer lock node
|
||||
</description>
|
||||
<parent>cm:content</parent>
|
||||
<mandatory-aspects>
|
||||
<aspect>trx:transferRelated</aspect>
|
||||
</mandatory-aspects>
|
||||
</type>
|
||||
|
||||
<property name="trx:transferId">
|
||||
<title>Locked Transfer Identifier</title>
|
||||
<type>d:text</type>
|
||||
<mandatory enforced="false">true</mandatory>
|
||||
</property>
|
||||
</properties>
|
||||
</type>
|
||||
<type name="trx:tempTransferStore">
|
||||
<title>Temp Transfer Store</title>
|
||||
<description>Node type used for storage of temporarily orphaned incoming nodes</description>
|
||||
<parent>cm:content</parent>
|
||||
<associations>
|
||||
<child-association name="trx:orphan">
|
||||
<source>
|
||||
<mandatory>false</mandatory>
|
||||
<many>true</many>
|
||||
</source>
|
||||
<target>
|
||||
<class>sys:base</class>
|
||||
<mandatory>false</mandatory>
|
||||
<many>true</many>
|
||||
</target>
|
||||
</child-association>
|
||||
</associations>
|
||||
</type>
|
||||
|
||||
<!-- The Transfer Report -->
|
||||
<type name="trx:transferReport">
|
||||
<title>Transfer Report</title>
|
||||
<description>Transfer Report</description>
|
||||
<parent>cm:content</parent>
|
||||
</type>
|
||||
<type name="trx:transferRecord">
|
||||
<title>Transfer Record</title>
|
||||
<description>Node type used to record transfer information
|
||||
</description>
|
||||
<parent>cm:content</parent>
|
||||
<properties>
|
||||
<property name="trx:progressPosition">
|
||||
<title>Current Progress</title>
|
||||
<type>d:int</type>
|
||||
<mandatory enforced="false">true</mandatory>
|
||||
</property>
|
||||
<property name="trx:progressEndpoint">
|
||||
<title>Progress Endpoint</title>
|
||||
<type>d:int</type>
|
||||
<mandatory enforced="false">true</mandatory>
|
||||
</property>
|
||||
<property name="trx:transferStatus">
|
||||
<title>Transfer Status</title>
|
||||
<type>d:text</type>
|
||||
<mandatory enforced="false">true</mandatory>
|
||||
</property>
|
||||
<property name="trx:transferError">
|
||||
<title>Transfer Error Object</title>
|
||||
<type>d:any</type>
|
||||
<mandatory>false</mandatory>
|
||||
</property>
|
||||
</properties>
|
||||
</type>
|
||||
|
||||
</types>
|
||||
<!-- The Transfer Report -->
|
||||
<type name="trx:transferReport">
|
||||
<title>Transfer Report</title>
|
||||
<description>Transfer Report</description>
|
||||
<parent>cm:content</parent>
|
||||
</type>
|
||||
|
||||
<aspects>
|
||||
<!-- Can this resorce be temporarily disabled? -->
|
||||
<aspect name="trx:enableable">
|
||||
<title>Can this resource be enabled/disabled.</title>
|
||||
<properties>
|
||||
<property name="trx:enabled">
|
||||
<title>Is this enabled.</title>
|
||||
<type>d:boolean</type>
|
||||
<mandatory>true</mandatory>
|
||||
</property>
|
||||
</properties>
|
||||
</aspect>
|
||||
</aspects>
|
||||
</types>
|
||||
|
||||
<aspects>
|
||||
<!-- Can this resorce be temporarily disabled? -->
|
||||
<aspect name="trx:enableable">
|
||||
<title>Can this resource be enabled/disabled.</title>
|
||||
<properties>
|
||||
<property name="trx:enabled">
|
||||
<title>Is this enabled.</title>
|
||||
<type>d:boolean</type>
|
||||
<mandatory>true</mandatory>
|
||||
</property>
|
||||
</properties>
|
||||
</aspect>
|
||||
|
||||
<aspect name="trx:transferRelated">
|
||||
<title>Nodes with this aspect are related to a particular transfer.
|
||||
</title>
|
||||
<properties>
|
||||
<property name="trx:transferId">
|
||||
<title>Transfer Identifier</title>
|
||||
<type>d:text</type>
|
||||
<mandatory enforced="false">true</mandatory>
|
||||
</property>
|
||||
</properties>
|
||||
</aspect>
|
||||
</aspects>
|
||||
|
||||
</model>
|
||||
|
@@ -1,37 +1,42 @@
|
||||
<?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" init-method="init">
|
||||
<property name="actionService">
|
||||
<ref bean="ActionService"/>
|
||||
</property>
|
||||
<property name="nodeService">
|
||||
<ref bean="NodeService"/>
|
||||
</property>
|
||||
<property name="searchService">
|
||||
<ref bean="SearchService"/>
|
||||
</property>
|
||||
<property name="transactionService">
|
||||
<ref bean="TransactionService"/>
|
||||
</property>
|
||||
<property name="transferSpaceQuery">
|
||||
<value>/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.transfers.childname}/${spaces.transfer_groups.childname}</value>
|
||||
</property>
|
||||
<property name="defaultTransferGroup">
|
||||
<value>Default Group</value>
|
||||
</property>
|
||||
<property name="transmitter" ref="transferTransmitter" />
|
||||
<!-- Transfer Service Configuration -->
|
||||
<bean id="transferService" class="org.alfresco.repo.transfer.TransferServiceImpl"
|
||||
init-method="init">
|
||||
<property name="actionService">
|
||||
<ref bean="ActionService" />
|
||||
</property>
|
||||
<property name="nodeService">
|
||||
<ref bean="NodeService" />
|
||||
</property>
|
||||
<property name="searchService">
|
||||
<ref bean="SearchService" />
|
||||
</property>
|
||||
<property name="transactionService">
|
||||
<ref bean="TransactionService" />
|
||||
</property>
|
||||
<property name="transferSpaceQuery">
|
||||
<value>/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.transfers.childname}/${spaces.transfer_groups.childname}</value>
|
||||
</property>
|
||||
<property name="defaultTransferGroup">
|
||||
<value>Default Group</value>
|
||||
</property>
|
||||
<property name="transmitter" ref="transferTransmitter" />
|
||||
|
||||
<property name="transferManifestNodeFactory" ref="transferManifestNodeFactory" />
|
||||
<property name="transferManifestNodeFactory" ref="transferManifestNodeFactory" />
|
||||
<property name="transferReporter" ref="transferReporter" />
|
||||
|
||||
<property name="transferReporter" ref="transferReporter" />
|
||||
<!-- How long to wait while polling for commit status, in mS -->
|
||||
<property name="commitPollDelay">
|
||||
<value>2000</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</bean>
|
||||
|
||||
<bean id="transferTransmitter" class="org.alfresco.repo.transfer.HttpClientTransmitterImpl" init-method="init" >
|
||||
<property name="contentService" ref="ContentService" />
|
||||
</bean>
|
||||
<bean id="transferTransmitter" class="org.alfresco.repo.transfer.HttpClientTransmitterImpl"
|
||||
init-method="init">
|
||||
<property name="contentService" ref="ContentService" />
|
||||
</bean>
|
||||
|
||||
<bean id="transferReporter" class="org.alfresco.repo.transfer.report.TransferReporterImpl" init-method="init" >
|
||||
<property name="contentService" ref="ContentService" />
|
||||
@@ -39,86 +44,181 @@
|
||||
</bean>
|
||||
|
||||
<bean id="transferManifestNodeFactory" class="org.alfresco.repo.transfer.manifest.TransferManifestNodeFactoryImpl" init-method="init" >
|
||||
<property name="nodeService" ref="NodeService" />
|
||||
</bean>
|
||||
<property name="nodeService" ref="NodeService" />
|
||||
</bean>
|
||||
|
||||
|
||||
<bean id="transferReceiver" class="org.alfresco.repo.transfer.RepoTransferReceiverImpl" init-method="init">
|
||||
<property name="nodeService" ref="NodeService" />
|
||||
<property name="searchService" ref="SearchService" />
|
||||
<property name="transactionService" ref="TransactionService" />
|
||||
<property name="transferLockFolderPath"><value>/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.transfers.childname}</value></property>
|
||||
<property name="transferTempFolderPath"><value>/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.transfers.childname}/${spaces.transfer_temp.childname}</value></property>
|
||||
<property name="inboundTransferRecordsPath"><value>/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.transfers.childname}/${spaces.inbound_transfer_records.childname}</value></property>
|
||||
<property name="rootStagingDirectory"><value>${transferservice.receiver.stagingDir}</value></property>
|
||||
<bean id="transferReceiver" class="org.alfresco.repo.transfer.RepoTransferReceiverImpl"
|
||||
init-method="init">
|
||||
<property name="nodeService" ref="NodeService" />
|
||||
<property name="searchService" ref="SearchService" />
|
||||
<property name="transactionService" ref="TransactionService" />
|
||||
<property name="actionService" ref="ActionService" />
|
||||
|
||||
<property name="transferLockFolderPath">
|
||||
<value>/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.transfers.childname}</value>
|
||||
</property>
|
||||
<property name="transferTempFolderPath">
|
||||
<value>/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.transfers.childname}/${spaces.transfer_temp.childname}</value>
|
||||
</property>
|
||||
<property name="inboundTransferRecordsPath">
|
||||
<value>/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.transfers.childname}/${spaces.inbound_transfer_records.childname}</value>
|
||||
</property>
|
||||
<property name="rootStagingDirectory">
|
||||
<value>${transferservice.receiver.stagingDir}</value>
|
||||
</property>
|
||||
<property name="manifestProcessorFactory" ref="transferManifestProcessorFactory" />
|
||||
<property name="behaviourFilter" ref="policyBehaviourFilter" />
|
||||
</bean>
|
||||
<property name="behaviourFilter" ref="policyBehaviourFilter" />
|
||||
<property name="progressMonitor" ref="transferProgressMonitor" />
|
||||
</bean>
|
||||
|
||||
<bean id="transferManifestProcessorFactory" class="org.alfresco.repo.transfer.DefaultManifestProcessorFactoryImpl">
|
||||
<property name="nodeService" ref="NodeService" />
|
||||
<property name="contentService" ref="ContentService" />
|
||||
<property name="nodeResolverFactory" ref="transferNodeResolverFactory" />
|
||||
</bean>
|
||||
<bean id="transferProgressMonitor"
|
||||
class="org.alfresco.repo.transfer.LoggingTransferProgressMonitorImpl">
|
||||
<property name="delegate">
|
||||
<bean class="org.alfresco.repo.transfer.RepoTransferProgressMonitorImpl">
|
||||
<property name="nodeService" ref="NodeService" />
|
||||
<property name="contentService" ref="ContentService" />
|
||||
<property name="transactionService" ref="TransactionService" />
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="transferNodeResolverFactory" class="org.alfresco.repo.transfer.DefaultCorrespondingNodeResolverFactory">
|
||||
<property name="nodeService" ref="NodeService" />
|
||||
</bean>
|
||||
<bean id="commit-transfer" class="org.alfresco.repo.transfer.TransferCommitActionExecuter" parent="action-executer">
|
||||
<property name="receiver" ref="TransferReceiver" />
|
||||
<property name="publicAction">
|
||||
<value>false</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- I18N -->
|
||||
<bean id="transferServiceResourceBundles" class="org.alfresco.i18n.ResourceBundleBootstrapComponent">
|
||||
<property name="resourceBundles">
|
||||
<list>
|
||||
<value>alfresco.messages.transfer-service</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
<bean id="TransferService_security" class="org.alfresco.repo.security.permissions.impl.AlwaysProceedMethodInterceptor" />
|
||||
<bean id="transferManifestProcessorFactory"
|
||||
class="org.alfresco.repo.transfer.DefaultManifestProcessorFactoryImpl">
|
||||
<property name="nodeService" ref="NodeService" />
|
||||
<property name="contentService" ref="ContentService" />
|
||||
<property name="nodeResolverFactory" ref="transferNodeResolverFactory" />
|
||||
</bean>
|
||||
|
||||
<bean id="TransferService_transaction" class="org.springframework.transaction.interceptor.TransactionInterceptor">
|
||||
<property name="transactionManager">
|
||||
<ref bean="transactionManager"/>
|
||||
</property>
|
||||
<property name="transactionAttributes">
|
||||
<props>
|
||||
<prop key="*">${server.transaction.mode.default}</prop>
|
||||
</props>
|
||||
</property>
|
||||
</bean>
|
||||
<bean id="transferNodeResolverFactory"
|
||||
class="org.alfresco.repo.transfer.DefaultCorrespondingNodeResolverFactory">
|
||||
<property name="nodeService" ref="NodeService" />
|
||||
</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>
|
||||
<!-- I18N -->
|
||||
<bean id="transferServiceResourceBundles" class="org.alfresco.i18n.ResourceBundleBootstrapComponent">
|
||||
<property name="resourceBundles">
|
||||
<list>
|
||||
<value>alfresco.messages.transfer-service</value>
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
<bean id="TransferService_security"
|
||||
class="org.alfresco.repo.security.permissions.impl.AlwaysProceedMethodInterceptor" />
|
||||
|
||||
<!-- Action for transfer async -->
|
||||
<bean id="transfer-async" class="org.alfresco.repo.transfer.TransferAsyncAction" parent="action-executer">
|
||||
<bean id="TransferService_transaction"
|
||||
class="org.springframework.transaction.interceptor.TransactionInterceptor">
|
||||
<property name="transactionManager">
|
||||
<ref bean="transactionManager" />
|
||||
</property>
|
||||
<property name="transactionAttributes">
|
||||
<props>
|
||||
<prop key="*">${server.transaction.mode.default}</prop>
|
||||
</props>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Run transferAsyncAction on the deployment queue -->
|
||||
<property name="queueName">
|
||||
<value>deployment</value>
|
||||
</property>
|
||||
<property name="transferService">
|
||||
<ref bean="TransferService"/>
|
||||
</property>
|
||||
<property name="publicAction">
|
||||
<value>false</value>
|
||||
</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="TransferReceiver_security"
|
||||
class="org.alfresco.repo.security.permissions.impl.AlwaysProceedMethodInterceptor" />
|
||||
|
||||
<bean id="TransferReceiver_transaction"
|
||||
class="org.springframework.transaction.interceptor.TransactionInterceptor">
|
||||
<property name="transactionManager">
|
||||
<ref bean="transactionManager" />
|
||||
</property>
|
||||
<property name="transactionAttributes">
|
||||
<props>
|
||||
<prop key="*">${server.transaction.mode.default}</prop>
|
||||
</props>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Transfer service bean -->
|
||||
<bean id="TransferReceiver" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||
<property name="proxyInterfaces">
|
||||
<value>org.alfresco.service.cmr.transfer.TransferReceiver</value>
|
||||
</property>
|
||||
<property name="target">
|
||||
<ref bean="transferReceiver" />
|
||||
</property>
|
||||
<property name="interceptorNames">
|
||||
<list>
|
||||
<idref local="TransferReceiver_transaction" />
|
||||
<idref bean="AuditMethodInterceptor" />
|
||||
<idref bean="exceptionTranslator" />
|
||||
<idref local="TransferReceiver_security" />
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
|
||||
<bean id="transfer-async" class="org.alfresco.repo.transfer.TransferAsyncAction"
|
||||
parent="action-executer">
|
||||
|
||||
<!-- Run transferAsyncAction on the deployment queue -->
|
||||
<property name="queueName">
|
||||
<value>deployment</value>
|
||||
</property>
|
||||
<property name="transferService">
|
||||
<ref bean="TransferService" />
|
||||
</property>
|
||||
<property name="publicAction">
|
||||
<value>false</value>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="transfer-this-node" class="org.alfresco.repo.transfer.TransferOneNodeActionExecuter"
|
||||
parent="action-executer">
|
||||
<property name="transferService">
|
||||
<ref bean="TransferService" />
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="create-transfer-target" class="org.alfresco.repo.transfer.CreateTransferTargetActionExecuter"
|
||||
parent="action-executer">
|
||||
<property name="transferService">
|
||||
<ref bean="TransferService" />
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="transfer-this-tree" class="org.alfresco.repo.transfer.TransferTreeActionExecuter"
|
||||
parent="action-executer">
|
||||
<property name="transferService">
|
||||
<ref bean="TransferService" />
|
||||
</property>
|
||||
<property name="serviceRegistry" ref="ServiceRegistry" />
|
||||
</bean>
|
||||
|
||||
<bean id="transfer-tree-with-cancel" class="org.alfresco.repo.transfer.TransferTreeWithCancelActionExecuter"
|
||||
parent="action-executer">
|
||||
<property name="transferService">
|
||||
<ref bean="TransferService" />
|
||||
</property>
|
||||
<property name="serviceRegistry" ref="ServiceRegistry" />
|
||||
</bean>
|
||||
</beans>
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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<ParameterDefinition> paramList)
|
||||
{
|
||||
}
|
||||
}
|
@@ -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);
|
||||
|
@@ -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;
|
||||
@@ -555,6 +556,59 @@ public class HttpClientTransmitterImpl implements TransferTransmitter
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
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)
|
||||
{
|
||||
this.contentService = contentService;
|
||||
@@ -566,4 +620,6 @@ public class HttpClientTransmitterImpl implements TransferTransmitter
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // end of class
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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<NodeRef> crawledNodes = crawler.crawl(node8);
|
||||
|
@@ -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<QName, Serializable> 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<QName> aspects = new HashSet<QName>(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<ChildAssociationRef> 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<QName, Serializable> 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<QName, Serializable> existingProps = (nodeToUpdate == null) ? new HashMap<QName, Serializable>()
|
||||
: nodeService.getProperties(nodeToUpdate);
|
||||
|
||||
@@ -457,7 +463,7 @@ public class RepoPrimaryManifestProcessorImpl implements TransferManifestProcess
|
||||
*/
|
||||
private void writeContent(NodeRef nodeToUpdate, Map<QName, Serializable> contentProps)
|
||||
{
|
||||
File stagingDir = receiver.getStagingFolder(transferId);
|
||||
File stagingDir = getStagingFolder();
|
||||
for (Map.Entry<QName, Serializable> 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<QName, Serializable> 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<QName, Serializable> 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<QName, Serializable> 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<QName, Serializable> 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<ChildAssociationRef> 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()
|
||||
{
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@@ -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<String, WritableByteChannel> transferLogWriters = new TreeMap<String, WritableByteChannel>();
|
||||
|
||||
/*
|
||||
* (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<TransferProgress>()
|
||||
{
|
||||
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<Object>()
|
||||
{
|
||||
public NodeRef execute() throws Throwable
|
||||
{
|
||||
if (ex != null)
|
||||
{
|
||||
NodeRef nodeRef = getTransferRecord(transferId);
|
||||
// Write the exception onto the transfer record
|
||||
nodeService.setProperty(nodeRef, TransferModel.PROP_TRANSFER_ERROR, ex);
|
||||
}
|
||||
WritableByteChannel writer = getLogWriter(transferId);
|
||||
Date now = new Date();
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
|
||||
String text = format.format(now) + " - " + obj.toString() + "\n";
|
||||
if (ex != null)
|
||||
{
|
||||
text += ex.getMessage() + "\n";
|
||||
StringWriter stringWriter = new StringWriter(1024);
|
||||
PrintWriter errorWriter = new PrintWriter(stringWriter);
|
||||
ex.printStackTrace(errorWriter);
|
||||
text += stringWriter.toString();
|
||||
}
|
||||
try
|
||||
{
|
||||
ByteBuffer.wrap(text.getBytes("UTF-8"));
|
||||
writer.write(ByteBuffer.wrap(text.getBytes("UTF-8")));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (log.isWarnEnabled())
|
||||
{
|
||||
log.warn("Unable to record transfer log information:\n " + text, ex);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}, false, true);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.alfresco.repo.transfer.TransferProgressMonitor#updateProgress(java.lang.String, int)
|
||||
*/
|
||||
public void updateProgress(final String transferId, final int currPos)
|
||||
{
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(
|
||||
new RetryingTransactionHelper.RetryingTransactionCallback<Object>()
|
||||
{
|
||||
public NodeRef execute() throws Throwable
|
||||
{
|
||||
NodeRef nodeRef = getTransferRecord(transferId);
|
||||
testCancelled(nodeRef);
|
||||
nodeService.setProperty(nodeRef, TransferModel.PROP_PROGRESS_POSITION, new Integer(currPos));
|
||||
return null;
|
||||
}
|
||||
}, false, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.alfresco.repo.transfer.TransferProgressMonitor#updateProgress(java.lang.String, int, int)
|
||||
*/
|
||||
public void updateProgress(final String transferId, final int currPos, final int endPos)
|
||||
{
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(
|
||||
new RetryingTransactionHelper.RetryingTransactionCallback<Object>()
|
||||
{
|
||||
public NodeRef execute() throws Throwable
|
||||
{
|
||||
NodeRef nodeRef = getTransferRecord(transferId);
|
||||
testCancelled(nodeRef);
|
||||
nodeService.setProperty(nodeRef, TransferModel.PROP_PROGRESS_POSITION, new Integer(currPos));
|
||||
nodeService.setProperty(nodeRef, TransferModel.PROP_PROGRESS_ENDPOINT, new Integer(endPos));
|
||||
return null;
|
||||
}
|
||||
}, false, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.alfresco.repo.transfer.TransferProgressMonitor#updateStatus(java.lang.String,
|
||||
* org.alfresco.service.cmr.transfer.TransferProgress.Status)
|
||||
*/
|
||||
public void updateStatus(final String transferId, final Status status)
|
||||
{
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(
|
||||
new RetryingTransactionHelper.RetryingTransactionCallback<Object>()
|
||||
{
|
||||
public NodeRef execute() throws Throwable
|
||||
{
|
||||
NodeRef nodeRef = getTransferRecord(transferId);
|
||||
testCancelled(nodeRef);
|
||||
String currentStatusString = (String)nodeService.getProperty(nodeRef, TransferModel.PROP_TRANSFER_STATUS);
|
||||
Status currentStatus = Status.valueOf(currentStatusString);
|
||||
//If the transfer has already reached a terminal state then we don't allow any further change
|
||||
if (!TransferProgress.getTerminalStatuses().contains(currentStatus))
|
||||
{
|
||||
log(transferId, "Status update: " + status);
|
||||
nodeService.setProperty(nodeRef, TransferModel.PROP_TRANSFER_STATUS, status.toString());
|
||||
//If the transfer has now reached a terminal state then the make sure that the log channel is
|
||||
//closed for it (if one was open).
|
||||
if (TransferProgress.getTerminalStatuses().contains(status))
|
||||
{
|
||||
WritableByteChannel logChannel = transferLogWriters.remove(transferId);
|
||||
if (logChannel != null)
|
||||
{
|
||||
logChannel.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}, false, true);
|
||||
}
|
||||
|
||||
private void testCancelled(NodeRef transferRecord) throws TransferFatalException
|
||||
{
|
||||
Status currentStatus = Status.valueOf((String)nodeService.getProperty(transferRecord, TransferModel.PROP_TRANSFER_STATUS));
|
||||
if (Status.CANCELLED.equals(currentStatus))
|
||||
{
|
||||
throw new TransferFatalException(MSG_TRANSFER_CANCELLED, new Object[] { transferRecord.toString() });
|
||||
}
|
||||
}
|
||||
|
||||
private NodeRef getTransferRecord(String transferId) throws TransferException
|
||||
{
|
||||
NodeRef nodeRef = new NodeRef(transferId);
|
||||
if (!nodeService.exists(nodeRef) || !nodeService.getType(nodeRef).equals(TransferModel.TYPE_TRANSFER_RECORD))
|
||||
{
|
||||
throw new TransferException(MSG_TRANSFER_NOT_FOUND, new Object[] { transferId });
|
||||
}
|
||||
return nodeRef;
|
||||
}
|
||||
|
||||
private WritableByteChannel getLogWriter(String transferId)
|
||||
{
|
||||
WritableByteChannel channel = this.transferLogWriters.get(transferId);
|
||||
if (channel == null)
|
||||
{
|
||||
NodeRef node = new NodeRef(transferId);
|
||||
ContentWriter writer = contentService.getWriter(node, ContentModel.PROP_CONTENT, true);
|
||||
writer.setMimetype("text/plain");
|
||||
channel = writer.getWritableChannel();
|
||||
transferLogWriters.put(transferId, channel);
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nodeService
|
||||
* the nodeService to set
|
||||
*/
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param contentService
|
||||
* the contentService to set
|
||||
*/
|
||||
public void setContentService(ContentService contentService)
|
||||
{
|
||||
this.contentService = contentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param transactionService
|
||||
* the transactionService to set
|
||||
*/
|
||||
public void setTransactionService(TransactionService transactionService)
|
||||
{
|
||||
this.transactionService = transactionService;
|
||||
}
|
||||
}
|
@@ -41,9 +41,15 @@ import javax.xml.parsers.SAXParserFactory;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.policy.BehaviourFilter;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.repo.transfer.manifest.TransferManifestProcessor;
|
||||
import org.alfresco.repo.transfer.manifest.XMLTransferManifestReader;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.action.ActionService;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
@@ -52,7 +58,9 @@ 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.TransferException;
|
||||
import org.alfresco.service.cmr.transfer.TransferProgress;
|
||||
import org.alfresco.service.cmr.transfer.TransferReceiver;
|
||||
import org.alfresco.service.cmr.transfer.TransferProgress.Status;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
@@ -68,6 +76,46 @@ import org.springframework.util.FileCopyUtils;
|
||||
*/
|
||||
public class RepoTransferReceiverImpl implements TransferReceiver
|
||||
{
|
||||
/**
|
||||
* This embedded class is used to push requests for asynchronous commits onto a different thread
|
||||
*
|
||||
* @author Brian
|
||||
*
|
||||
*/
|
||||
public class AsyncCommitCommand implements Runnable
|
||||
{
|
||||
|
||||
private String transferId;
|
||||
private String runAsUser;
|
||||
|
||||
public AsyncCommitCommand(String transferId)
|
||||
{
|
||||
this.transferId = transferId;
|
||||
this.runAsUser = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
RunAsWork<Object> actionRunAs = new RunAsWork<Object>()
|
||||
{
|
||||
public Object doWork() throws Exception
|
||||
{
|
||||
return transactionService.getRetryingTransactionHelper().doInTransaction(
|
||||
new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
public Object execute()
|
||||
{
|
||||
commit(transferId);
|
||||
return null;
|
||||
}
|
||||
}, false, true);
|
||||
}
|
||||
};
|
||||
AuthenticationUtil.runAs(actionRunAs, runAsUser);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final static Log log = LogFactory.getLog(RepoTransferReceiverImpl.class);
|
||||
|
||||
private static final String MSG_FAILED_TO_CREATE_STAGING_FOLDER = "transfer_service.receiver.failed_to_create_staging_folder";
|
||||
@@ -95,7 +143,8 @@ public class RepoTransferReceiverImpl implements TransferReceiver
|
||||
private String transferTempFolderPath;
|
||||
private ManifestProcessorFactory manifestProcessorFactory;
|
||||
private BehaviourFilter behaviourFilter;
|
||||
|
||||
private TransferProgressMonitor progressMonitor;
|
||||
private ActionService actionService;
|
||||
|
||||
private NodeRef transferLockFolder;
|
||||
private NodeRef transferTempFolder;
|
||||
@@ -133,7 +182,7 @@ public class RepoTransferReceiverImpl implements TransferReceiver
|
||||
if (!tempFolder.mkdirs())
|
||||
{
|
||||
tempFolder = null;
|
||||
throw new TransferException(MSG_FAILED_TO_CREATE_STAGING_FOLDER, new Object[] {transferId});
|
||||
throw new TransferException(MSG_FAILED_TO_CREATE_STAGING_FOLDER, new Object[] { transferId });
|
||||
}
|
||||
}
|
||||
return tempFolder;
|
||||
@@ -151,13 +200,15 @@ public class RepoTransferReceiverImpl implements TransferReceiver
|
||||
if (transferLockFolder == null)
|
||||
{
|
||||
ResultSet rs = searchService.query(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE,
|
||||
SearchService.LANGUAGE_LUCENE, "PATH:\"" + transferLockFolderPath + "\"");
|
||||
SearchService.LANGUAGE_XPATH, transferLockFolderPath);
|
||||
if (rs.length() > 0)
|
||||
{
|
||||
transferLockFolder = rs.getNodeRef(0);
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new TransferException(MSG_TRANSFER_LOCK_FOLDER_NOT_FOUND, new Object[] {transferLockFolderPath});
|
||||
throw new TransferException(MSG_TRANSFER_LOCK_FOLDER_NOT_FOUND,
|
||||
new Object[] { transferLockFolderPath });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -177,13 +228,15 @@ public class RepoTransferReceiverImpl implements TransferReceiver
|
||||
if (transferTempFolder == null)
|
||||
{
|
||||
ResultSet rs = searchService.query(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE,
|
||||
SearchService.LANGUAGE_LUCENE, "PATH:\"" + transferTempFolderPath + "\"");
|
||||
SearchService.LANGUAGE_XPATH, transferTempFolderPath);
|
||||
if (rs.length() > 0)
|
||||
{
|
||||
transferTempFolder = rs.getNodeRef(0);
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new TransferException(MSG_TRANSFER_TEMP_FOLDER_NOT_FOUND, new Object[] {transferId, transferTempFolderPath});
|
||||
throw new TransferException(MSG_TRANSFER_TEMP_FOLDER_NOT_FOUND, new Object[] { transferId,
|
||||
transferTempFolderPath });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,8 +256,9 @@ public class RepoTransferReceiverImpl implements TransferReceiver
|
||||
Map<QName, Serializable> props = new HashMap<QName, Serializable>();
|
||||
props.put(ContentModel.PROP_NAME, tempTransferFolderName);
|
||||
tempFolderNode = nodeService.createNode(transferTempFolder, ContentModel.ASSOC_CONTAINS, folderName,
|
||||
ContentModel.TYPE_FOLDER, props).getChildRef();
|
||||
} else
|
||||
TransferModel.TYPE_TEMP_TRANSFER_STORE, props).getChildRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Yes, we do have a temp folder for this transfer already. Return it.
|
||||
tempFolderNode = tempChildren.get(0).getChildRef();
|
||||
@@ -220,28 +274,40 @@ public class RepoTransferReceiverImpl implements TransferReceiver
|
||||
*/
|
||||
public String start()
|
||||
{
|
||||
log.debug("start");
|
||||
final NodeRef relatedTransferRecord = createTransferRecord();
|
||||
final NodeRef lockFolder = getLockFolder();
|
||||
NodeRef relatedTransferRecord = null;
|
||||
|
||||
RetryingTransactionHelper txHelper = transactionService.getRetryingTransactionHelper();
|
||||
try
|
||||
{
|
||||
txHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<NodeRef>()
|
||||
{
|
||||
public NodeRef execute() throws Throwable
|
||||
{
|
||||
Map<QName, Serializable> props = new HashMap<QName, Serializable>();
|
||||
props.put(ContentModel.PROP_NAME, LOCK_FILE_NAME);
|
||||
props.put(TransferModel.PROP_TRANSFER_ID, relatedTransferRecord.toString());
|
||||
relatedTransferRecord = txHelper.doInTransaction(
|
||||
new RetryingTransactionHelper.RetryingTransactionCallback<NodeRef>()
|
||||
{
|
||||
public NodeRef execute() throws Throwable
|
||||
{
|
||||
final NodeRef relatedTransferRecord = createTransferRecord();
|
||||
getTempFolder(relatedTransferRecord.toString());
|
||||
|
||||
log.error("Creating transfer lock associated with this transfer record: " + relatedTransferRecord);
|
||||
ChildAssociationRef assoc = nodeService.createNode(lockFolder, ContentModel.ASSOC_CONTAINS,
|
||||
LOCK_QNAME, TransferModel.TYPE_TRANSFER_LOCK, props);
|
||||
log.error("Transfer lock created as node " + assoc.getChildRef());
|
||||
return assoc.getChildRef();
|
||||
}
|
||||
}, false, true);
|
||||
Map<QName, Serializable> props = new HashMap<QName, Serializable>();
|
||||
props.put(ContentModel.PROP_NAME, LOCK_FILE_NAME);
|
||||
props.put(TransferModel.PROP_TRANSFER_ID, relatedTransferRecord.toString());
|
||||
|
||||
if (log.isInfoEnabled())
|
||||
{
|
||||
log.info("Creating transfer lock associated with this transfer record: "
|
||||
+ relatedTransferRecord);
|
||||
}
|
||||
|
||||
ChildAssociationRef assoc = nodeService.createNode(lockFolder, ContentModel.ASSOC_CONTAINS,
|
||||
LOCK_QNAME, TransferModel.TYPE_TRANSFER_LOCK, props);
|
||||
|
||||
if (log.isInfoEnabled())
|
||||
{
|
||||
log.info("Transfer lock created as node " + assoc.getChildRef());
|
||||
}
|
||||
return relatedTransferRecord;
|
||||
}
|
||||
}, false, true);
|
||||
}
|
||||
catch (DuplicateChildNodeNameException ex)
|
||||
{
|
||||
@@ -268,28 +334,33 @@ public class RepoTransferReceiverImpl implements TransferReceiver
|
||||
{
|
||||
log.debug("Trying to find transfer records folder: " + inboundTransferRecordsPath);
|
||||
ResultSet rs = searchService.query(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE,
|
||||
SearchService.LANGUAGE_LUCENE, "PATH:\"" + inboundTransferRecordsPath + "\"");
|
||||
SearchService.LANGUAGE_XPATH, inboundTransferRecordsPath);
|
||||
if (rs.length() > 0)
|
||||
{
|
||||
inboundTransferRecordsFolder = rs.getNodeRef(0);
|
||||
log.debug("Found inbound transfer records folder: " + inboundTransferRecordsFolder);
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new TransferException(MSG_INBOUND_TRANSFER_FOLDER_NOT_FOUND, new Object[] {inboundTransferRecordsPath});
|
||||
throw new TransferException(MSG_INBOUND_TRANSFER_FOLDER_NOT_FOUND,
|
||||
new Object[] { inboundTransferRecordsPath });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmssSSSZ");
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmssSSSZ");
|
||||
String timeNow = format.format(new Date());
|
||||
QName recordName = QName.createQName(NamespaceService.APP_MODEL_1_0_URI, timeNow);
|
||||
|
||||
Map<QName, Serializable> props = new HashMap<QName, Serializable>();
|
||||
props.put(ContentModel.PROP_NAME, timeNow);
|
||||
props.put(TransferModel.PROP_PROGRESS_POSITION, 0);
|
||||
props.put(TransferModel.PROP_PROGRESS_ENDPOINT, 1);
|
||||
props.put(TransferModel.PROP_TRANSFER_STATUS, TransferProgress.Status.PRE_COMMIT.toString());
|
||||
|
||||
log.debug("Creating transfer record with name: " + timeNow);
|
||||
ChildAssociationRef assoc = nodeService.createNode(inboundTransferRecordsFolder, ContentModel.ASSOC_CONTAINS,
|
||||
recordName, ContentModel.TYPE_CONTENT, props);
|
||||
recordName, TransferModel.TYPE_TRANSFER_RECORD, props);
|
||||
log.debug("<-createTransferRecord: " + assoc.getChildRef());
|
||||
return assoc.getChildRef();
|
||||
}
|
||||
@@ -301,7 +372,10 @@ public class RepoTransferReceiverImpl implements TransferReceiver
|
||||
*/
|
||||
public void end(final String transferId)
|
||||
{
|
||||
log.debug("end transferId:" + transferId);
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("Request to end transfer " + transferId);
|
||||
}
|
||||
if (transferId == null)
|
||||
{
|
||||
throw new IllegalArgumentException("transferId = " + transferId);
|
||||
@@ -321,12 +395,12 @@ public class RepoTransferReceiverImpl implements TransferReceiver
|
||||
{
|
||||
if (!testLockedTransfer(lockId, transferId))
|
||||
{
|
||||
throw new TransferException(MSG_NOT_LOCK_OWNER, new Object[] {transferId});
|
||||
throw new TransferException(MSG_NOT_LOCK_OWNER, new Object[] { transferId });
|
||||
}
|
||||
// Delete the lock node.
|
||||
log.debug("delete lock node :" + lockId);
|
||||
nodeService.deleteNode(lockId);
|
||||
|
||||
log.debug("lock deleted :" + lockId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -347,10 +421,14 @@ public class RepoTransferReceiverImpl implements TransferReceiver
|
||||
}
|
||||
}
|
||||
|
||||
public void abort(String transferId) throws TransferException
|
||||
public void cancel(String transferId) throws TransferException
|
||||
{
|
||||
//TODO Think about the relationship between abort and end.
|
||||
end(transferId);
|
||||
TransferProgress progress = getProgressMonitor().getProgress(transferId);
|
||||
getProgressMonitor().updateStatus(transferId, TransferProgress.Status.CANCELLED);
|
||||
if (progress.getStatus().equals(TransferProgress.Status.PRE_COMMIT))
|
||||
{
|
||||
end(transferId);
|
||||
}
|
||||
}
|
||||
|
||||
public void prepare(String transferId) throws TransferException
|
||||
@@ -362,11 +440,15 @@ public class RepoTransferReceiverImpl implements TransferReceiver
|
||||
*/
|
||||
private void deleteFile(File file)
|
||||
{
|
||||
if (!file.isDirectory()) file.delete();
|
||||
File[] fileList = file.listFiles();
|
||||
if (fileList != null) {
|
||||
for (File currentFile : fileList) {
|
||||
deleteFile(currentFile);
|
||||
if (file.isDirectory())
|
||||
{
|
||||
File[] fileList = file.listFiles();
|
||||
if (fileList != null)
|
||||
{
|
||||
for (File currentFile : fileList)
|
||||
{
|
||||
deleteFile(currentFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
file.delete();
|
||||
@@ -432,9 +514,13 @@ public class RepoTransferReceiverImpl implements TransferReceiver
|
||||
*/
|
||||
public void saveSnapshot(String transferId, InputStream openStream) throws TransferException
|
||||
{
|
||||
log.debug("save snapshot transferId=" + transferId);
|
||||
// Check that this transfer owns the lock and give it a nudge to stop it expiring
|
||||
nudgeLock(transferId);
|
||||
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("Saving snapshot for transferId =" + transferId);
|
||||
}
|
||||
File snapshotFile = new File(getStagingFolder(transferId), SNAPSHOT_FILE_NAME);
|
||||
try
|
||||
{
|
||||
@@ -442,7 +528,10 @@ public class RepoTransferReceiverImpl implements TransferReceiver
|
||||
{
|
||||
FileCopyUtils.copy(openStream, new FileOutputStream(snapshotFile));
|
||||
}
|
||||
log.debug("saved snapshot for transferId=" + transferId);
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("Saved snapshot for transferId =" + transferId);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -474,60 +563,110 @@ public class RepoTransferReceiverImpl implements TransferReceiver
|
||||
}
|
||||
}
|
||||
|
||||
public void commit(String transferId) throws TransferException
|
||||
public void commitAsync(String transferId)
|
||||
{
|
||||
log.debug("commit transferId=" + transferId);
|
||||
nudgeLock(transferId);
|
||||
progressMonitor.updateStatus(transferId, Status.COMMIT_REQUESTED);
|
||||
Action commitAction = actionService.createAction(TransferCommitActionExecuter.NAME);
|
||||
commitAction.setParameterValue(TransferCommitActionExecuter.PARAM_TRANSFER_ID, transferId);
|
||||
commitAction.setExecuteAsynchronously(true);
|
||||
actionService.executeAction(commitAction, new NodeRef(transferId));
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("Registered transfer commit for asynchronous execution: " + transferId);
|
||||
}
|
||||
}
|
||||
|
||||
public void commit(final String transferId) throws TransferException
|
||||
{
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("Committing transferId=" + transferId);
|
||||
}
|
||||
try
|
||||
{
|
||||
nudgeLock(transferId);
|
||||
List<TransferManifestProcessor> commitProcessors = manifestProcessorFactory.getCommitProcessors(this, transferId);
|
||||
progressMonitor.updateStatus(transferId, Status.COMMITTING);
|
||||
|
||||
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
|
||||
SAXParser parser = saxParserFactory.newSAXParser();
|
||||
File snapshotFile = getSnapshotFile(transferId);
|
||||
|
||||
if (snapshotFile.exists())
|
||||
RetryingTransactionHelper.RetryingTransactionCallback<Object> commitWork = new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
log.debug("processing manifest file:" + snapshotFile.getAbsolutePath());
|
||||
//We parse the file as many times as we have processors
|
||||
for (TransferManifestProcessor processor : commitProcessors)
|
||||
public Object execute() throws Throwable
|
||||
{
|
||||
XMLTransferManifestReader reader = new XMLTransferManifestReader(processor);
|
||||
behaviourFilter.disableBehaviour(ContentModel.ASPECT_AUDITABLE);
|
||||
try
|
||||
AlfrescoTransactionSupport.bindListener(new TransferCommitTransactionListener(transferId,
|
||||
RepoTransferReceiverImpl.this));
|
||||
|
||||
List<TransferManifestProcessor> commitProcessors = manifestProcessorFactory.getCommitProcessors(
|
||||
RepoTransferReceiverImpl.this, transferId);
|
||||
|
||||
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
|
||||
SAXParser parser = saxParserFactory.newSAXParser();
|
||||
File snapshotFile = getSnapshotFile(transferId);
|
||||
|
||||
if (snapshotFile.exists())
|
||||
{
|
||||
parser.parse(snapshotFile, reader);
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("Processing manifest file:" + snapshotFile.getAbsolutePath());
|
||||
}
|
||||
// We parse the file as many times as we have processors
|
||||
for (TransferManifestProcessor processor : commitProcessors)
|
||||
{
|
||||
XMLTransferManifestReader reader = new XMLTransferManifestReader(processor);
|
||||
behaviourFilter.disableBehaviour(ContentModel.ASPECT_AUDITABLE);
|
||||
try
|
||||
{
|
||||
parser.parse(snapshotFile, reader);
|
||||
}
|
||||
finally
|
||||
{
|
||||
behaviourFilter.enableBehaviour(ContentModel.ASPECT_AUDITABLE);
|
||||
}
|
||||
nudgeLock(transferId);
|
||||
parser.reset();
|
||||
}
|
||||
}
|
||||
finally
|
||||
else
|
||||
{
|
||||
behaviourFilter.enableBehaviour(ContentModel.ASPECT_AUDITABLE);
|
||||
progressMonitor.log(transferId, "Unable to start commit. No snapshot file received",
|
||||
new TransferException(MSG_NO_SNAPSHOT_RECEIVED));
|
||||
}
|
||||
nudgeLock(transferId);
|
||||
parser.reset();
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(commitWork, false, true);
|
||||
|
||||
Throwable error = progressMonitor.getProgress(transferId).getError();
|
||||
if (error != null)
|
||||
{
|
||||
if (TransferException.class.isAssignableFrom(error.getClass()))
|
||||
{
|
||||
throw (TransferException) error;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new TransferException(MSG_ERROR_WHILE_COMMITTING_TRANSFER, error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log.debug("no snapshot received");
|
||||
throw new TransferException(MSG_NO_SNAPSHOT_RECEIVED);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Successfully transfred
|
||||
* Successfully committed
|
||||
*/
|
||||
log.debug("commit success transferId=" + transferId);
|
||||
|
||||
}
|
||||
catch (TransferException ex)
|
||||
{
|
||||
log.debug("unable to commit", ex);
|
||||
throw ex;
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("Commit success transferId=" + transferId);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.debug("unable to commit", ex);
|
||||
throw new TransferException(MSG_ERROR_WHILE_COMMITTING_TRANSFER, ex);
|
||||
if (TransferException.class.isAssignableFrom(ex.getClass()))
|
||||
{
|
||||
throw (TransferException) ex;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new TransferException(MSG_ERROR_WHILE_COMMITTING_TRANSFER, ex);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -547,6 +686,11 @@ public class RepoTransferReceiverImpl implements TransferReceiver
|
||||
}
|
||||
}
|
||||
|
||||
public TransferProgress getStatus(String transferId) throws TransferException
|
||||
{
|
||||
return getProgressMonitor().getProgress(transferId);
|
||||
}
|
||||
|
||||
private File getSnapshotFile(String transferId)
|
||||
{
|
||||
return new File(getStagingFolder(transferId), SNAPSHOT_FILE_NAME);
|
||||
@@ -580,7 +724,8 @@ public class RepoTransferReceiverImpl implements TransferReceiver
|
||||
}
|
||||
|
||||
/**
|
||||
* @param transferTempFolderPath the transferTempFolderPath to set
|
||||
* @param transferTempFolderPath
|
||||
* the transferTempFolderPath to set
|
||||
*/
|
||||
public void setTransferTempFolderPath(String transferTempFolderPath)
|
||||
{
|
||||
@@ -615,7 +760,8 @@ public class RepoTransferReceiverImpl implements TransferReceiver
|
||||
}
|
||||
|
||||
/**
|
||||
* @param manifestProcessorFactory the manifestProcessorFactory to set
|
||||
* @param manifestProcessorFactory
|
||||
* the manifestProcessorFactory to set
|
||||
*/
|
||||
public void setManifestProcessorFactory(ManifestProcessorFactory manifestProcessorFactory)
|
||||
{
|
||||
@@ -623,11 +769,34 @@ public class RepoTransferReceiverImpl implements TransferReceiver
|
||||
}
|
||||
|
||||
/**
|
||||
* @param behaviourFilter the behaviourFilter to set
|
||||
* @param behaviourFilter
|
||||
* the behaviourFilter to set
|
||||
*/
|
||||
public void setBehaviourFilter(BehaviourFilter behaviourFilter)
|
||||
{
|
||||
this.behaviourFilter = behaviourFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the progressMonitor
|
||||
*/
|
||||
public TransferProgressMonitor getProgressMonitor()
|
||||
{
|
||||
return progressMonitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param progressMonitor
|
||||
* the progressMonitor to set
|
||||
*/
|
||||
public void setProgressMonitor(TransferProgressMonitor progressMonitor)
|
||||
{
|
||||
this.progressMonitor = progressMonitor;
|
||||
}
|
||||
|
||||
public void setActionService(ActionService actionService)
|
||||
{
|
||||
this.actionService = actionService;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -38,31 +38,42 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
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.XMLTransferManifestWriter;
|
||||
import org.alfresco.service.cmr.action.ActionService;
|
||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.Path;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.security.MutableAuthenticationService;
|
||||
import org.alfresco.service.cmr.transfer.TransferException;
|
||||
import org.alfresco.service.cmr.transfer.TransferProgress;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.BaseAlfrescoSpringTest;
|
||||
import org.alfresco.util.GUID;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.tools.ant.filters.StringInputStream;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
|
||||
/**
|
||||
* Unit test for RepoTransferReceiverImpl
|
||||
*
|
||||
* @author Brian Remmington
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
// It's a test
|
||||
public class RepoTransferReceiverImplTest extends BaseAlfrescoSpringTest
|
||||
{
|
||||
private static int fileCount = 0;
|
||||
@@ -72,144 +83,230 @@ public class RepoTransferReceiverImplTest extends BaseAlfrescoSpringTest
|
||||
private String dummyContent;
|
||||
private byte[] dummyContentBytes;
|
||||
|
||||
@Override
|
||||
public void runBare() throws Throwable
|
||||
{
|
||||
preventTransaction();
|
||||
super.runBare();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called during the transaction setup
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
protected void onSetUpInTransaction() throws Exception
|
||||
protected void onSetUp() throws Exception
|
||||
{
|
||||
super.onSetUp();
|
||||
System.out.println("java.io.tmpdir == " + System.getProperty("java.io.tmpdir"));
|
||||
super.onSetUpInTransaction();
|
||||
|
||||
// Get the required services
|
||||
this.nodeService = (NodeService) this.applicationContext.getBean("nodeService");
|
||||
this.contentService = (ContentService) this.applicationContext.getBean("contentService");
|
||||
this.authenticationService = (MutableAuthenticationService) this.applicationContext
|
||||
.getBean("authenticationService");
|
||||
this.actionService = (ActionService) this.applicationContext.getBean("actionService");
|
||||
this.transactionService = (TransactionService) this.applicationContext.getBean("transactionComponent");
|
||||
this.authenticationComponent = (AuthenticationComponent) this.applicationContext
|
||||
.getBean("authenticationComponent");
|
||||
this.receiver = (RepoTransferReceiverImpl) this.getApplicationContext().getBean("transferReceiver");
|
||||
this.dummyContent = "This is some dummy content.";
|
||||
this.dummyContentBytes = dummyContent.getBytes("UTF-8");
|
||||
setTransactionDefinition(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW));
|
||||
authenticationComponent.setSystemUserAsCurrentUser();
|
||||
}
|
||||
|
||||
public void testStartAndEnd() throws Exception
|
||||
{
|
||||
String transferId = receiver.start();
|
||||
System.out.println("TransferId == " + transferId);
|
||||
|
||||
File stagingFolder = receiver.getStagingFolder(transferId);
|
||||
assertTrue(receiver.getStagingFolder(transferId).exists());
|
||||
|
||||
log.info("testStartAndEnd");
|
||||
startNewTransaction();
|
||||
try
|
||||
{
|
||||
receiver.start();
|
||||
fail("Successfully started twice!");
|
||||
} catch (TransferException ex)
|
||||
{
|
||||
// Expected
|
||||
}
|
||||
try
|
||||
{
|
||||
receiver.end(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, GUID.generate()).toString());
|
||||
fail("Successfully ended with transfer id that doesn't own lock.");
|
||||
} catch (TransferException ex)
|
||||
{
|
||||
// Expected
|
||||
}
|
||||
receiver.end(transferId);
|
||||
assertFalse(stagingFolder.exists());
|
||||
String transferId = receiver.start();
|
||||
System.out.println("TransferId == " + transferId);
|
||||
|
||||
receiver.end(receiver.start());
|
||||
File stagingFolder = receiver.getStagingFolder(transferId);
|
||||
assertTrue(receiver.getStagingFolder(transferId).exists());
|
||||
|
||||
try
|
||||
{
|
||||
receiver.start();
|
||||
fail("Successfully started twice!");
|
||||
}
|
||||
catch (TransferException ex)
|
||||
{
|
||||
// Expected
|
||||
}
|
||||
try
|
||||
{
|
||||
receiver.end(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, GUID.generate()).toString());
|
||||
fail("Successfully ended with transfer id that doesn't own lock.");
|
||||
}
|
||||
catch (TransferException ex)
|
||||
{
|
||||
// Expected
|
||||
}
|
||||
receiver.end(transferId);
|
||||
assertFalse(stagingFolder.exists());
|
||||
|
||||
receiver.end(receiver.start());
|
||||
}
|
||||
finally
|
||||
{
|
||||
endTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
public void testSaveContent() throws Exception
|
||||
{
|
||||
String transferId = receiver.start();
|
||||
log.info("testSaveContent");
|
||||
startNewTransaction();
|
||||
try
|
||||
{
|
||||
String contentId = "mytestcontent";
|
||||
receiver.saveContent(transferId, contentId, new ByteArrayInputStream(dummyContentBytes));
|
||||
File contentFile = new File(receiver.getStagingFolder(transferId), contentId);
|
||||
assertTrue(contentFile.exists());
|
||||
assertEquals(dummyContentBytes.length, contentFile.length());
|
||||
} finally
|
||||
String transferId = receiver.start();
|
||||
try
|
||||
{
|
||||
String contentId = "mytestcontent";
|
||||
receiver.saveContent(transferId, contentId, new ByteArrayInputStream(dummyContentBytes));
|
||||
File contentFile = new File(receiver.getStagingFolder(transferId), contentId);
|
||||
assertTrue(contentFile.exists());
|
||||
assertEquals(dummyContentBytes.length, contentFile.length());
|
||||
}
|
||||
finally
|
||||
{
|
||||
receiver.end(transferId);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
receiver.end(transferId);
|
||||
endTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
public void testSaveSnapshot() throws Exception
|
||||
{
|
||||
String transferId = receiver.start();
|
||||
File snapshotFile = null;
|
||||
log.info("testSaveSnapshot");
|
||||
startNewTransaction();
|
||||
try
|
||||
{
|
||||
TransferManifestNode node = createContentNode(transferId);
|
||||
List<TransferManifestNode> nodes = new ArrayList<TransferManifestNode>();
|
||||
nodes.add(node);
|
||||
String snapshot = createSnapshot(nodes);
|
||||
String transferId = receiver.start();
|
||||
File snapshotFile = null;
|
||||
try
|
||||
{
|
||||
TransferManifestNode node = createContentNode(transferId);
|
||||
List<TransferManifestNode> nodes = new ArrayList<TransferManifestNode>();
|
||||
nodes.add(node);
|
||||
String snapshot = createSnapshot(nodes);
|
||||
|
||||
receiver.saveSnapshot(transferId, new StringInputStream(snapshot, "UTF-8"));
|
||||
receiver.saveSnapshot(transferId, new StringInputStream(snapshot, "UTF-8"));
|
||||
|
||||
File stagingFolder = receiver.getStagingFolder(transferId);
|
||||
snapshotFile = new File(stagingFolder, "snapshot.xml");
|
||||
assertTrue(snapshotFile.exists());
|
||||
assertEquals(snapshot.getBytes("UTF-8").length, snapshotFile.length());
|
||||
} finally
|
||||
{
|
||||
receiver.end(transferId);
|
||||
if (snapshotFile != null) {
|
||||
assertFalse(snapshotFile.exists());
|
||||
File stagingFolder = receiver.getStagingFolder(transferId);
|
||||
snapshotFile = new File(stagingFolder, "snapshot.xml");
|
||||
assertTrue(snapshotFile.exists());
|
||||
assertEquals(snapshot.getBytes("UTF-8").length, snapshotFile.length());
|
||||
}
|
||||
finally
|
||||
{
|
||||
receiver.end(transferId);
|
||||
if (snapshotFile != null)
|
||||
{
|
||||
assertFalse(snapshotFile.exists());
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
endTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
public void testBasicCommit() throws Exception {
|
||||
String transferId = receiver.start();
|
||||
public void testBasicCommit() throws Exception
|
||||
{
|
||||
log.info("testBasicCommit");
|
||||
startNewTransaction();
|
||||
TransferManifestNode node = null;
|
||||
|
||||
try
|
||||
{
|
||||
TransferManifestNode node = createContentNode(transferId);
|
||||
List<TransferManifestNode> nodes = new ArrayList<TransferManifestNode>();
|
||||
nodes.add(node);
|
||||
String snapshot = createSnapshot(nodes);
|
||||
String transferId = receiver.start();
|
||||
try
|
||||
{
|
||||
node = createContentNode(transferId);
|
||||
List<TransferManifestNode> nodes = new ArrayList<TransferManifestNode>();
|
||||
nodes.add(node);
|
||||
String snapshot = createSnapshot(nodes);
|
||||
|
||||
receiver.saveSnapshot(transferId, new StringInputStream(snapshot, "UTF-8"));
|
||||
receiver.saveContent(transferId, node.getUuid(), new ByteArrayInputStream(dummyContentBytes));
|
||||
receiver.commit(transferId);
|
||||
receiver.saveSnapshot(transferId, new StringInputStream(snapshot, "UTF-8"));
|
||||
receiver.saveContent(transferId, node.getUuid(), new ByteArrayInputStream(dummyContentBytes));
|
||||
receiver.commit(transferId);
|
||||
|
||||
assertTrue(nodeService.exists(node.getNodeRef()));
|
||||
nodeService.deleteNode(node.getNodeRef());
|
||||
} catch (Exception ex)
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
receiver.end(transferId);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
receiver.end(transferId);
|
||||
throw ex;
|
||||
endTransaction();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void testMoreComplexCommit() throws Exception {
|
||||
String transferId = receiver.start();
|
||||
startNewTransaction();
|
||||
try
|
||||
{
|
||||
List<TransferManifestNode> nodes = new ArrayList<TransferManifestNode>();
|
||||
TransferManifestNormalNode node1 = createContentNode(transferId);
|
||||
assertTrue(nodeService.exists(node.getNodeRef()));
|
||||
nodeService.deleteNode(node.getNodeRef());
|
||||
}
|
||||
finally
|
||||
{
|
||||
endTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
public void testMoreComplexCommit() throws Exception
|
||||
{
|
||||
log.info("testMoreComplexCommit");
|
||||
List<TransferManifestNode> nodes = new ArrayList<TransferManifestNode>();
|
||||
TransferManifestNormalNode node1 = null;
|
||||
TransferManifestNormalNode node2 = null;
|
||||
TransferManifestNode node3 = null;
|
||||
TransferManifestNode node4 = null;
|
||||
TransferManifestNode node5 = null;
|
||||
TransferManifestNode node6 = null;
|
||||
TransferManifestNode node7 = null;
|
||||
TransferManifestNode node8 = null;
|
||||
TransferManifestNode node9 = null;
|
||||
TransferManifestNode node10 = null;
|
||||
TransferManifestNormalNode node11 = null;
|
||||
TransferManifestNode node12 = null;
|
||||
String transferId = null;
|
||||
|
||||
startNewTransaction();
|
||||
try
|
||||
{
|
||||
transferId = receiver.start();
|
||||
node1 = createContentNode(transferId);
|
||||
nodes.add(node1);
|
||||
TransferManifestNormalNode node2 = createContentNode(transferId);
|
||||
node2 = createContentNode(transferId);
|
||||
nodes.add(node2);
|
||||
TransferManifestNode node3 = createContentNode(transferId);
|
||||
node3 = createContentNode(transferId);
|
||||
nodes.add(node3);
|
||||
TransferManifestNode node4 = createContentNode(transferId);
|
||||
node4 = createContentNode(transferId);
|
||||
nodes.add(node4);
|
||||
TransferManifestNode node5 = createContentNode(transferId);
|
||||
node5 = createContentNode(transferId);
|
||||
nodes.add(node5);
|
||||
TransferManifestNode node6 = createContentNode(transferId);
|
||||
node6 = createContentNode(transferId);
|
||||
nodes.add(node6);
|
||||
TransferManifestNode node7 = createContentNode(transferId);
|
||||
node7 = createContentNode(transferId);
|
||||
nodes.add(node7);
|
||||
TransferManifestNode node8 = createFolderNode(transferId);
|
||||
node8 = createFolderNode(transferId);
|
||||
nodes.add(node8);
|
||||
TransferManifestNode node9 = createFolderNode(transferId);
|
||||
node9 = createFolderNode(transferId);
|
||||
nodes.add(node9);
|
||||
TransferManifestNode node10 = createFolderNode(transferId);
|
||||
node10 = createFolderNode(transferId);
|
||||
nodes.add(node10);
|
||||
TransferManifestNormalNode node11 = createFolderNode(transferId);
|
||||
node11 = createFolderNode(transferId);
|
||||
nodes.add(node11);
|
||||
TransferManifestNode node12 = createFolderNode(transferId);
|
||||
node12 = createFolderNode(transferId);
|
||||
nodes.add(node12);
|
||||
|
||||
associatePeers(node1, node2);
|
||||
@@ -219,90 +316,144 @@ public class RepoTransferReceiverImplTest extends BaseAlfrescoSpringTest
|
||||
|
||||
receiver.saveSnapshot(transferId, new StringInputStream(snapshot, "UTF-8"));
|
||||
|
||||
for (TransferManifestNode node : nodes) {
|
||||
for (TransferManifestNode node : nodes)
|
||||
{
|
||||
receiver.saveContent(transferId, node.getUuid(), new ByteArrayInputStream(dummyContentBytes));
|
||||
}
|
||||
receiver.commit(transferId);
|
||||
|
||||
assertTrue(nodeService.getAspects(node1.getNodeRef()).contains(ContentModel.ASPECT_ATTACHABLE));
|
||||
assertFalse(nodeService.getSourceAssocs(node2.getNodeRef(), ContentModel.ASSOC_ATTACHMENTS).isEmpty());
|
||||
for (TransferManifestNode node : nodes) {
|
||||
assertTrue(nodeService.exists(node.getNodeRef()));
|
||||
}
|
||||
} catch (Exception ex)
|
||||
}
|
||||
finally
|
||||
{
|
||||
receiver.end(transferId);
|
||||
throw ex;
|
||||
endTransaction();
|
||||
}
|
||||
|
||||
startNewTransaction();
|
||||
try
|
||||
{
|
||||
assertTrue(nodeService.getAspects(node1.getNodeRef()).contains(ContentModel.ASPECT_ATTACHABLE));
|
||||
assertFalse(nodeService.getSourceAssocs(node2.getNodeRef(), ContentModel.ASSOC_ATTACHMENTS).isEmpty());
|
||||
for (TransferManifestNode node : nodes)
|
||||
{
|
||||
assertTrue(nodeService.exists(node.getNodeRef()));
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
endTransaction();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void testNodeDeleteAndRestore() throws Exception {
|
||||
public void testNodeDeleteAndRestore() throws Exception
|
||||
{
|
||||
log.info("testNodeDeleteAndRestore");
|
||||
|
||||
this.setDefaultRollback(false);
|
||||
startNewTransaction();
|
||||
String transferId = receiver.start();
|
||||
|
||||
List<TransferManifestNode> nodes = new ArrayList<TransferManifestNode>();
|
||||
TransferManifestNormalNode node1 = createContentNode(transferId);
|
||||
nodes.add(node1);
|
||||
TransferManifestNormalNode node2 = createContentNode(transferId);
|
||||
nodes.add(node2);
|
||||
TransferManifestNode node3 = createContentNode(transferId);
|
||||
nodes.add(node3);
|
||||
TransferManifestNode node4 = createContentNode(transferId);
|
||||
nodes.add(node4);
|
||||
TransferManifestNode node5 = createContentNode(transferId);
|
||||
nodes.add(node5);
|
||||
TransferManifestNode node6 = createContentNode(transferId);
|
||||
nodes.add(node6);
|
||||
TransferManifestNode node7 = createContentNode(transferId);
|
||||
nodes.add(node7);
|
||||
TransferManifestNode node8 = createFolderNode(transferId);
|
||||
nodes.add(node8);
|
||||
TransferManifestNode node9 = createFolderNode(transferId);
|
||||
nodes.add(node9);
|
||||
TransferManifestNode node10 = createFolderNode(transferId);
|
||||
nodes.add(node10);
|
||||
TransferManifestNormalNode node11 = createFolderNode(transferId);
|
||||
nodes.add(node11);
|
||||
TransferManifestNode node12 = createFolderNode(transferId);
|
||||
nodes.add(node12);
|
||||
|
||||
associatePeers(node1, node2);
|
||||
moveNode(node2, node11);
|
||||
|
||||
TransferManifestDeletedNode deletedNode8 = createDeletedNode(node8);
|
||||
TransferManifestDeletedNode deletedNode2 = createDeletedNode(node2);
|
||||
TransferManifestDeletedNode deletedNode11 = createDeletedNode(node11);
|
||||
|
||||
endTransaction();
|
||||
|
||||
startNewTransaction();
|
||||
try
|
||||
{
|
||||
List<TransferManifestNode> nodes = new ArrayList<TransferManifestNode>();
|
||||
TransferManifestNormalNode node1 = createContentNode(transferId);
|
||||
nodes.add(node1);
|
||||
TransferManifestNormalNode node2 = createContentNode(transferId);
|
||||
nodes.add(node2);
|
||||
TransferManifestNode node3 = createContentNode(transferId);
|
||||
nodes.add(node3);
|
||||
TransferManifestNode node4 = createContentNode(transferId);
|
||||
nodes.add(node4);
|
||||
TransferManifestNode node5 = createContentNode(transferId);
|
||||
nodes.add(node5);
|
||||
TransferManifestNode node6 = createContentNode(transferId);
|
||||
nodes.add(node6);
|
||||
TransferManifestNode node7 = createContentNode(transferId);
|
||||
nodes.add(node7);
|
||||
TransferManifestNode node8 = createFolderNode(transferId);
|
||||
nodes.add(node8);
|
||||
TransferManifestNode node9 = createFolderNode(transferId);
|
||||
nodes.add(node9);
|
||||
TransferManifestNode node10 = createFolderNode(transferId);
|
||||
nodes.add(node10);
|
||||
TransferManifestNormalNode node11 = createFolderNode(transferId);
|
||||
nodes.add(node11);
|
||||
TransferManifestNode node12 = createFolderNode(transferId);
|
||||
nodes.add(node12);
|
||||
|
||||
associatePeers(node1, node2);
|
||||
moveNode(node2, node11);
|
||||
|
||||
String snapshot = createSnapshot(nodes);
|
||||
log.debug(snapshot);
|
||||
receiver.saveSnapshot(transferId, new StringInputStream(snapshot, "UTF-8"));
|
||||
|
||||
for (TransferManifestNode node : nodes) {
|
||||
for (TransferManifestNode node : nodes)
|
||||
{
|
||||
receiver.saveContent(transferId, node.getUuid(), new ByteArrayInputStream(dummyContentBytes));
|
||||
}
|
||||
receiver.commit(transferId);
|
||||
|
||||
assertTrue(nodeService.getAspects(node1.getNodeRef()).contains(ContentModel.ASPECT_ATTACHABLE));
|
||||
assertFalse(nodeService.getSourceAssocs(node2.getNodeRef(), ContentModel.ASSOC_ATTACHMENTS).isEmpty());
|
||||
for (TransferManifestNode node : nodes) {
|
||||
for (TransferManifestNode node : nodes)
|
||||
{
|
||||
assertTrue(nodeService.exists(node.getNodeRef()));
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
endTransaction();
|
||||
}
|
||||
|
||||
//Now delete nodes 8, 2, and 11 (2 and 11 are parent/child)
|
||||
TransferManifestDeletedNode deletedNode8 = createDeletedNode(node8);
|
||||
TransferManifestDeletedNode deletedNode2 = createDeletedNode(node2);
|
||||
TransferManifestDeletedNode deletedNode11 = createDeletedNode(node11);
|
||||
startNewTransaction();
|
||||
try
|
||||
{
|
||||
// Now delete nodes 8, 2, and 11 (2 and 11 are parent/child)
|
||||
transferId = receiver.start();
|
||||
snapshot = createSnapshot(Arrays.asList(new TransferManifestNode[] {deletedNode8, deletedNode2, deletedNode11}));
|
||||
String snapshot = createSnapshot(Arrays.asList(new TransferManifestNode[] { deletedNode8, deletedNode2,
|
||||
deletedNode11 }));
|
||||
receiver.saveSnapshot(transferId, new StringInputStream(snapshot, "UTF-8"));
|
||||
receiver.commit(transferId);
|
||||
}
|
||||
finally
|
||||
{
|
||||
endTransaction();
|
||||
}
|
||||
|
||||
startNewTransaction();
|
||||
try
|
||||
{
|
||||
assertTrue(nodeService.exists(deletedNode8.getNodeRef()));
|
||||
assertTrue(nodeService.hasAspect(deletedNode8.getNodeRef(), ContentModel.ASPECT_ARCHIVED));
|
||||
assertTrue(nodeService.exists(deletedNode2.getNodeRef()));
|
||||
assertTrue(nodeService.hasAspect(deletedNode2.getNodeRef(), ContentModel.ASPECT_ARCHIVED));
|
||||
assertTrue(nodeService.exists(deletedNode11.getNodeRef()));
|
||||
assertTrue(nodeService.hasAspect(deletedNode11.getNodeRef(), ContentModel.ASPECT_ARCHIVED));
|
||||
TransferProgress progress = receiver.getProgressMonitor().getProgress(transferId);
|
||||
assertEquals(TransferProgress.Status.COMPLETE, progress.getStatus());
|
||||
log.debug("Progress indication: " + progress.getCurrentPosition() + "/" + progress.getEndPosition());
|
||||
}
|
||||
finally
|
||||
{
|
||||
endTransaction();
|
||||
}
|
||||
|
||||
//try to restore node 2. Expect an "orphan" failure, since its parent (node11) is deleted
|
||||
String errorMsgId = null;
|
||||
startNewTransaction();
|
||||
try
|
||||
{
|
||||
// try to restore node 2. Expect an "orphan" failure, since its parent (node11) is deleted
|
||||
transferId = receiver.start();
|
||||
snapshot = createSnapshot(Arrays.asList(new TransferManifestNode[] {node2}));
|
||||
String snapshot = createSnapshot(Arrays.asList(new TransferManifestNode[] { node2 }));
|
||||
log.debug(snapshot);
|
||||
receiver.saveSnapshot(transferId, new StringInputStream(snapshot, "UTF-8"));
|
||||
receiver.saveContent(transferId, node2.getUuid(), new ByteArrayInputStream(dummyContentBytes));
|
||||
@@ -313,15 +464,125 @@ public class RepoTransferReceiverImplTest extends BaseAlfrescoSpringTest
|
||||
}
|
||||
catch (TransferException ex)
|
||||
{
|
||||
assertTrue(ex.getMsgId(), ex.getMsgId().contains("orphan"));
|
||||
// Expected
|
||||
errorMsgId = ex.getMsgId();
|
||||
}
|
||||
|
||||
} catch (Exception ex)
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
receiver.end(transferId);
|
||||
throw ex;
|
||||
}
|
||||
finally
|
||||
{
|
||||
endTransaction();
|
||||
}
|
||||
|
||||
startNewTransaction();
|
||||
try
|
||||
{
|
||||
TransferProgress progress = receiver.getProgressMonitor().getProgress(transferId);
|
||||
assertEquals(TransferProgress.Status.ERROR, progress.getStatus());
|
||||
log.debug("Progress indication: " + progress.getCurrentPosition() + "/" + progress.getEndPosition());
|
||||
assertNotNull("Progress error", progress.getError());
|
||||
assertTrue(progress.getError() instanceof Exception);
|
||||
assertTrue(errorMsgId, errorMsgId.contains("orphan"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
endTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
public void testAsyncCommit() throws Exception
|
||||
{
|
||||
log.info("testAsyncCommit");
|
||||
|
||||
this.setDefaultRollback(false);
|
||||
|
||||
startNewTransaction();
|
||||
final String transferId = receiver.start();
|
||||
endTransaction();
|
||||
|
||||
startNewTransaction();
|
||||
final List<TransferManifestNode> nodes = new ArrayList<TransferManifestNode>();
|
||||
final TransferManifestNormalNode node1 = createContentNode(transferId);
|
||||
nodes.add(node1);
|
||||
final TransferManifestNormalNode node2 = createContentNode(transferId);
|
||||
nodes.add(node2);
|
||||
TransferManifestNode node3 = createContentNode(transferId);
|
||||
nodes.add(node3);
|
||||
TransferManifestNode node4 = createContentNode(transferId);
|
||||
nodes.add(node4);
|
||||
TransferManifestNode node5 = createContentNode(transferId);
|
||||
nodes.add(node5);
|
||||
TransferManifestNode node6 = createContentNode(transferId);
|
||||
nodes.add(node6);
|
||||
TransferManifestNode node7 = createContentNode(transferId);
|
||||
nodes.add(node7);
|
||||
TransferManifestNode node8 = createFolderNode(transferId);
|
||||
nodes.add(node8);
|
||||
TransferManifestNode node9 = createFolderNode(transferId);
|
||||
nodes.add(node9);
|
||||
TransferManifestNode node10 = createFolderNode(transferId);
|
||||
nodes.add(node10);
|
||||
TransferManifestNormalNode node11 = createFolderNode(transferId);
|
||||
nodes.add(node11);
|
||||
TransferManifestNode node12 = createFolderNode(transferId);
|
||||
nodes.add(node12);
|
||||
|
||||
associatePeers(node1, node2);
|
||||
moveNode(node2, node11);
|
||||
|
||||
endTransaction();
|
||||
|
||||
String snapshot = createSnapshot(nodes);
|
||||
|
||||
startNewTransaction();
|
||||
receiver.saveSnapshot(transferId, new StringInputStream(snapshot, "UTF-8"));
|
||||
endTransaction();
|
||||
|
||||
for (TransferManifestNode node : nodes)
|
||||
{
|
||||
startNewTransaction();
|
||||
receiver.saveContent(transferId, node.getUuid(), new ByteArrayInputStream(dummyContentBytes));
|
||||
endTransaction();
|
||||
}
|
||||
|
||||
startNewTransaction();
|
||||
receiver.commitAsync(transferId);
|
||||
endTransaction();
|
||||
|
||||
log.debug("Posted request for commit");
|
||||
|
||||
TransferProgressMonitor progressMonitor = receiver.getProgressMonitor();
|
||||
TransferProgress progress = null;
|
||||
while (progress == null || !TransferProgress.getTerminalStatuses().contains(progress.getStatus()))
|
||||
{
|
||||
Thread.sleep(500);
|
||||
startNewTransaction();
|
||||
progress = progressMonitor.getProgress(transferId);
|
||||
endTransaction();
|
||||
log.debug("Progress indication: " + progress.getStatus() + ": " + progress.getCurrentPosition() + "/"
|
||||
+ progress.getEndPosition());
|
||||
}
|
||||
assertEquals(TransferProgress.Status.COMPLETE, progress.getStatus());
|
||||
|
||||
startNewTransaction();
|
||||
try
|
||||
{
|
||||
assertTrue(nodeService.getAspects(node1.getNodeRef()).contains(ContentModel.ASPECT_ATTACHABLE));
|
||||
assertFalse(nodeService.getSourceAssocs(node2.getNodeRef(), ContentModel.ASSOC_ATTACHMENTS).isEmpty());
|
||||
for (TransferManifestNode node : nodes)
|
||||
{
|
||||
assertTrue(nodeService.exists(node.getNodeRef()));
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
endTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -347,12 +608,16 @@ public class RepoTransferReceiverImplTest extends BaseAlfrescoSpringTest
|
||||
List<ChildAssociationRef> currentParents = childNode.getParentAssocs();
|
||||
List<ChildAssociationRef> newParents = new ArrayList<ChildAssociationRef>();
|
||||
|
||||
for (ChildAssociationRef parent : currentParents) {
|
||||
if (!parent.isPrimary()) {
|
||||
for (ChildAssociationRef parent : currentParents)
|
||||
{
|
||||
if (!parent.isPrimary())
|
||||
{
|
||||
newParents.add(parent);
|
||||
} else {
|
||||
ChildAssociationRef newPrimaryAssoc = new ChildAssociationRef(ContentModel.ASSOC_CONTAINS,
|
||||
newParent.getNodeRef(), parent.getQName(), parent.getChildRef(), true, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
ChildAssociationRef newPrimaryAssoc = new ChildAssociationRef(ContentModel.ASSOC_CONTAINS, newParent
|
||||
.getNodeRef(), parent.getQName(), parent.getChildRef(), true, -1);
|
||||
newParents.add(newPrimaryAssoc);
|
||||
childNode.setPrimaryParentAssoc(newPrimaryAssoc);
|
||||
Path newParentPath = new Path();
|
||||
@@ -364,39 +629,47 @@ public class RepoTransferReceiverImplTest extends BaseAlfrescoSpringTest
|
||||
childNode.setParentAssocs(newParents);
|
||||
}
|
||||
|
||||
private void associatePeers(TransferManifestNormalNode source, TransferManifestNormalNode target) {
|
||||
private void associatePeers(TransferManifestNormalNode source, TransferManifestNormalNode target)
|
||||
{
|
||||
List<AssociationRef> currentReferencedPeers = source.getTargetAssocs();
|
||||
if (currentReferencedPeers == null) {
|
||||
if (currentReferencedPeers == null)
|
||||
{
|
||||
currentReferencedPeers = new ArrayList<AssociationRef>();
|
||||
source.setTargetAssocs(currentReferencedPeers);
|
||||
}
|
||||
|
||||
List<AssociationRef> currentRefereePeers = target.getSourceAssocs();
|
||||
if (currentRefereePeers == null) {
|
||||
if (currentRefereePeers == null)
|
||||
{
|
||||
currentRefereePeers = new ArrayList<AssociationRef>();
|
||||
target.setSourceAssocs(currentRefereePeers);
|
||||
}
|
||||
|
||||
Set<QName> aspects = source.getAspects();
|
||||
if (aspects == null ) {
|
||||
if (aspects == null)
|
||||
{
|
||||
aspects = new HashSet<QName>();
|
||||
source.setAspects(aspects);
|
||||
}
|
||||
aspects.add(ContentModel.ASPECT_ATTACHABLE);
|
||||
|
||||
AssociationRef newAssoc = new AssociationRef(source.getNodeRef(), ContentModel.ASSOC_ATTACHMENTS, target.getNodeRef());
|
||||
AssociationRef newAssoc = new AssociationRef(source.getNodeRef(), ContentModel.ASSOC_ATTACHMENTS, target
|
||||
.getNodeRef());
|
||||
currentRefereePeers.add(newAssoc);
|
||||
currentReferencedPeers.add(newAssoc);
|
||||
}
|
||||
|
||||
private String createSnapshot(List<TransferManifestNode> nodes) throws Exception {
|
||||
private String createSnapshot(List<TransferManifestNode> nodes) throws Exception
|
||||
{
|
||||
XMLTransferManifestWriter manifestWriter = new XMLTransferManifestWriter();
|
||||
StringWriter output = new StringWriter();
|
||||
manifestWriter.startTransferManifest(output);
|
||||
TransferManifestHeader header = new TransferManifestHeader();
|
||||
header.setCreatedDate(new Date());
|
||||
header.setNodeCount(nodes.size());
|
||||
manifestWriter.writeTransferManifestHeader(header);
|
||||
for (TransferManifestNode node : nodes) {
|
||||
for (TransferManifestNode node : nodes)
|
||||
{
|
||||
manifestWriter.writeTransferManifestNode(node);
|
||||
}
|
||||
manifestWriter.endTransferManifest();
|
||||
@@ -420,11 +693,11 @@ public class RepoTransferReceiverImplTest extends BaseAlfrescoSpringTest
|
||||
node.setType(ContentModel.TYPE_CONTENT);
|
||||
|
||||
NodeRef parentFolder = receiver.getTempFolder(transferId);
|
||||
String nodeName = transferId + ".testnode" + getNameSuffix();
|
||||
String nodeName = uuid + ".testnode" + getNameSuffix();
|
||||
|
||||
List<ChildAssociationRef> parents = new ArrayList<ChildAssociationRef>();
|
||||
ChildAssociationRef primaryAssoc = new ChildAssociationRef(ContentModel.ASSOC_CONTAINS, parentFolder, QName.createQName(
|
||||
NamespaceService.CONTENT_MODEL_1_0_URI, nodeName), node.getNodeRef(), true, -1);
|
||||
ChildAssociationRef primaryAssoc = new ChildAssociationRef(ContentModel.ASSOC_CONTAINS, parentFolder, QName
|
||||
.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, nodeName), node.getNodeRef(), true, -1);
|
||||
parents.add(primaryAssoc);
|
||||
node.setParentAssocs(parents);
|
||||
node.setParentPath(nodeService.getPath(parentFolder));
|
||||
@@ -451,11 +724,11 @@ public class RepoTransferReceiverImplTest extends BaseAlfrescoSpringTest
|
||||
node.setType(ContentModel.TYPE_FOLDER);
|
||||
|
||||
NodeRef parentFolder = receiver.getTempFolder(transferId);
|
||||
String nodeName = transferId + ".folder" + getNameSuffix();
|
||||
String nodeName = uuid + ".folder" + getNameSuffix();
|
||||
|
||||
List<ChildAssociationRef> parents = new ArrayList<ChildAssociationRef>();
|
||||
ChildAssociationRef primaryAssoc = new ChildAssociationRef(ContentModel.ASSOC_CONTAINS, parentFolder, QName.createQName(
|
||||
NamespaceService.CONTENT_MODEL_1_0_URI, nodeName), node.getNodeRef(), true, -1);
|
||||
ChildAssociationRef primaryAssoc = new ChildAssociationRef(ContentModel.ASSOC_CONTAINS, parentFolder, QName
|
||||
.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, nodeName), node.getNodeRef(), true, -1);
|
||||
parents.add(primaryAssoc);
|
||||
node.setParentAssocs(parents);
|
||||
node.setParentPath(nodeService.getPath(parentFolder));
|
||||
@@ -469,7 +742,8 @@ public class RepoTransferReceiverImplTest extends BaseAlfrescoSpringTest
|
||||
return node;
|
||||
}
|
||||
|
||||
private String getNameSuffix() {
|
||||
private String getNameSuffix()
|
||||
{
|
||||
return "" + fileCount++;
|
||||
}
|
||||
}
|
||||
|
@@ -35,6 +35,7 @@ import java.util.Set;
|
||||
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.transfer.NodeCrawler;
|
||||
import org.alfresco.service.cmr.transfer.NodeFilter;
|
||||
import org.alfresco.service.cmr.transfer.NodeFinder;
|
||||
import org.alfresco.service.cmr.transfer.TransferService;
|
||||
@@ -50,7 +51,7 @@ import org.alfresco.service.cmr.transfer.TransferService;
|
||||
* @author brian
|
||||
*
|
||||
*/
|
||||
public class StandardNodeCrawlerImpl
|
||||
public class StandardNodeCrawlerImpl implements NodeCrawler
|
||||
{
|
||||
private ServiceRegistry serviceRegistry;
|
||||
private List<NodeFinder> nodeFinders = new ArrayList<NodeFinder>();
|
||||
@@ -82,11 +83,17 @@ public class StandardNodeCrawlerImpl
|
||||
this.serviceRegistry = serviceRegistry;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.transfer.NodeCrawler#crawl(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
public Set<NodeRef> crawl(NodeRef... nodes)
|
||||
{
|
||||
return crawl(new HashSet<NodeRef>(Arrays.asList(nodes)));
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.transfer.NodeCrawler#crawl(java.util.Set)
|
||||
*/
|
||||
public synchronized Set<NodeRef> crawl(Set<NodeRef> startingNodes)
|
||||
{
|
||||
init();
|
||||
@@ -166,11 +173,17 @@ public class StandardNodeCrawlerImpl
|
||||
return include;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.transfer.NodeCrawler#setNodeFinders(org.alfresco.service.cmr.transfer.NodeFinder)
|
||||
*/
|
||||
public synchronized void setNodeFinders(NodeFinder... finders)
|
||||
{
|
||||
nodeFinders = Arrays.asList(finders);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.transfer.NodeCrawler#setNodeFilters(org.alfresco.service.cmr.transfer.NodeFilter)
|
||||
*/
|
||||
public synchronized void setNodeFilters(NodeFilter... filters)
|
||||
{
|
||||
nodeFilters = Arrays.asList(filters);
|
||||
|
@@ -5,6 +5,7 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
import org.alfresco.service.cmr.transfer.TransferCallback;
|
||||
import org.alfresco.service.cmr.transfer.TransferEvent;
|
||||
import org.alfresco.service.cmr.transfer.TransferEventBegin;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
@@ -16,13 +17,23 @@ public class TestTransferCallback implements TransferCallback
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static Log logger = LogFactory.getLog(TestTransferCallback.class);
|
||||
|
||||
|
||||
Queue<TransferEvent> events = new ConcurrentLinkedQueue<TransferEvent>();
|
||||
String transferId = null;
|
||||
|
||||
public void processEvent(TransferEvent event)
|
||||
{
|
||||
logger.debug(event.toString());
|
||||
events.add(event);
|
||||
|
||||
if(event instanceof TransferEventBegin)
|
||||
{
|
||||
TransferEventBegin beginEvent = (TransferEventBegin)event;
|
||||
transferId = beginEvent.getTransferId();
|
||||
}
|
||||
}
|
||||
|
||||
Queue<TransferEvent> events = new ConcurrentLinkedQueue<TransferEvent>();
|
||||
|
||||
|
||||
/**
|
||||
* Get the thread safe queue of events
|
||||
|
@@ -25,8 +25,8 @@
|
||||
|
||||
package org.alfresco.repo.transfer;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.repo.action.executer.ActionExecuterAbstractBase;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
@@ -39,50 +39,47 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Deploys a website to a remote server.
|
||||
*
|
||||
* TODO refactor and add to WCM services (when we support WCM deployment config)
|
||||
*
|
||||
* @author gavinc
|
||||
* @author markr
|
||||
*/
|
||||
public class TransferAsyncAction extends ActionExecuterAbstractBase
|
||||
{
|
||||
public static final String ASYNC_QUEUE_NAME = "deployment";
|
||||
public static final String ASYNC_QUEUE_NAME = "deployment";
|
||||
|
||||
private TransferService transferService;
|
||||
private TransferService transferService;
|
||||
|
||||
private static Log logger = LogFactory.getLog(TransferAsyncAction.class);
|
||||
private static Log logger = LogFactory.getLog(TransferAsyncAction.class);
|
||||
|
||||
public void init()
|
||||
{
|
||||
super.name = "transfer-async";
|
||||
}
|
||||
public void init()
|
||||
{
|
||||
super.name = "transfer-async";
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void executeImpl(Action action, NodeRef actionedUponNodeRef)
|
||||
{
|
||||
logger.debug("In TransferAsyncAction");
|
||||
|
||||
@Override
|
||||
protected void executeImpl(Action action, NodeRef actionedUponNodeRef)
|
||||
{
|
||||
System.out.println("In TransferAsyncAction");
|
||||
String targetName = (String) action.getParameterValue("targetName");
|
||||
TransferDefinition definition = (TransferDefinition) action.getParameterValue("definition");
|
||||
Collection<TransferCallback> callback = (Collection<TransferCallback>) action.getParameterValue("callbacks");
|
||||
|
||||
String targetName = (String)action.getParameterValue("targetName");
|
||||
TransferDefinition definition = (TransferDefinition)action.getParameterValue("definition");
|
||||
Set<TransferCallback> callback = (Set<TransferCallback>) action.getParameterValue("callbacks");
|
||||
transferService.transfer(targetName, definition, callback);
|
||||
}
|
||||
|
||||
transferService.transfer(targetName, definition, callback);
|
||||
}
|
||||
@Override
|
||||
protected void addParameterDefinitions(List<ParameterDefinition> paramList)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addParameterDefinitions(List<ParameterDefinition> paramList)
|
||||
{
|
||||
}
|
||||
public void setTransferService(TransferService transferService)
|
||||
{
|
||||
this.transferService = transferService;
|
||||
}
|
||||
|
||||
public void setTransferService(TransferService transferService)
|
||||
{
|
||||
this.transferService = transferService;
|
||||
}
|
||||
|
||||
public TransferService getTransferService()
|
||||
{
|
||||
return transferService;
|
||||
}
|
||||
public TransferService getTransferService()
|
||||
{
|
||||
return transferService;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,46 @@
|
||||
package org.alfresco.repo.transfer;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.repo.action.ParameterDefinitionImpl;
|
||||
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.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.transfer.TransferReceiver;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
public class TransferCommitActionExecuter extends ActionExecuterAbstractBase
|
||||
{
|
||||
private Log log = LogFactory.getLog(TransferCommitActionExecuter.class);
|
||||
|
||||
public static final String NAME = "commit-transfer";
|
||||
public static final String PARAM_TRANSFER_ID = "transfer-id";
|
||||
|
||||
private TransferReceiver receiver;
|
||||
|
||||
public void setReceiver(TransferReceiver receiver)
|
||||
{
|
||||
this.receiver = receiver;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void executeImpl(Action action, NodeRef actionedUponNodeRef)
|
||||
{
|
||||
String transferId = (String)action.getParameterValue(PARAM_TRANSFER_ID);
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("Transfer id = " + transferId);
|
||||
}
|
||||
receiver.commit(transferId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addParameterDefinitions(List<ParameterDefinition> paramList)
|
||||
{
|
||||
paramList.add(new ParameterDefinitionImpl(PARAM_TRANSFER_ID, DataTypeDefinition.TEXT, true,
|
||||
getParamDisplayLabel(PARAM_TRANSFER_ID)));
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
package org.alfresco.repo.transfer;
|
||||
|
||||
import org.alfresco.repo.transaction.TransactionListenerAdapter;
|
||||
import org.alfresco.service.cmr.transfer.TransferProgress;
|
||||
import org.alfresco.service.cmr.transfer.TransferReceiver;
|
||||
|
||||
public class TransferCommitTransactionListener extends TransactionListenerAdapter
|
||||
{
|
||||
private TransferReceiver receiver;
|
||||
private String transferId;
|
||||
|
||||
public TransferCommitTransactionListener(String transferId, TransferReceiver receiver)
|
||||
{
|
||||
super();
|
||||
this.receiver = receiver;
|
||||
this.transferId = transferId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCommit()
|
||||
{
|
||||
updateTransferStatus(TransferProgress.Status.COMPLETE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterRollback()
|
||||
{
|
||||
updateTransferStatus(TransferProgress.Status.ERROR);
|
||||
}
|
||||
|
||||
private void updateTransferStatus(TransferProgress.Status status)
|
||||
{
|
||||
receiver.getProgressMonitor().updateStatus(transferId, status);
|
||||
}
|
||||
}
|
@@ -24,7 +24,6 @@
|
||||
*/
|
||||
package org.alfresco.repo.transfer;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
@@ -32,6 +31,7 @@ import java.util.concurrent.LinkedBlockingQueue;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.transfer.TransferCallback;
|
||||
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;
|
||||
@@ -77,6 +77,17 @@ public class TransferEventProcessor
|
||||
|
||||
}
|
||||
|
||||
public void begin(String transferId)
|
||||
{
|
||||
setState(TransferEvent.TransferState.START);
|
||||
TransferEventBegin event = new TransferEventBegin();
|
||||
event.setTransferState(TransferEvent.TransferState.START);
|
||||
event.setMessage("begin transferId:" + transferId);
|
||||
queue.add(event);
|
||||
event.setTransferId(transferId);
|
||||
notifyObservers();
|
||||
}
|
||||
|
||||
public void start()
|
||||
{
|
||||
setState(TransferEvent.TransferState.START);
|
||||
@@ -93,6 +104,7 @@ public class TransferEventProcessor
|
||||
TransferEventSuccess event = new TransferEventSuccess();
|
||||
event.setTransferState(TransferEvent.TransferState.SUCCESS);
|
||||
event.setLast(true);
|
||||
event.setMessage("success lastEvent:true");
|
||||
queue.add(event);
|
||||
notifyObservers();
|
||||
}
|
||||
@@ -107,6 +119,7 @@ public class TransferEventProcessor
|
||||
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();
|
||||
@@ -157,6 +170,12 @@ public class TransferEventProcessor
|
||||
notifyObservers();
|
||||
}
|
||||
|
||||
public void commit()
|
||||
{
|
||||
setState(TransferEvent.TransferState.COMMITTING);
|
||||
notifyObservers();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param range
|
||||
|
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* @author brian
|
||||
*
|
||||
*/
|
||||
public class TransferFatalException extends TransferException
|
||||
{
|
||||
private static final long serialVersionUID = 1022985703059592513L;
|
||||
|
||||
/**
|
||||
* @param msgId
|
||||
* @param msgParams
|
||||
* @param cause
|
||||
*/
|
||||
public TransferFatalException(String msgId, Object[] msgParams, Throwable cause)
|
||||
{
|
||||
super(msgId, msgParams, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param msgId
|
||||
* @param msgParams
|
||||
*/
|
||||
public TransferFatalException(String msgId, Object[] msgParams)
|
||||
{
|
||||
super(msgId, msgParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param msgId
|
||||
* @param cause
|
||||
*/
|
||||
public TransferFatalException(String msgId, Throwable cause)
|
||||
{
|
||||
super(msgId, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param msgId
|
||||
*/
|
||||
public TransferFatalException(String msgId)
|
||||
{
|
||||
super(msgId);
|
||||
}
|
||||
}
|
@@ -30,6 +30,7 @@ import org.alfresco.service.namespace.QName;
|
||||
* Transfer Model Constants
|
||||
*
|
||||
* @author Mark Rogers
|
||||
* @author Brian Remmington
|
||||
*/
|
||||
public interface TransferModel
|
||||
{
|
||||
@@ -62,9 +63,25 @@ public interface TransferModel
|
||||
static final QName TYPE_TRANSFER_LOCK = QName.createQName(TRANSFER_MODEL_1_0_URI, "transferLock");
|
||||
static final QName PROP_TRANSFER_ID = QName.createQName(TRANSFER_MODEL_1_0_URI, "transferId");
|
||||
|
||||
/*
|
||||
* Type : Transfer Record
|
||||
*/
|
||||
static final QName TYPE_TRANSFER_RECORD = QName.createQName(TRANSFER_MODEL_1_0_URI, "transferRecord");
|
||||
static final QName PROP_PROGRESS_POSITION = QName.createQName(TRANSFER_MODEL_1_0_URI, "progressPosition");
|
||||
static final QName PROP_PROGRESS_ENDPOINT = QName.createQName(TRANSFER_MODEL_1_0_URI, "progressEndpoint");
|
||||
static final QName PROP_TRANSFER_STATUS = QName.createQName(TRANSFER_MODEL_1_0_URI, "transferStatus");
|
||||
static final QName PROP_TRANSFER_ERROR = QName.createQName(TRANSFER_MODEL_1_0_URI, "transferError");
|
||||
|
||||
|
||||
/*
|
||||
* Type : Transfer report
|
||||
*/
|
||||
static final QName TYPE_TRANSFER_REPORT = QName.createQName(TRANSFER_MODEL_1_0_URI, "transferReport");
|
||||
|
||||
/*
|
||||
* Type : Temp Transfer Storage
|
||||
*/
|
||||
static final QName TYPE_TEMP_TRANSFER_STORE = QName.createQName(TRANSFER_MODEL_1_0_URI, "tempTransferStore");
|
||||
static final QName ASSOC_TRANSFER_ORPHAN = QName.createQName(TRANSFER_MODEL_1_0_URI, "orphan");
|
||||
|
||||
}
|
||||
|
@@ -25,27 +25,23 @@
|
||||
|
||||
package org.alfresco.repo.transfer;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.repo.action.ParameterDefinitionImpl;
|
||||
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.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.transfer.TransferDefinition;
|
||||
import org.alfresco.service.cmr.transfer.TransferService;
|
||||
import org.alfresco.service.cmr.transfer.TransferTarget;
|
||||
|
||||
/**
|
||||
* @author brian
|
||||
*
|
||||
*/
|
||||
public class TransferActionExecuter extends ActionExecuterAbstractBase
|
||||
public class TransferOneNodeActionExecuter extends ActionExecuterAbstractBase
|
||||
{
|
||||
public static final String NAME = "transfer-node";
|
||||
public static final String PARAM_TRANSFER_TARGET = "target-name";
|
||||
public static final String NAME = "transfer-this-node";
|
||||
private TransferService transferService;
|
||||
|
||||
/**
|
||||
@@ -62,20 +58,14 @@ public class TransferActionExecuter extends ActionExecuterAbstractBase
|
||||
@Override
|
||||
protected void executeImpl(Action action, NodeRef actionedUponNodeRef)
|
||||
{
|
||||
TransferTarget target = TransferTestUtil.getTestTarget(transferService);
|
||||
TransferDefinition td = new TransferDefinition();
|
||||
Set<NodeRef> nodes = new HashSet<NodeRef>();
|
||||
nodes.add(actionedUponNodeRef);
|
||||
td.setNodes(nodes);
|
||||
transferService.transfer("transferMe", td);
|
||||
td.setNodes(actionedUponNodeRef);
|
||||
transferService.transfer(target.getName(), td);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List)
|
||||
*/
|
||||
@Override
|
||||
protected void addParameterDefinitions(List<ParameterDefinition> paramList)
|
||||
{
|
||||
//paramList.add(new ParameterDefinitionImpl(PARAM_TRANSFER_TARGET, DataTypeDefinition.TEXT, true, "Transfer Target Name"));
|
||||
}
|
||||
|
||||
}
|
@@ -33,7 +33,10 @@ import org.alfresco.service.cmr.transfer.TransferException;
|
||||
*/
|
||||
public class TransferProcessingException extends TransferException
|
||||
{
|
||||
private boolean fatal = false;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 2547803698674661069L;
|
||||
|
||||
/**
|
||||
* @param msgId
|
||||
@@ -70,21 +73,4 @@ public class TransferProcessingException extends TransferException
|
||||
{
|
||||
super(msgId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the fatal
|
||||
*/
|
||||
public boolean isFatal()
|
||||
{
|
||||
return fatal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fatal the fatal to set
|
||||
*/
|
||||
public void setFatal(boolean fatal)
|
||||
{
|
||||
this.fatal = fatal;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* @author brian
|
||||
*
|
||||
*/
|
||||
public interface TransferProgressMonitor
|
||||
{
|
||||
void log(String transferId, Object obj) throws TransferException;
|
||||
void log(String transferId, Object obj, Throwable ex) throws TransferException;
|
||||
void updateProgress(String transferId, int currPos) throws TransferException;
|
||||
void updateProgress(String transferId, int currPos, int endPos) throws TransferException;
|
||||
void updateStatus(String transferId, TransferProgress.Status status) throws TransferException;
|
||||
TransferProgress getProgress(String transferId) throws TransferException;
|
||||
}
|
@@ -30,6 +30,10 @@ import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -80,6 +84,7 @@ import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.alfresco.service.cmr.transfer.TransferCallback;
|
||||
import org.alfresco.service.cmr.transfer.TransferDefinition;
|
||||
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.TransferTarget;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
@@ -99,8 +104,14 @@ public class TransferServiceImpl implements TransferService
|
||||
private static final String MSG_NO_GROUP = "transfer_service.unable_to_find_transfer_group";
|
||||
private static final String MSG_NO_TARGET = "transfer_service.unable_to_find_transfer_target";
|
||||
private static final String MSG_TARGET_EXISTS = "transfer_service.target_exists";
|
||||
private static final String MSG_CANCELLED = "transfer_service.cancelled";
|
||||
private static final String MSG_NO_NODES = "transfer_service.no_nodes";
|
||||
|
||||
/**
|
||||
* The synchronised list of transfers in progress.
|
||||
*/
|
||||
private Map<String, TransferStatus> transferMonitoring = Collections.synchronizedMap(new HashMap<String,TransferStatus>());
|
||||
|
||||
private static Log logger = LogFactory.getLog(TransferServiceImpl.class);
|
||||
|
||||
public void init()
|
||||
@@ -125,6 +136,11 @@ public class TransferServiceImpl implements TransferService
|
||||
private TransferManifestNodeFactory transferManifestNodeFactory;
|
||||
private TransferReporter transferReporter;
|
||||
|
||||
/**
|
||||
* How long to delay while polling for commit status.
|
||||
*/
|
||||
private long commitPollDelay = 2000;
|
||||
|
||||
/**
|
||||
* create transfer target
|
||||
*/
|
||||
@@ -269,6 +285,11 @@ public class TransferServiceImpl implements TransferService
|
||||
nodeService.setProperty(nodeRef, TransferModel.PROP_ENABLED, new Boolean(enable));
|
||||
}
|
||||
|
||||
public boolean targetExists(String name)
|
||||
{
|
||||
return (lookupTransferTarget(name) != null);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@@ -321,7 +342,7 @@ public class TransferServiceImpl implements TransferService
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Transfer sync without callbacks.
|
||||
*/
|
||||
public NodeRef transfer(String targetName, TransferDefinition definition)
|
||||
{
|
||||
@@ -335,8 +356,22 @@ public class TransferServiceImpl implements TransferService
|
||||
* @param targetName
|
||||
* @param definition
|
||||
* @param callbacks
|
||||
*
|
||||
*/
|
||||
public void transferAsync(String targetName, TransferDefinition definition, Set<TransferCallback> callbacks)
|
||||
public void transferAsync(String targetName, TransferDefinition definition, TransferCallback... callbacks)
|
||||
{
|
||||
transferAsync(targetName, definition, Arrays.asList(callbacks));
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfer async.
|
||||
*
|
||||
* @param targetName
|
||||
* @param definition
|
||||
* @param callbacks
|
||||
*
|
||||
*/
|
||||
public void transferAsync(String targetName, TransferDefinition definition, Collection<TransferCallback> callbacks)
|
||||
{
|
||||
/**
|
||||
* Event processor for this transfer instance
|
||||
@@ -399,7 +434,20 @@ public class TransferServiceImpl implements TransferService
|
||||
* @param definition
|
||||
* @param callbacks
|
||||
*/
|
||||
public NodeRef transfer(String targetName, TransferDefinition definition, Set<TransferCallback> callbacks)
|
||||
public NodeRef transfer(String targetName, TransferDefinition definition, TransferCallback... callbacks)
|
||||
{
|
||||
return transfer(targetName, definition, Arrays.asList(callbacks));
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfer Synchronous
|
||||
*
|
||||
* @param targetName
|
||||
* @param definition
|
||||
* @param callbacks
|
||||
*/
|
||||
|
||||
public NodeRef transfer(String targetName, TransferDefinition definition, Collection<TransferCallback> callbacks)
|
||||
{
|
||||
/**
|
||||
* Event processor for this transfer instance
|
||||
@@ -425,15 +473,13 @@ public class TransferServiceImpl implements TransferService
|
||||
*/
|
||||
private NodeRef transferImpl(String targetName, final TransferDefinition definition, final TransferEventProcessor eventProcessor)
|
||||
{
|
||||
NodeRef reportNode = null;
|
||||
|
||||
if(logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("transfer started to :" + targetName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wire in the transferReport
|
||||
* Wire in the transferReport - so any callbacks are stored in transferReport
|
||||
*/
|
||||
final List<TransferEvent> transferReport = new LinkedList<TransferEvent>();
|
||||
TransferCallback reportCallback = new TransferCallback()
|
||||
@@ -468,8 +514,6 @@ public class TransferServiceImpl implements TransferService
|
||||
String prefix = "TRX-SNAP";
|
||||
String suffix = ".xml";
|
||||
|
||||
long numberOfNodes = 0;
|
||||
|
||||
logger.debug("create snapshot");
|
||||
|
||||
// where to put snapshot ?
|
||||
@@ -481,13 +525,13 @@ public class TransferServiceImpl implements TransferService
|
||||
TransferManifestWriter formatter = new XMLTransferManifestWriter();
|
||||
TransferManifestHeader header = new TransferManifestHeader();
|
||||
header.setCreatedDate(new Date());
|
||||
header.setNodeCount(nodes.size());
|
||||
formatter.startTransferManifest(snapshotWriter);
|
||||
formatter.writeTransferManifestHeader(header);
|
||||
for(NodeRef nodeRef : nodes)
|
||||
{
|
||||
TransferManifestNode node = transferManifestNodeFactory.createTransferManifestNode(nodeRef);
|
||||
formatter.writeTransferManifestNode(node);
|
||||
numberOfNodes++;
|
||||
}
|
||||
formatter.endTransferManifest();
|
||||
snapshotWriter.close();
|
||||
@@ -500,8 +544,10 @@ public class TransferServiceImpl implements TransferService
|
||||
{
|
||||
outputFile(snapshotFile);
|
||||
}
|
||||
catch (Exception error)
|
||||
catch (IOException error)
|
||||
{
|
||||
// This is debug code - so an exception thrown while debugging
|
||||
logger.debug("error while outputting snapshotFile");
|
||||
error.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -509,15 +555,22 @@ public class TransferServiceImpl implements TransferService
|
||||
/**
|
||||
* Begin
|
||||
*/
|
||||
logger.debug("transfer begin");
|
||||
eventProcessor.start();
|
||||
final Transfer transfer = transmitter.begin(target);
|
||||
if(transfer != null)
|
||||
{
|
||||
logger.debug("transfer begin");
|
||||
String transferId = transfer.getTransferId();
|
||||
TransferStatus status = new TransferStatus(transferId);
|
||||
transferMonitoring.put(transferId, status);
|
||||
logger.debug("transfer begun transferId:" + transferId);
|
||||
|
||||
boolean prepared = false;
|
||||
try
|
||||
{
|
||||
eventProcessor.begin(transferId);
|
||||
checkCancel(transferId);
|
||||
|
||||
/**
|
||||
* send Manifest
|
||||
*/
|
||||
@@ -528,16 +581,19 @@ public class TransferServiceImpl implements TransferService
|
||||
|
||||
/**
|
||||
* Parse the manifest file and transfer chunks over
|
||||
*
|
||||
* ManifestFile -> Manifest Processor -> Chunker -> Transmitter
|
||||
*
|
||||
* Step 1: Create a chunker and wire it up to the transmitter
|
||||
*/
|
||||
|
||||
// create a chunker and wire it up to the transmitter
|
||||
final ContentChunker chunker = new ContentChunkerImpl();
|
||||
final Long fRange = Long.valueOf(numberOfNodes);
|
||||
final Long fRange = Long.valueOf(nodes.size());
|
||||
chunker.setHandler(
|
||||
new ContentChunkProcessor(){
|
||||
private long counter = 0;
|
||||
public void processChunk(Set<ContentData> data)
|
||||
{
|
||||
checkCancel(transfer.getTransferId());
|
||||
logger.debug("send chunk to transmitter");
|
||||
for(ContentData file : data)
|
||||
{
|
||||
@@ -549,8 +605,9 @@ public class TransferServiceImpl implements TransferService
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
// create a manifest processor and wire it up to the chunker
|
||||
/**
|
||||
* Step 2 : create a manifest processor and wire it up to the chunker
|
||||
*/
|
||||
TransferManifestProcessor processor = new TransferManifestProcessor()
|
||||
{
|
||||
public void processTransferManifestNode(TransferManifestNormalNode node)
|
||||
@@ -558,6 +615,7 @@ public class TransferServiceImpl implements TransferService
|
||||
Set<ContentData> data = TransferManifestNodeHelper.getContentData(node);
|
||||
for(ContentData d : data)
|
||||
{
|
||||
checkCancel(transfer.getTransferId());
|
||||
logger.debug("add content to chunker");
|
||||
chunker.addContent(d);
|
||||
}
|
||||
@@ -571,68 +629,103 @@ public class TransferServiceImpl implements TransferService
|
||||
}
|
||||
};
|
||||
|
||||
// wire up the manifest parser to a manifest processor
|
||||
/**
|
||||
* Step 3: wire up the manifest reader to a manifest processor
|
||||
*/
|
||||
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
|
||||
SAXParser parser;
|
||||
parser = saxParserFactory.newSAXParser();
|
||||
XMLTransferManifestReader reader = new XMLTransferManifestReader(processor);
|
||||
|
||||
// start the magic
|
||||
/**
|
||||
* Step 4: start the magic Give the manifest file to the manifest reader
|
||||
*/
|
||||
parser.parse(snapshotFile, reader);
|
||||
|
||||
chunker.flush();
|
||||
|
||||
/**
|
||||
* Content all sent over
|
||||
*/
|
||||
logger.debug("content sending finished");
|
||||
checkCancel(transfer.getTransferId());
|
||||
|
||||
/**
|
||||
* prepare
|
||||
*/
|
||||
eventProcessor.prepare();
|
||||
transmitter.prepare(transfer);
|
||||
logger.debug("prepared");
|
||||
logger.debug("prepared transferId:" + transferId);
|
||||
checkCancel(transfer.getTransferId());
|
||||
|
||||
/**
|
||||
* committing
|
||||
*/
|
||||
eventProcessor.committing(100, 0);
|
||||
eventProcessor.commit();
|
||||
transmitter.commit(transfer);
|
||||
logger.debug("committing transferId:" + transferId);
|
||||
checkCancel(transfer.getTransferId());
|
||||
|
||||
/**
|
||||
* need to poll for status
|
||||
* need to poll for committed status
|
||||
*/
|
||||
// transmitter.getCommitStatus(transfer);
|
||||
TransferProgress progress = null;
|
||||
|
||||
eventProcessor.committing(100, 50);
|
||||
eventProcessor.committing(100, 100);
|
||||
int position = -1;
|
||||
for(int retries = 0; retries < 3; retries++)
|
||||
{
|
||||
checkCancel(transfer.getTransferId());
|
||||
try
|
||||
{
|
||||
progress = transmitter.getStatus(transfer);
|
||||
if(progress.getCurrentPosition() != position)
|
||||
{
|
||||
position = progress.getCurrentPosition();
|
||||
eventProcessor.committing(progress.getEndPosition(), position);
|
||||
}
|
||||
if(progress.isFinished())
|
||||
{
|
||||
logger.debug("isFinished=true");
|
||||
break;
|
||||
}
|
||||
retries = 0;
|
||||
}
|
||||
catch (TransferException te)
|
||||
{
|
||||
logger.debug("error while committing - retrying", te);
|
||||
}
|
||||
|
||||
/**
|
||||
* Now sleep for a while.
|
||||
*/
|
||||
Thread.sleep(commitPollDelay);
|
||||
}
|
||||
logger.debug("Finished transferId:" + transferId);
|
||||
|
||||
checkCancel(transfer.getTransferId());
|
||||
|
||||
/**
|
||||
* committed
|
||||
*/
|
||||
//eventProcessor.serverMessage("Committed");
|
||||
|
||||
eventProcessor.success();
|
||||
|
||||
checkCancel(transfer.getTransferId());
|
||||
prepared = true;
|
||||
|
||||
logger.debug("committed");
|
||||
logger.debug("committed - write transfer report transferId:" + transferId);
|
||||
|
||||
// Write the Successful transfer report if we get here
|
||||
// in its own transaction so it cannot be rolled back
|
||||
final TransferTarget fTarget = target;
|
||||
reportNode = transactionService.getRetryingTransactionHelper().doInTransaction(
|
||||
new RetryingTransactionHelper.RetryingTransactionCallback<NodeRef>()
|
||||
{
|
||||
public NodeRef execute() throws Throwable
|
||||
{
|
||||
logger.debug("transfer report starting");
|
||||
NodeRef reportNode = transferReporter.createTransferReport(transfer, fTarget, definition, transferReport);
|
||||
logger.debug("transfer report done");
|
||||
return reportNode;
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Write the Successful transfer report if we get here
|
||||
*/
|
||||
NodeRef reportNode = persistTransferReport(transfer, target, definition, transferReport, snapshotFile);
|
||||
|
||||
logger.debug("success - at end of method transferId:" + transferId);
|
||||
return reportNode;
|
||||
}
|
||||
finally
|
||||
{
|
||||
logger.debug("remove monitoring for transferId:" + transferId);
|
||||
transferMonitoring.remove(transferId);
|
||||
logger.debug("removed monitoring for transferId:" + transferId);
|
||||
|
||||
if(!prepared)
|
||||
{
|
||||
logger.debug("abort incomplete transfer");
|
||||
@@ -640,33 +733,42 @@ public class TransferServiceImpl implements TransferService
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO Do we ever get here ?
|
||||
logger.debug("returning null - unable lock target");
|
||||
return null;
|
||||
}
|
||||
catch (TransferException t)
|
||||
{
|
||||
logger.debug("TransferException - unable to transfer", t);
|
||||
eventProcessor.error(t);
|
||||
|
||||
/**
|
||||
* Write the transfer report. This is an error report so needs to be out
|
||||
*/
|
||||
if(target != null && reportNode!= null)
|
||||
if(target != null )
|
||||
{
|
||||
// reportNode = transferReporter.createTransferReport(target, definition, transferReport);
|
||||
persistTransferReport(t, target, definition, transferReport, snapshotFile);
|
||||
}
|
||||
throw t;
|
||||
}
|
||||
catch (Exception t)
|
||||
{
|
||||
// Wrap any other exception as a transfer exception
|
||||
logger.debug("unable to transfer", t);
|
||||
logger.debug("Exception - unable to transfer", t);
|
||||
eventProcessor.error(t);
|
||||
|
||||
/**
|
||||
* Write the transfer report. This is an error report so needs to be out
|
||||
*/
|
||||
if(target != null && reportNode!= null)
|
||||
if(target != null )
|
||||
{
|
||||
// reportNode = transferReporter.createTransferReport(target, definition, transferReport);
|
||||
persistTransferReport(t, target, definition, transferReport, snapshotFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the exception as a transfer exception
|
||||
*/
|
||||
throw new TransferException("unable to transfer:" + t.toString(), t);
|
||||
}
|
||||
finally
|
||||
@@ -678,11 +780,40 @@ public class TransferServiceImpl implements TransferService
|
||||
{
|
||||
snapshotFile.delete();
|
||||
}
|
||||
logger.debug("snapshot file deleted");
|
||||
}
|
||||
|
||||
return reportNode;
|
||||
} // end of transferImpl
|
||||
|
||||
/**
|
||||
* CancelAsync
|
||||
*/
|
||||
public void cancelAsync(String transferHandle)
|
||||
{
|
||||
TransferStatus status = transferMonitoring.get(transferHandle);
|
||||
if(status != null)
|
||||
{
|
||||
logger.debug("canceling transfer :" + transferHandle);
|
||||
status.cancelMe = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the specified transfer should be cancelled.
|
||||
* @param transferHandle
|
||||
* @throws TransferException - the transfer has been cancelled.
|
||||
*/
|
||||
private void checkCancel(String transferHandle) throws TransferException
|
||||
{
|
||||
TransferStatus status = transferMonitoring.get(transferHandle);
|
||||
if(status != null)
|
||||
{
|
||||
if(status.cancelMe)
|
||||
{
|
||||
throw new TransferException(MSG_CANCELLED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
@@ -836,7 +967,7 @@ public class TransferServiceImpl implements TransferService
|
||||
* Utility to dump the contents of a file to the console
|
||||
* @param file
|
||||
*/
|
||||
private static void outputFile(File file) throws Exception
|
||||
private static void outputFile(File file) throws IOException
|
||||
{
|
||||
BufferedReader reader = new BufferedReader(new FileReader(file));
|
||||
String s = reader.readLine();
|
||||
@@ -847,6 +978,48 @@ public class TransferServiceImpl implements TransferService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Success transfer report
|
||||
*/
|
||||
private NodeRef persistTransferReport(final Transfer transfer, final TransferTarget target, final TransferDefinition definition, final List<TransferEvent> events, final File snapshotFile)
|
||||
{
|
||||
/**
|
||||
* persist the transfer report in its own transaction so it cannot be rolled back
|
||||
*/
|
||||
NodeRef reportNode = transactionService.getRetryingTransactionHelper().doInTransaction(
|
||||
new RetryingTransactionHelper.RetryingTransactionCallback<NodeRef>()
|
||||
{
|
||||
public NodeRef execute() throws Throwable
|
||||
{
|
||||
logger.debug("transfer report starting");
|
||||
NodeRef reportNode = transferReporter.createTransferReport(transfer, target, definition, events, snapshotFile);
|
||||
logger.debug("transfer report done");
|
||||
return reportNode;
|
||||
}
|
||||
}, false, true);
|
||||
return reportNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Error Transfer report
|
||||
*/
|
||||
private NodeRef persistTransferReport(final Exception t, final TransferTarget target, final TransferDefinition definition, final List<TransferEvent> events, final File snapshotFile)
|
||||
{
|
||||
// in its own transaction so it cannot be rolled back
|
||||
NodeRef reportNode = transactionService.getRetryingTransactionHelper().doInTransaction(
|
||||
new RetryingTransactionHelper.RetryingTransactionCallback<NodeRef>()
|
||||
{
|
||||
public NodeRef execute() throws Throwable
|
||||
{
|
||||
logger.debug("transfer report starting");
|
||||
NodeRef reportNode = transferReporter.createTransferReport(t, target, definition, events, snapshotFile);
|
||||
logger.debug("transfer report done");
|
||||
return reportNode;
|
||||
}
|
||||
}, false, true);
|
||||
return reportNode;
|
||||
}
|
||||
|
||||
public void setTransferManifestNodeFactory(TransferManifestNodeFactory transferManifestNodeFactory)
|
||||
{
|
||||
this.transferManifestNodeFactory = transferManifestNodeFactory;
|
||||
@@ -886,4 +1059,24 @@ public class TransferServiceImpl implements TransferService
|
||||
{
|
||||
return transferReporter;
|
||||
}
|
||||
|
||||
public void setCommitPollDelay(long commitPollDelay)
|
||||
{
|
||||
this.commitPollDelay = commitPollDelay;
|
||||
}
|
||||
|
||||
public long getCommitPollDelay()
|
||||
{
|
||||
return commitPollDelay;
|
||||
}
|
||||
|
||||
private class TransferStatus
|
||||
{
|
||||
TransferStatus(String transferId)
|
||||
{
|
||||
this.transferId = transferId;
|
||||
}
|
||||
String transferId;
|
||||
boolean cancelMe = false;
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
29
source/java/org/alfresco/repo/transfer/TransferTestUtil.java
Normal file
29
source/java/org/alfresco/repo/transfer/TransferTestUtil.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package org.alfresco.repo.transfer;
|
||||
|
||||
import org.alfresco.service.cmr.transfer.TransferService;
|
||||
import org.alfresco.service.cmr.transfer.TransferTarget;
|
||||
|
||||
public class TransferTestUtil
|
||||
{
|
||||
private final static String TEST_TARGET_NAME = "TestTarget";
|
||||
|
||||
private TransferTestUtil()
|
||||
{
|
||||
// Static methods only
|
||||
}
|
||||
|
||||
public static TransferTarget getTestTarget(TransferService transferService)
|
||||
{
|
||||
TransferTarget target;
|
||||
if (!transferService.targetExists(TEST_TARGET_NAME))
|
||||
{
|
||||
target = transferService.createTransferTarget(TEST_TARGET_NAME, "Test Target", "Test Target", "http",
|
||||
"localhost", 8090, "/alfresco/service/api/transfer", "admin", "admin".toCharArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
target = transferService.getTransferTarget(TEST_TARGET_NAME);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
}
|
@@ -31,6 +31,7 @@ import java.util.Set;
|
||||
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.transfer.TransferException;
|
||||
import org.alfresco.service.cmr.transfer.TransferProgress;
|
||||
import org.alfresco.service.cmr.transfer.TransferTarget;
|
||||
|
||||
/**
|
||||
@@ -93,6 +94,11 @@ public interface TransferTransmitter
|
||||
*/
|
||||
void abort(Transfer transfer) throws TransferException;
|
||||
|
||||
/**
|
||||
* Get the status of an in process transfer
|
||||
*/
|
||||
TransferProgress getStatus(Transfer transfer) throws TransferException;
|
||||
|
||||
/**
|
||||
* Get Async Messages for a transfer.
|
||||
* Server Side Messages.
|
||||
|
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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 java.util.Set;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.action.executer.ActionExecuterAbstractBase;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
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.NodeCrawler;
|
||||
import org.alfresco.service.cmr.transfer.TransferDefinition;
|
||||
import org.alfresco.service.cmr.transfer.TransferService;
|
||||
import org.alfresco.service.cmr.transfer.TransferTarget;
|
||||
|
||||
/**
|
||||
* @author brian
|
||||
*
|
||||
*/
|
||||
public class TransferTreeActionExecuter extends ActionExecuterAbstractBase
|
||||
{
|
||||
public static final String NAME = "transfer-this-tree";
|
||||
private TransferService transferService;
|
||||
private ServiceRegistry serviceRegistry;
|
||||
|
||||
/**
|
||||
* @param transferService the transferService to set
|
||||
*/
|
||||
public void setTransferService(TransferService transferService)
|
||||
{
|
||||
this.transferService = transferService;
|
||||
}
|
||||
|
||||
public void setServiceRegistry(ServiceRegistry serviceRegistry)
|
||||
{
|
||||
this.serviceRegistry = serviceRegistry;
|
||||
}
|
||||
|
||||
/* (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)
|
||||
{
|
||||
TransferTarget target = TransferTestUtil.getTestTarget(transferService);
|
||||
NodeCrawler crawler = new StandardNodeCrawlerImpl(serviceRegistry);
|
||||
crawler.setNodeFinders(new ChildAssociatedNodeFinder(ContentModel.ASSOC_CONTAINS));
|
||||
Set<NodeRef> nodes = crawler.crawl(actionedUponNodeRef);
|
||||
TransferDefinition td = new TransferDefinition();
|
||||
td.setNodes(nodes);
|
||||
transferService.transfer(target.getName(), td);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addParameterDefinitions(List<ParameterDefinition> paramList)
|
||||
{
|
||||
}
|
||||
}
|
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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 java.util.Set;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.action.executer.ActionExecuterAbstractBase;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
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.NodeCrawler;
|
||||
import org.alfresco.service.cmr.transfer.TransferCallback;
|
||||
import org.alfresco.service.cmr.transfer.TransferDefinition;
|
||||
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.TransferService;
|
||||
import org.alfresco.service.cmr.transfer.TransferTarget;
|
||||
|
||||
/**
|
||||
* @author brian
|
||||
*
|
||||
*/
|
||||
public class TransferTreeWithCancelActionExecuter extends ActionExecuterAbstractBase
|
||||
{
|
||||
public static final String NAME = "transfer-tree-with-cancel";
|
||||
private TransferService transferService;
|
||||
private ServiceRegistry serviceRegistry;
|
||||
|
||||
/**
|
||||
* @param transferService the transferService to set
|
||||
*/
|
||||
public void setTransferService(TransferService transferService)
|
||||
{
|
||||
this.transferService = transferService;
|
||||
}
|
||||
|
||||
public void setServiceRegistry(ServiceRegistry serviceRegistry)
|
||||
{
|
||||
this.serviceRegistry = serviceRegistry;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@Override
|
||||
protected void executeImpl(Action action, NodeRef actionedUponNodeRef)
|
||||
{
|
||||
TransferTarget target = serviceRegistry.getTransactionService().getRetryingTransactionHelper().doInTransaction(
|
||||
new RetryingTransactionHelper.RetryingTransactionCallback<TransferTarget>()
|
||||
{
|
||||
public TransferTarget execute() throws Throwable
|
||||
{
|
||||
return TransferTestUtil.getTestTarget(transferService);
|
||||
}
|
||||
}, false, true);
|
||||
|
||||
NodeCrawler crawler = new StandardNodeCrawlerImpl(serviceRegistry);
|
||||
crawler.setNodeFinders(new ChildAssociatedNodeFinder(ContentModel.ASSOC_CONTAINS));
|
||||
Set<NodeRef> nodes = crawler.crawl(actionedUponNodeRef);
|
||||
TransferDefinition td = new TransferDefinition();
|
||||
td.setNodes(nodes);
|
||||
transferService.transferAsync(target.getName(), td, new TransferCallback(){
|
||||
|
||||
private String transferId;
|
||||
|
||||
public void processEvent(TransferEvent event)
|
||||
{
|
||||
if (event instanceof TransferEventBegin)
|
||||
{
|
||||
transferId = ((TransferEventBegin)event).getTransferId();
|
||||
}
|
||||
else if (event instanceof TransferEventCommittingStatus)
|
||||
{
|
||||
transferService.cancelAsync(transferId);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addParameterDefinitions(List<ParameterDefinition> paramList)
|
||||
{
|
||||
}
|
||||
}
|
@@ -33,11 +33,14 @@ import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
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.TransferReceiver;
|
||||
import org.alfresco.service.cmr.transfer.TransferTarget;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
|
||||
/**
|
||||
* This class delegates transfer service to the transfer receiver without
|
||||
@@ -53,32 +56,54 @@ public class UnitTestInProcessTransmitterImpl implements TransferTransmitter
|
||||
private TransferReceiver receiver;
|
||||
|
||||
private ContentService contentService;
|
||||
private TransactionService transactionService;
|
||||
|
||||
public UnitTestInProcessTransmitterImpl(TransferReceiver receiver, ContentService contentService)
|
||||
public UnitTestInProcessTransmitterImpl(TransferReceiver receiver, ContentService contentService, TransactionService transactionService)
|
||||
{
|
||||
this.receiver = receiver;
|
||||
this.contentService = contentService;
|
||||
this.transactionService = transactionService;
|
||||
}
|
||||
|
||||
public Transfer begin(TransferTarget target) throws TransferException
|
||||
public Transfer begin(final TransferTarget target) throws TransferException
|
||||
{
|
||||
Transfer transfer = new Transfer();
|
||||
String transferId = receiver.start();
|
||||
transfer.setTransferId(transferId);
|
||||
transfer.setTransferTarget(target);
|
||||
return transfer;
|
||||
return transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Transfer>()
|
||||
{
|
||||
public Transfer execute() throws Throwable
|
||||
{
|
||||
Transfer transfer = new Transfer();
|
||||
String transferId = receiver.start();
|
||||
transfer.setTransferId(transferId);
|
||||
transfer.setTransferTarget(target);
|
||||
return transfer;
|
||||
}
|
||||
}, false, true);
|
||||
}
|
||||
|
||||
public void abort(Transfer transfer) throws TransferException
|
||||
public void abort(final Transfer transfer) throws TransferException
|
||||
{
|
||||
String transferId = transfer.getTransferId();
|
||||
receiver.abort(transferId);
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Transfer>()
|
||||
{
|
||||
public Transfer execute() throws Throwable
|
||||
{
|
||||
String transferId = transfer.getTransferId();
|
||||
receiver.cancel(transferId);
|
||||
return null;
|
||||
}
|
||||
}, false, true);
|
||||
}
|
||||
|
||||
public void commit(Transfer transfer) throws TransferException
|
||||
public void commit(final Transfer transfer) throws TransferException
|
||||
{
|
||||
String transferId = transfer.getTransferId();
|
||||
receiver.commit(transferId);
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback<Transfer>()
|
||||
{
|
||||
public Transfer execute() throws Throwable
|
||||
{
|
||||
String transferId = transfer.getTransferId();
|
||||
receiver.commit(transferId);
|
||||
return null;
|
||||
}
|
||||
}, false, true);
|
||||
}
|
||||
|
||||
public Set<TransferMessage> getMessages(Transfer transfer)
|
||||
@@ -128,6 +153,12 @@ public class UnitTestInProcessTransmitterImpl implements TransferTransmitter
|
||||
|
||||
}
|
||||
|
||||
public TransferProgress getStatus(Transfer transfer) throws TransferException
|
||||
{
|
||||
String transferId = transfer.getTransferId();
|
||||
return receiver.getStatus(transferId);
|
||||
}
|
||||
|
||||
public void setReceiver(TransferReceiver receiver)
|
||||
{
|
||||
this.receiver = receiver;
|
||||
@@ -147,4 +178,6 @@ public class UnitTestInProcessTransmitterImpl implements TransferTransmitter
|
||||
{
|
||||
return contentService;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -25,7 +25,6 @@
|
||||
package org.alfresco.repo.transfer.manifest;
|
||||
|
||||
import org.alfresco.repo.transfer.TransferModel;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* The transfer model - extended for XML Manifest Model
|
||||
@@ -35,6 +34,7 @@ public interface ManifestModel extends TransferModel
|
||||
static final String LOCALNAME_TRANSFER_MAINIFEST = "transferManifest";
|
||||
static final String LOCALNAME_TRANSFER_HEADER = "transferManifestHeader";
|
||||
static final String LOCALNAME_HEADER_CREATED_DATE = "createdDate";
|
||||
static final String LOCALNAME_HEADER_NODE_COUNT = "nodeCount";
|
||||
static final String LOCALNAME_ELEMENT_NODES = "nodes";
|
||||
static final String LOCALNAME_ELEMENT_NODE = "node";
|
||||
static final String LOCALNAME_ELEMENT_DELETED_NODE = "deletedNode";
|
||||
@@ -52,7 +52,9 @@ public interface ManifestModel extends TransferModel
|
||||
static final String LOCALNAME_ELEMENT_PRIMARY_PARENT = "primaryParent";
|
||||
static final String LOCALNAME_ELEMENT_PRIMARY_PATH = "primaryPath";
|
||||
static final String LOCALNAME_ELEMENT_VALUES = "values";
|
||||
static final String LOCALNAME_ELEMENT_VALUE = "value";
|
||||
static final String LOCALNAME_ELEMENT_VALUE_STRING = "value";
|
||||
static final String LOCALNAME_ELEMENT_VALUE_NULL = "nullValue";
|
||||
static final String LOCALNAME_ELEMENT_VALUE_SERIALIZED = "serializedValue";
|
||||
static final String LOCALNAME_ELEMENT_MLVALUE = "mlvalue";
|
||||
static final String LOCALNAME_ELEMENT_CONTENT_HEADER = "content";
|
||||
|
||||
|
@@ -35,6 +35,7 @@ import java.util.Date;
|
||||
public class TransferManifestHeader
|
||||
{
|
||||
private Date createdDate;
|
||||
private int nodeCount;
|
||||
|
||||
public void setCreatedDate(Date createDate)
|
||||
{
|
||||
@@ -46,4 +47,20 @@ public class TransferManifestHeader
|
||||
return createdDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the nodeCount
|
||||
*/
|
||||
public int getNodeCount()
|
||||
{
|
||||
return nodeCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nodeCount the nodeCount to set
|
||||
*/
|
||||
public void setNodeCount(int nodeCount)
|
||||
{
|
||||
this.nodeCount = nodeCount;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -57,6 +57,11 @@ import junit.framework.TestCase;
|
||||
|
||||
public class TransferManifestTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* This unit test creates and reads a manifest.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testCreateAndReadSnapshot() throws Exception
|
||||
{
|
||||
/**
|
||||
@@ -78,7 +83,8 @@ public class TransferManifestTest extends TestCase
|
||||
|
||||
// node to transmit
|
||||
TransferManifestNormalNode node = new TransferManifestNormalNode();
|
||||
node.setNodeRef(new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "123"));
|
||||
NodeRef nodeRefA = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "123");
|
||||
node.setNodeRef(nodeRefA);
|
||||
node.setParentPath(new Path());
|
||||
Set<QName> aspects = new HashSet<QName>();
|
||||
aspects.add(QName.createQName("{gsxhjsx}", "cm:wobble"));
|
||||
@@ -86,17 +92,70 @@ public class TransferManifestTest extends TestCase
|
||||
node.setAspects(aspects);
|
||||
|
||||
Map<QName, Serializable> properties = new HashMap<QName, Serializable>();
|
||||
|
||||
/**
|
||||
* String type
|
||||
*/
|
||||
properties.put(QName.createQName("{gsxhjsx}", "cm:name"), "brian.jpg");
|
||||
|
||||
/**
|
||||
* Date type
|
||||
*/
|
||||
properties.put(QName.createQName("{gsxhjsx}", "cm:created"), new java.util.Date());
|
||||
|
||||
/**
|
||||
* Boolean type
|
||||
*/
|
||||
properties.put(QName.createQName("{gsxhjsx}", "trx:enabled"), Boolean.FALSE);
|
||||
|
||||
/**
|
||||
* MLText value
|
||||
*/
|
||||
MLText mltext = new MLText();
|
||||
mltext.addValue(Locale.FRENCH, "Bonjour");
|
||||
mltext.addValue(Locale.ENGLISH, "Hello");
|
||||
mltext.addValue(Locale.ITALY, "Buongiorno");
|
||||
properties.put(QName.createQName("{gsxhjsx}", "cm:title"), mltext);
|
||||
String password = "helloWorld";
|
||||
|
||||
/**
|
||||
* Put a char array type
|
||||
*/
|
||||
properties.put(QName.createQName("{gsxhjsx}", "trx:password"), password.toCharArray());
|
||||
|
||||
/**
|
||||
* Put an ArrayList type
|
||||
*/
|
||||
ArrayList a1 = new ArrayList();
|
||||
a1.add("Rhubarb");
|
||||
a1.add("Custard");
|
||||
properties.put(QName.createQName("{gsxhjsx}", "trx:arrayList"), a1);
|
||||
|
||||
/**
|
||||
* Put a HashMap type
|
||||
*/
|
||||
HashMap m1 = new HashMap();
|
||||
m1.put("Rhubarb", "Rhubarb");
|
||||
m1.put("Custard", "Custard");
|
||||
properties.put(QName.createQName("{gsxhjsx}", "trx:hashMap"), m1);
|
||||
|
||||
/**
|
||||
* Put a null value
|
||||
*/
|
||||
properties.put(QName.createQName("{gsxhjsx}", "cm:nullTest"), null);
|
||||
|
||||
/**
|
||||
* Put a node ref property
|
||||
*/
|
||||
properties.put(QName.createQName("{gsxhjsx}", "trx:nodeRef"), new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, "P1"));
|
||||
|
||||
/**
|
||||
* Put an obscure "unknown type".
|
||||
*/
|
||||
// TestPrivateBean obscure = new TestPrivateBean();
|
||||
// obscure.a = "hello";
|
||||
// obscure.b = "world";
|
||||
// properties.put(QName.createQName("{gsxhjsx}", "cm:obscure"), obscure);
|
||||
|
||||
List<ChildAssociationRef> parents = new ArrayList<ChildAssociationRef>();
|
||||
ChildAssociationRef primaryParent = new ChildAssociationRef(QName.createQName("{gsxhjsx}", "cm:contains"),
|
||||
@@ -201,14 +260,68 @@ public class TransferManifestTest extends TestCase
|
||||
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
|
||||
SAXParser parser = saxParserFactory.newSAXParser();
|
||||
|
||||
TransferManifestProcessor tp = new TestTransferManifestProcessor();
|
||||
TestTransferManifestProcessor tp = new TestTransferManifestProcessor();
|
||||
|
||||
XMLTransferManifestReader xmlReader = new XMLTransferManifestReader(tp);
|
||||
parser.parse(snapshotFile, xmlReader );
|
||||
|
||||
/**
|
||||
* Now validate the parsed data.
|
||||
*/
|
||||
|
||||
Map<NodeRef, TransferManifestNode> nodes = tp.getNodes();
|
||||
|
||||
TransferManifestNormalNode rxNodeA = (TransferManifestNormalNode)nodes.get(nodeRefA);
|
||||
|
||||
assertNotNull("rxNodeA is null", rxNodeA);
|
||||
|
||||
Map<QName, Serializable> rxNodeAProps = rxNodeA.getProperties();
|
||||
System.out.println(rxNodeAProps.get(QName.createQName("{gsxhjsx}", "trx:password")));
|
||||
for(Map.Entry value : rxNodeAProps.entrySet())
|
||||
{
|
||||
System.out.println("key = " + value.getKey() + " value =" + value.getValue());
|
||||
if(value.getValue() != null)
|
||||
{
|
||||
if(value.getValue().getClass().isArray())
|
||||
{
|
||||
System.out.println("arrayValue="+ value.getValue().toString());
|
||||
char[] chars = (char[])value.getValue();
|
||||
|
||||
System.out.println(chars);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tp.getHeader();
|
||||
|
||||
snapshotFile.delete();
|
||||
}
|
||||
|
||||
public class TestPrivateBean implements Serializable
|
||||
{
|
||||
public TestPrivateBean()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void setA(String a)
|
||||
{
|
||||
this.a = a;
|
||||
}
|
||||
public String getA()
|
||||
{
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1053132227110567282L;
|
||||
private String a;
|
||||
private String b;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -24,6 +24,10 @@
|
||||
*/
|
||||
package org.alfresco.repo.transfer.manifest;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
@@ -33,21 +37,18 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.alfresco.repo.transfer.PathHelper;
|
||||
import org.alfresco.service.cmr.repository.Path;
|
||||
|
||||
import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.repository.MLText;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.Path;
|
||||
import org.alfresco.service.namespace.NamespaceException;
|
||||
import org.alfresco.service.namespace.NamespacePrefixResolver;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.ISO9075;
|
||||
import org.springframework.extensions.surf.util.Base64;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
import org.springframework.extensions.surf.util.ISO8601DateFormat;
|
||||
import org.xml.sax.Attributes;
|
||||
@@ -56,8 +57,6 @@ import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* SAX XML Content Handler to read a transfer manifest XML Stream and
|
||||
* delegate processing to the specified TransferManifestProcessor
|
||||
@@ -150,22 +149,19 @@ public class XMLTransferManifestReader extends DefaultHandler implements Content
|
||||
{
|
||||
// Good we got this
|
||||
}
|
||||
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_TRANSFER_HEADER))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_TRANSFER_HEADER))
|
||||
{
|
||||
TransferManifestHeader header = new TransferManifestHeader();
|
||||
props.put("header", header);
|
||||
}
|
||||
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_DELETED_NODE))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_DELETED_NODE))
|
||||
{
|
||||
TransferManifestDeletedNode node = new TransferManifestDeletedNode();
|
||||
NodeRef nodeRef = new NodeRef(atts.getValue("", "nodeRef"));
|
||||
node.setNodeRef(nodeRef);
|
||||
props.put("node", node);
|
||||
}
|
||||
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_NODE))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_NODE))
|
||||
{
|
||||
TransferManifestNormalNode node = new TransferManifestNormalNode();
|
||||
NodeRef nodeRef = new NodeRef(atts.getValue("", "nodeRef"));
|
||||
@@ -174,50 +170,47 @@ public class XMLTransferManifestReader extends DefaultHandler implements Content
|
||||
node.setType(type);
|
||||
props.put("node", node);
|
||||
}
|
||||
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_ASPECTS))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_ASPECTS))
|
||||
{
|
||||
TransferManifestNormalNode node = (TransferManifestNormalNode)props.get("node");
|
||||
node.setAspects(new HashSet<QName>());
|
||||
}
|
||||
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_ASPECT))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_ASPECT))
|
||||
{
|
||||
buffer = new StringBuffer();
|
||||
}
|
||||
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_PROPERTIES))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_PROPERTIES))
|
||||
{
|
||||
TransferManifestNormalNode node = (TransferManifestNormalNode)props.get("node");
|
||||
HashMap<QName, Serializable>properties = new HashMap<QName, Serializable>();
|
||||
node.setProperties(properties);
|
||||
props.put("properties", properties);
|
||||
}
|
||||
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_PROPERTY))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_PROPERTY))
|
||||
{
|
||||
QName name = QName.createQName(atts.getValue("", "name"));
|
||||
props.put("name", name);
|
||||
props.remove("values");
|
||||
props.remove("mltext");
|
||||
}
|
||||
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_HEADER_CREATED_DATE))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_HEADER_CREATED_DATE))
|
||||
{
|
||||
buffer = new StringBuffer();
|
||||
}
|
||||
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_PARENT_ASSOCS))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_HEADER_NODE_COUNT))
|
||||
{
|
||||
buffer = new StringBuffer();
|
||||
}
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_PARENT_ASSOCS))
|
||||
{
|
||||
TransferManifestNormalNode node = (TransferManifestNormalNode)props.get("node");
|
||||
}
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_CHILD_ASSOCS))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_CHILD_ASSOCS))
|
||||
{
|
||||
TransferManifestNormalNode node = (TransferManifestNormalNode)props.get("node");
|
||||
node.setChildAssocs(new ArrayList<ChildAssociationRef>());
|
||||
|
||||
}
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_CHILD_ASSOC))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_CHILD_ASSOC))
|
||||
{
|
||||
buffer = new StringBuffer();
|
||||
NodeRef to = new NodeRef(atts.getValue("", "to"));
|
||||
@@ -228,7 +221,7 @@ public class XMLTransferManifestReader extends DefaultHandler implements Content
|
||||
props.put("type", type);
|
||||
props.put("isPrimary", isPrimary);
|
||||
}
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_PARENT_ASSOC))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_PARENT_ASSOC))
|
||||
{
|
||||
buffer = new StringBuffer();
|
||||
NodeRef from = new NodeRef(atts.getValue("", "from"));
|
||||
@@ -239,14 +232,14 @@ public class XMLTransferManifestReader extends DefaultHandler implements Content
|
||||
props.put("isPrimary", isPrimary);
|
||||
|
||||
}
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_TARGET_ASSOCS))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_TARGET_ASSOCS))
|
||||
{
|
||||
TransferManifestNormalNode node = (TransferManifestNormalNode)props.get("node");
|
||||
List<AssociationRef> assocs = new ArrayList<AssociationRef>();
|
||||
node.setTargetAssocs(assocs);
|
||||
props.put("assocs", assocs);
|
||||
}
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_SOURCE_ASSOCS))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_SOURCE_ASSOCS))
|
||||
{
|
||||
TransferManifestNormalNode node = (TransferManifestNormalNode)props.get("node");
|
||||
List<AssociationRef> assocs = new ArrayList<AssociationRef>();
|
||||
@@ -254,7 +247,7 @@ public class XMLTransferManifestReader extends DefaultHandler implements Content
|
||||
props.put("assocs", assocs);
|
||||
|
||||
}
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_ASSOC))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_ASSOC))
|
||||
{
|
||||
NodeRef source = new NodeRef(atts.getValue("", "source"));
|
||||
NodeRef target = new NodeRef(atts.getValue("", "target"));
|
||||
@@ -264,20 +257,27 @@ public class XMLTransferManifestReader extends DefaultHandler implements Content
|
||||
props.put("type", type);
|
||||
|
||||
}
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_PRIMARY_PARENT))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_PRIMARY_PARENT))
|
||||
{
|
||||
buffer = new StringBuffer();
|
||||
}
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_VALUES))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_VALUES))
|
||||
{
|
||||
Collection<Serializable> values = new ArrayList<Serializable>();
|
||||
props.put("values", values);
|
||||
}
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_VALUE))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_VALUE_STRING))
|
||||
{
|
||||
buffer = new StringBuffer();
|
||||
}
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_MLVALUE))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_VALUE_NULL))
|
||||
{
|
||||
}
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_VALUE_SERIALIZED))
|
||||
{
|
||||
buffer = new StringBuffer();
|
||||
}
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_MLVALUE))
|
||||
{
|
||||
MLText mltext = (MLText)props.get("mlvalues");
|
||||
if(mltext == null)
|
||||
@@ -290,7 +290,7 @@ public class XMLTransferManifestReader extends DefaultHandler implements Content
|
||||
props.put("locale", locale);
|
||||
buffer = new StringBuffer();
|
||||
}
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_CONTENT_HEADER))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_CONTENT_HEADER))
|
||||
{
|
||||
String contentURL = (String)atts.getValue("", "contentURL");
|
||||
String mimetype = (String)atts.getValue("", "mimetype");
|
||||
@@ -302,9 +302,7 @@ public class XMLTransferManifestReader extends DefaultHandler implements Content
|
||||
ContentData contentHeader = new ContentData(contentURL, mimetype, size.longValue(), encoding, locale);
|
||||
props.put("contentHeader", contentHeader);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
} // if transfer URI
|
||||
} // startElement
|
||||
|
||||
/**
|
||||
@@ -330,68 +328,64 @@ public class XMLTransferManifestReader extends DefaultHandler implements Content
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_TRANSFER_MAINIFEST))
|
||||
{
|
||||
}
|
||||
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_TRANSFER_HEADER))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_TRANSFER_HEADER))
|
||||
{
|
||||
TransferManifestHeader header = (TransferManifestHeader)props.get("header");
|
||||
// User to process the header
|
||||
processor.processTransferManifiestHeader(header);
|
||||
}
|
||||
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_NODE))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_NODE))
|
||||
{
|
||||
TransferManifestNormalNode node = (TransferManifestNormalNode)props.get("node");
|
||||
processor.processTransferManifestNode(node);
|
||||
}
|
||||
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_DELETED_NODE))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_DELETED_NODE))
|
||||
{
|
||||
TransferManifestDeletedNode node = (TransferManifestDeletedNode)props.get("node");
|
||||
processor.processTransferManifestNode(node);
|
||||
}
|
||||
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_ASPECTS))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_ASPECTS))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_ASPECT))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_ASPECT))
|
||||
{
|
||||
TransferManifestNormalNode node = (TransferManifestNormalNode)props.get("node");
|
||||
node.getAspects().add(QName.createQName(buffer.toString()));
|
||||
buffer = null;
|
||||
}
|
||||
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_PROPERTIES))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_PROPERTIES))
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_PROPERTY))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_PROPERTY))
|
||||
{
|
||||
TransferManifestNormalNode node = (TransferManifestNormalNode)props.get("node");
|
||||
QName name = (QName)props.get("name");
|
||||
Serializable value = (Serializable)props.get("value");
|
||||
node.getProperties().put(name, value);
|
||||
}
|
||||
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_HEADER_CREATED_DATE))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_HEADER_CREATED_DATE))
|
||||
{
|
||||
TransferManifestHeader header = (TransferManifestHeader)props.get("header");
|
||||
header.setCreatedDate(ISO8601DateFormat.parse(buffer.toString()));
|
||||
buffer = null;
|
||||
}
|
||||
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_PARENT_ASSOCS))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_HEADER_NODE_COUNT))
|
||||
{
|
||||
TransferManifestHeader header = (TransferManifestHeader)props.get("header");
|
||||
header.setNodeCount(Integer.parseInt(buffer.toString()));
|
||||
buffer = null;
|
||||
}
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_PARENT_ASSOCS))
|
||||
{
|
||||
// No-op
|
||||
}
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_CHILD_ASSOCS))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_CHILD_ASSOCS))
|
||||
{
|
||||
// No-op
|
||||
}
|
||||
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_CHILD_ASSOC))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_CHILD_ASSOC))
|
||||
{
|
||||
String value = buffer.toString();
|
||||
QName name = QName.createQName(value);
|
||||
@@ -404,7 +398,7 @@ public class XMLTransferManifestReader extends DefaultHandler implements Content
|
||||
node.getChildAssocs().add(childAssociationRef);
|
||||
|
||||
}
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_PARENT_ASSOC))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_PARENT_ASSOC))
|
||||
{
|
||||
String value = buffer.toString();
|
||||
QName name = QName.createQName(value);
|
||||
@@ -431,17 +425,17 @@ public class XMLTransferManifestReader extends DefaultHandler implements Content
|
||||
node.setPrimaryParentAssoc(childAssociationRef);
|
||||
}
|
||||
}
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_TARGET_ASSOCS))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_TARGET_ASSOCS))
|
||||
{
|
||||
//TransferManifestNode node = (TransferManifestNode)props.get("node");
|
||||
//node.getTargetAssocs().add((AssociationRef)props.get("assoc"));
|
||||
}
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_SOURCE_ASSOCS))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_SOURCE_ASSOCS))
|
||||
{
|
||||
//TransferManifestNode node = (TransferManifestNode)props.get("node");
|
||||
//node.getSourceAssocs().add((AssociationRef)props.get("assoc"));
|
||||
}
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_ASSOC))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_ASSOC))
|
||||
{
|
||||
NodeRef source = (NodeRef)props.get("source");
|
||||
NodeRef target = (NodeRef)props.get("target");
|
||||
@@ -451,18 +445,18 @@ public class XMLTransferManifestReader extends DefaultHandler implements Content
|
||||
assocs.add(assoc);
|
||||
props.put("assoc", new AssociationRef(source, type, target));
|
||||
}
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_PRIMARY_PATH))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_PRIMARY_PATH))
|
||||
{
|
||||
TransferManifestNode node = (TransferManifestNode)props.get("node");
|
||||
String value = buffer.toString();
|
||||
Path path = PathHelper.stringToPath(value);
|
||||
node.setParentPath(path);
|
||||
}
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_VALUES))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_VALUES))
|
||||
{
|
||||
props.put("value", props.get("values"));
|
||||
}
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_VALUE))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_VALUE_STRING))
|
||||
{
|
||||
Collection<Serializable> values = (Collection<Serializable>)props.get("values");
|
||||
String value = buffer.toString();
|
||||
@@ -476,7 +470,54 @@ public class XMLTransferManifestReader extends DefaultHandler implements Content
|
||||
props.put("value", value);
|
||||
}
|
||||
}
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_MLVALUE))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_VALUE_NULL))
|
||||
{
|
||||
Collection<Serializable> values = (Collection<Serializable>)props.get("values");
|
||||
|
||||
if(values != null)
|
||||
{
|
||||
values.add(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
props.put("value", null);
|
||||
}
|
||||
}
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_VALUE_SERIALIZED))
|
||||
{
|
||||
Collection<Serializable> values = (Collection<Serializable>)props.get("values");
|
||||
|
||||
String strValue = buffer.toString();
|
||||
Object value = null;
|
||||
|
||||
// TODO assumes "base64/ObjectOutputStream" - should check
|
||||
try
|
||||
{
|
||||
byte[] data = Base64.decode(strValue.getBytes("UTF-8"));
|
||||
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data));
|
||||
value = ois.readObject();
|
||||
}
|
||||
catch (IOException error)
|
||||
{
|
||||
//TODO Error handler - should this fail the transfer ?
|
||||
error.printStackTrace();
|
||||
}
|
||||
catch (ClassNotFoundException error)
|
||||
{
|
||||
//TODO Error handler - should this fail the transfer ?
|
||||
error.printStackTrace();
|
||||
}
|
||||
|
||||
if(values != null)
|
||||
{
|
||||
values.add((Serializable)value);
|
||||
}
|
||||
else
|
||||
{
|
||||
props.put("value", value);
|
||||
}
|
||||
}
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_MLVALUE))
|
||||
{
|
||||
MLText mltext = (MLText)props.get("mlvalues");
|
||||
Locale locale = (Locale)props.get("locale");
|
||||
@@ -485,13 +526,13 @@ public class XMLTransferManifestReader extends DefaultHandler implements Content
|
||||
props.put("value", mltext);
|
||||
|
||||
}
|
||||
if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_CONTENT_HEADER))
|
||||
else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_CONTENT_HEADER))
|
||||
{
|
||||
TransferManifestNode node = (TransferManifestNode)props.get("node");
|
||||
ContentData data = (ContentData)props.get("contentHeader");
|
||||
props.put("value", data);
|
||||
}
|
||||
}
|
||||
} // if transfer URI
|
||||
} // end element
|
||||
|
||||
|
||||
|
@@ -24,6 +24,9 @@
|
||||
*/
|
||||
package org.alfresco.repo.transfer.manifest;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.io.Writer;
|
||||
import java.util.Collection;
|
||||
@@ -39,17 +42,21 @@ import org.alfresco.service.cmr.repository.AssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.repository.MLText;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.Path;
|
||||
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
|
||||
import org.alfresco.service.cmr.repository.datatype.TypeConversionException;
|
||||
import org.alfresco.service.cmr.transfer.TransferException;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.dom4j.io.OutputFormat;
|
||||
import org.dom4j.io.XMLWriter;
|
||||
import org.springframework.extensions.surf.util.Base64;
|
||||
import org.springframework.extensions.surf.util.ISO8601DateFormat;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.AttributesImpl;
|
||||
|
||||
//import com.sun.org.apache.xml.internal.security.utils.Base64;
|
||||
|
||||
/**
|
||||
* XMLTransferManifestWriter
|
||||
*
|
||||
@@ -116,6 +123,12 @@ public class XMLTransferManifestWriter implements TransferManifestWriter
|
||||
writeDate(header.getCreatedDate());
|
||||
writer.endElement(TransferModel.TRANSFER_MODEL_1_0_URI, ManifestModel.LOCALNAME_HEADER_CREATED_DATE, PREFIX + ":" + ManifestModel.LOCALNAME_HEADER_CREATED_DATE);
|
||||
|
||||
// Node count
|
||||
writer.startElement(TransferModel.TRANSFER_MODEL_1_0_URI, ManifestModel.LOCALNAME_HEADER_NODE_COUNT, PREFIX + ":" + ManifestModel.LOCALNAME_HEADER_NODE_COUNT, EMPTY_ATTRIBUTES);
|
||||
char[] nodeCountChars = Integer.toString(header.getNodeCount()).toCharArray();
|
||||
writer.characters(nodeCountChars, 0, nodeCountChars.length);
|
||||
writer.endElement(TransferModel.TRANSFER_MODEL_1_0_URI, ManifestModel.LOCALNAME_HEADER_NODE_COUNT, PREFIX + ":" + ManifestModel.LOCALNAME_HEADER_NODE_COUNT);
|
||||
|
||||
// End Header
|
||||
writer.endElement(TransferModel.TRANSFER_MODEL_1_0_URI, ManifestModel.LOCALNAME_TRANSFER_HEADER, PREFIX + ":" + ManifestModel.LOCALNAME_TRANSFER_HEADER);
|
||||
}
|
||||
@@ -217,12 +230,10 @@ public class XMLTransferManifestWriter implements TransferManifestWriter
|
||||
writer.startElement(TransferModel.TRANSFER_MODEL_1_0_URI, ManifestModel.LOCALNAME_ELEMENT_PROPERTY, PREFIX + ":" + ManifestModel.LOCALNAME_ELEMENT_PROPERTY, attributes);
|
||||
}
|
||||
|
||||
// TODO - Char [] does not seem to be processed correctly
|
||||
if(value.getClass().isArray())
|
||||
if(value == null)
|
||||
{
|
||||
writeValue(value.toString());
|
||||
writeNullValue();
|
||||
}
|
||||
// Collection
|
||||
else if(value instanceof ContentData)
|
||||
{
|
||||
ContentData data = (ContentData)value;
|
||||
@@ -235,7 +246,6 @@ public class XMLTransferManifestWriter implements TransferManifestWriter
|
||||
writer.startElement(TransferModel.TRANSFER_MODEL_1_0_URI, ManifestModel.LOCALNAME_ELEMENT_CONTENT_HEADER, PREFIX + ":" + ManifestModel.LOCALNAME_ELEMENT_CONTENT_HEADER, dataAttributes);
|
||||
writer.endElement(TransferModel.TRANSFER_MODEL_1_0_URI, ManifestModel.LOCALNAME_ELEMENT_CONTENT_HEADER, PREFIX + ":" + ManifestModel.LOCALNAME_ELEMENT_CONTENT_HEADER);
|
||||
}
|
||||
// Collection
|
||||
else if(value instanceof Collection)
|
||||
{
|
||||
writer.startElement(TransferModel.TRANSFER_MODEL_1_0_URI, ManifestModel.LOCALNAME_ELEMENT_VALUES, PREFIX + ":" + ManifestModel.LOCALNAME_ELEMENT_VALUES, EMPTY_ATTRIBUTES);
|
||||
@@ -264,11 +274,59 @@ public class XMLTransferManifestWriter implements TransferManifestWriter
|
||||
|
||||
private void writeValue(Serializable value) throws SAXException
|
||||
{
|
||||
writer.startElement(TransferModel.TRANSFER_MODEL_1_0_URI, ManifestModel.LOCALNAME_ELEMENT_VALUE, PREFIX + ":" + ManifestModel.LOCALNAME_ELEMENT_VALUE, EMPTY_ATTRIBUTES);
|
||||
String strValue = (String)DefaultTypeConverter.INSTANCE.convert(String.class, value);
|
||||
try
|
||||
{
|
||||
String strValue = (String)DefaultTypeConverter.INSTANCE.convert(String.class, value);
|
||||
writer.startElement(TransferModel.TRANSFER_MODEL_1_0_URI, ManifestModel.LOCALNAME_ELEMENT_VALUE_STRING, PREFIX + ":" + ManifestModel.LOCALNAME_ELEMENT_VALUE_STRING, EMPTY_ATTRIBUTES);
|
||||
|
||||
writer.characters(strValue.toCharArray(), 0, strValue.length());
|
||||
writer.endElement(TransferModel.TRANSFER_MODEL_1_0_URI, ManifestModel.LOCALNAME_ELEMENT_VALUE, PREFIX + ":" + ManifestModel.LOCALNAME_ELEMENT_VALUE);
|
||||
writer.characters(strValue.toCharArray(), 0, strValue.length());
|
||||
|
||||
writer.endElement(TransferModel.TRANSFER_MODEL_1_0_URI, ManifestModel.LOCALNAME_ELEMENT_VALUE_STRING, PREFIX + ":" + ManifestModel.LOCALNAME_ELEMENT_VALUE_STRING);
|
||||
}
|
||||
catch (TypeConversionException e)
|
||||
{
|
||||
/**
|
||||
* Can't convert this to a string for transmission
|
||||
*
|
||||
* Need to serialize the Java Object
|
||||
*/
|
||||
|
||||
try
|
||||
{
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
|
||||
ObjectOutputStream oos;
|
||||
oos = new ObjectOutputStream(bos);
|
||||
oos.writeObject(value);
|
||||
oos.close();
|
||||
|
||||
byte[] ba = bos.toByteArray();
|
||||
String s = new String(Base64.encodeBytes(ba));
|
||||
|
||||
AttributesImpl attributes = new AttributesImpl();
|
||||
attributes.addAttribute(TransferModel.TRANSFER_MODEL_1_0_URI, "className", "className", "String", value.getClass().getName());
|
||||
attributes.addAttribute(TransferModel.TRANSFER_MODEL_1_0_URI, "encoding", "encoding", "String", "base64/ObjectOutputStream");
|
||||
writer.startElement(TransferModel.TRANSFER_MODEL_1_0_URI, ManifestModel.LOCALNAME_ELEMENT_VALUE_SERIALIZED, PREFIX + ":" + ManifestModel.LOCALNAME_ELEMENT_VALUE_SERIALIZED, attributes);
|
||||
|
||||
writer.startCDATA();
|
||||
writer.characters(s.toCharArray(), 0, s.length());
|
||||
writer.endCDATA();
|
||||
|
||||
writer.endElement(TransferModel.TRANSFER_MODEL_1_0_URI, ManifestModel.LOCALNAME_ELEMENT_VALUE_SERIALIZED, PREFIX + ":" + ManifestModel.LOCALNAME_ELEMENT_VALUE_SERIALIZED);
|
||||
|
||||
}
|
||||
catch (IOException err)
|
||||
{
|
||||
throw new TransferException("Unable to write property value", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writeNullValue() throws SAXException
|
||||
{
|
||||
AttributesImpl attributes = new AttributesImpl();
|
||||
writer.startElement(TransferModel.TRANSFER_MODEL_1_0_URI, ManifestModel.LOCALNAME_ELEMENT_VALUE_NULL, PREFIX + ":" + ManifestModel.LOCALNAME_ELEMENT_VALUE_NULL, attributes);
|
||||
writer.endElement(TransferModel.TRANSFER_MODEL_1_0_URI, ManifestModel.LOCALNAME_ELEMENT_VALUE_NULL, PREFIX + ":" + ManifestModel.LOCALNAME_ELEMENT_VALUE_NULL);
|
||||
}
|
||||
|
||||
private void writeMLValue(Locale locale, Serializable value) throws SAXException
|
||||
|
@@ -1,44 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.alfresco.org/model/transferReport/1.0" xmlns:report="http://www.alfresco.org/model/transferReport/1.0" elementFormDefault="qualified">
|
||||
|
||||
<!-- XML Schema for the client side transferReport -->
|
||||
<complexType name="transferReport">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
This is the transfer report root tag
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<sequence>
|
||||
<element name="target" type="report:target" maxOccurs="1" minOccurs="1"></element>
|
||||
<element name="definition" type="report:definition" maxOccurs="1" minOccurs="1"></element>
|
||||
<element name="events" type="report:events"></element>
|
||||
</sequence>
|
||||
</complexType>
|
||||
<schema
|
||||
targetNamespace="http://www.alfresco.org/model/transferReport/1.0"
|
||||
xmlns:report="http://www.alfresco.org/model/transferReport/1.0"
|
||||
xmlns="http://www.w3.org/2001/XMLSchema"
|
||||
elementFormDefault="qualified">
|
||||
|
||||
<complexType name="target">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
<!-- XML Schema for the client side transferReport -->
|
||||
|
||||
<complexType name="transferReport">
|
||||
<annotation>
|
||||
<documentation>
|
||||
This is an alfresco client side transfer report
|
||||
</documentation>
|
||||
</annotation>
|
||||
<sequence>
|
||||
<element name="target" type="report:target" maxOccurs="1"
|
||||
minOccurs="1">
|
||||
</element>
|
||||
<element name="definition" type="report:definition"
|
||||
maxOccurs="1" minOccurs="1">
|
||||
</element>
|
||||
<element name="exception" type="report:exception" maxOccurs="1"
|
||||
minOccurs="0">
|
||||
</element>
|
||||
<element name="events" type="report:events"></element>
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="target">
|
||||
<annotation>
|
||||
<documentation>
|
||||
The destination of the transfer
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<attribute name="name" type="string"></attribute>
|
||||
<attribute name="endpointPort" type="int"></attribute>
|
||||
<attribute name="endpointHost" type="string"></attribute>
|
||||
</complexType>
|
||||
</documentation>
|
||||
</annotation>
|
||||
<attribute name="name" type="string"></attribute>
|
||||
<attribute name="endpointPort" type="int"></attribute>
|
||||
<attribute name="endpointHost" type="string"></attribute>
|
||||
</complexType>
|
||||
|
||||
<complexType name="definition">
|
||||
</complexType>
|
||||
<complexType name="definition"></complexType>
|
||||
|
||||
<complexType name="events">
|
||||
<sequence maxOccurs="unbounded" minOccurs="0">
|
||||
<element name="event" type="report:event"></element>
|
||||
</sequence>
|
||||
</complexType>
|
||||
<complexType name="events">
|
||||
<sequence maxOccurs="unbounded" minOccurs="0">
|
||||
<element name="event" type="report:event"></element>
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="event">
|
||||
<attribute name="date" type="dateTime"></attribute>
|
||||
<!-- message is content -->
|
||||
</complexType>
|
||||
<complexType name="event">
|
||||
</complexType>
|
||||
|
||||
<complexType name="exception">
|
||||
|
||||
</complexType>
|
||||
|
||||
<element name="report" type="string"></element>
|
||||
</schema>
|
@@ -35,8 +35,12 @@ public interface TransferReportModel extends TransferModel
|
||||
static final String LOCALNAME_TRANSFER_REPORT = "transferReport";
|
||||
static final String LOCALNAME_TRANSFER_TARGET = "target";
|
||||
static final String LOCALNAME_TRANSFER_DEFINITION = "definition";
|
||||
static final String LOCALNAME_EXCEPTION = "exception";
|
||||
static final String LOCALNAME_TRANSFER_EVENTS = "events";
|
||||
static final String LOCALNAME_TRANSFER_EVENT = "event";
|
||||
static final String LOCALNAME_TRANSFER_NODE = "node";
|
||||
static final String LOCALNAME_TRANSFER_PRIMARY_PATH = "primaryPath";
|
||||
static final String LOCALNAME_TRANSFER_PRIMARY_PARENT = "primaryParent";
|
||||
static final String REPORT_PREFIX = "report";
|
||||
|
||||
static final String TRANSFER_REPORT_MODEL_1_0_URI = "http://www.alfresco.org/model/transferReport/1.0";
|
||||
|
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
package org.alfresco.repo.transfer.report;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.repo.transfer.Transfer;
|
||||
@@ -35,15 +36,35 @@ import org.alfresco.service.cmr.transfer.TransferTarget;
|
||||
public interface TransferReporter
|
||||
{
|
||||
/**
|
||||
* Create a transfer report
|
||||
* Create a transfer report of success
|
||||
* @param target the target of the transfer
|
||||
* @param definition the definition of the transfer
|
||||
* @param events the transfer events generated by the transfer.
|
||||
* @param snapshotFile
|
||||
*
|
||||
* @return the node ref of the transfer report
|
||||
*/
|
||||
NodeRef createTransferReport(Transfer transfer,
|
||||
public NodeRef createTransferReport(Transfer transfer,
|
||||
TransferTarget target,
|
||||
TransferDefinition definition,
|
||||
List<TransferEvent> events);
|
||||
List<TransferEvent> events,
|
||||
File snapshotFile
|
||||
);
|
||||
|
||||
/**
|
||||
* Create a transfer report of failure
|
||||
* @param e
|
||||
* @param target
|
||||
* @param definition
|
||||
* @param events
|
||||
* @param snapshotFile
|
||||
* @return the node ref of the transfer report
|
||||
*/
|
||||
public NodeRef createTransferReport(Exception e,
|
||||
TransferTarget target,
|
||||
TransferDefinition definition,
|
||||
List<TransferEvent> events,
|
||||
File snapshotFile
|
||||
);
|
||||
|
||||
}
|
||||
|
@@ -25,19 +25,34 @@
|
||||
package org.alfresco.repo.transfer.report;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
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;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
|
||||
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.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.repo.transfer.manifest.XMLTransferManifestReader;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
@@ -48,6 +63,7 @@ import org.alfresco.service.cmr.transfer.TransferTarget;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.dom4j.io.XMLWriter;
|
||||
import org.springframework.extensions.surf.util.ISO8601DateFormat;
|
||||
import org.springframework.extensions.surf.util.PropertyCheck;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
@@ -65,20 +81,27 @@ public class TransferReporterImpl implements TransferReporter
|
||||
PropertyCheck.mandatory(this, "contentService", contentService);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a new transfer report
|
||||
* Write exception transfer report
|
||||
*
|
||||
* @return NodeRef the node ref of the new transfer report
|
||||
*/
|
||||
public NodeRef createTransferReport(Transfer transfer,
|
||||
public NodeRef createTransferReport(Exception e,
|
||||
TransferTarget target,
|
||||
TransferDefinition definition,
|
||||
List<TransferEvent> events)
|
||||
List<TransferEvent> events,
|
||||
File snapshotFile)
|
||||
{
|
||||
Map<QName, Serializable> properties = new HashMap<QName, Serializable> ();
|
||||
String transferId = transfer.getTransferId();
|
||||
String title = "transfer report: success :" + transferId;
|
||||
String name = transferId;
|
||||
String description = "successful transfer report";
|
||||
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmssSSSZ");
|
||||
String timeNow = format.format(new Date());
|
||||
|
||||
String title = "Transfer report, error, " + timeNow;
|
||||
String description = "Transfer error report";
|
||||
String name = "Transfer error report, " + timeNow;
|
||||
|
||||
properties.put(ContentModel.PROP_NAME, name);
|
||||
properties.put(ContentModel.PROP_TITLE, title);
|
||||
@@ -87,7 +110,7 @@ public class TransferReporterImpl implements TransferReporter
|
||||
ContentWriter writer = contentService.getWriter(ref.getChildRef(), ContentModel.PROP_CONTENT, true);
|
||||
writer.setLocale(Locale.getDefault());
|
||||
writer.setMimetype(MimetypeMap.MIMETYPE_XML);
|
||||
writer.setEncoding("UTF-8");
|
||||
writer.setEncoding(DEFAULT_ENCODING);
|
||||
|
||||
//
|
||||
XMLTransferReportWriter reportWriter = new XMLTransferReportWriter();
|
||||
@@ -96,13 +119,15 @@ public class TransferReporterImpl implements TransferReporter
|
||||
|
||||
try
|
||||
{
|
||||
reportWriter.startTransferReport("UTF-8", bufferedWriter);
|
||||
reportWriter.startTransferReport(DEFAULT_ENCODING, bufferedWriter);
|
||||
|
||||
// Header
|
||||
reportWriter.writeTarget(target);
|
||||
|
||||
reportWriter.writeDefinition(definition);
|
||||
|
||||
reportWriter.writeException(e);
|
||||
|
||||
// Detail
|
||||
reportWriter.writeTransferEvents(events);
|
||||
|
||||
@@ -128,6 +153,139 @@ public class TransferReporterImpl implements TransferReporter
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new transfer report of success
|
||||
*
|
||||
* @return NodeRef the node ref of the new transfer report
|
||||
*/
|
||||
public NodeRef createTransferReport(Transfer transfer,
|
||||
TransferTarget target,
|
||||
TransferDefinition definition,
|
||||
List<TransferEvent> events,
|
||||
File snapshotFile)
|
||||
{
|
||||
Map<QName, Serializable> properties = new HashMap<QName, Serializable> ();
|
||||
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddhhmmssSSSZ");
|
||||
String timeNow = format.format(new Date());
|
||||
|
||||
String title = "Transfer report, " + timeNow + "success";
|
||||
String description = "Transfer report success targetName : " + target.getName();
|
||||
String name = "Transfer report, " + timeNow;
|
||||
|
||||
properties.put(ContentModel.PROP_NAME, name);
|
||||
properties.put(ContentModel.PROP_TITLE, title);
|
||||
properties.put(ContentModel.PROP_DESCRIPTION, description);
|
||||
ChildAssociationRef ref = nodeService.createNode(target.getNodeRef(), ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, name), TransferModel.TYPE_TRANSFER_REPORT, properties);
|
||||
ContentWriter writer = contentService.getWriter(ref.getChildRef(), ContentModel.PROP_CONTENT, true);
|
||||
writer.setLocale(Locale.getDefault());
|
||||
writer.setMimetype(MimetypeMap.MIMETYPE_XML);
|
||||
writer.setEncoding(DEFAULT_ENCODING);
|
||||
|
||||
//
|
||||
final XMLTransferReportWriter reportWriter = new XMLTransferReportWriter();
|
||||
|
||||
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(writer.getContentOutputStream()));
|
||||
|
||||
try
|
||||
{
|
||||
reportWriter.startTransferReport(DEFAULT_ENCODING, bufferedWriter);
|
||||
|
||||
// Header
|
||||
reportWriter.writeTarget(target);
|
||||
|
||||
reportWriter.writeDefinition(definition);
|
||||
|
||||
/**
|
||||
* Write the node summary details to the transfer report
|
||||
*/
|
||||
TransferManifestProcessor processor = new TransferManifestProcessor()
|
||||
{
|
||||
public void processTransferManifestNode(TransferManifestNormalNode node)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
reportWriter.writeNodeSummary(node);
|
||||
}
|
||||
catch (SAXException error)
|
||||
{
|
||||
error.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void processTransferManifestNode(TransferManifestDeletedNode node)
|
||||
{
|
||||
try
|
||||
{
|
||||
reportWriter.writeNodeSummary(node);
|
||||
}
|
||||
catch (SAXException error)
|
||||
{
|
||||
error.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void processTransferManifiestHeader(TransferManifestHeader header){/* NO-OP */ }
|
||||
public void startTransferManifest(){ /* NO-OP */ }
|
||||
public void endTransferManifest(){ /* NO-OP */ }
|
||||
};
|
||||
|
||||
/**
|
||||
* Step 3: wire up the manifest reader to a manifest processor
|
||||
*/
|
||||
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
|
||||
SAXParser parser;
|
||||
parser = saxParserFactory.newSAXParser();
|
||||
XMLTransferManifestReader reader = new XMLTransferManifestReader(processor);
|
||||
|
||||
/**
|
||||
* Step 4: start the magic Give the manifest file to the manifest reader
|
||||
*/
|
||||
try
|
||||
{
|
||||
parser.parse(snapshotFile, reader);
|
||||
}
|
||||
catch (IOException error)
|
||||
{
|
||||
//TODO temp code
|
||||
error.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
// Detail Events
|
||||
reportWriter.writeTransferEvents(events);
|
||||
|
||||
reportWriter.endTransferReport();
|
||||
|
||||
return ref.getChildRef();
|
||||
}
|
||||
|
||||
catch (SAXException se)
|
||||
{
|
||||
//TODO Temp code
|
||||
return null;
|
||||
}
|
||||
catch (ParserConfigurationException error)
|
||||
{
|
||||
// TODO temp code
|
||||
error.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
bufferedWriter.close();
|
||||
}
|
||||
catch (IOException error)
|
||||
{
|
||||
error.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
@@ -148,4 +306,5 @@ public class TransferReporterImpl implements TransferReporter
|
||||
return contentService;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -7,9 +7,13 @@ import java.util.List;
|
||||
import org.alfresco.repo.transfer.TransferModel;
|
||||
import org.alfresco.repo.transfer.manifest.ManifestModel;
|
||||
import org.alfresco.repo.transfer.manifest.TransferManifestHeader;
|
||||
import org.alfresco.repo.transfer.manifest.TransferManifestNode;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.Path;
|
||||
import org.alfresco.service.cmr.transfer.TransferDefinition;
|
||||
import org.alfresco.service.cmr.transfer.TransferEvent;
|
||||
import org.alfresco.service.cmr.transfer.TransferTarget;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.dom4j.io.OutputFormat;
|
||||
import org.dom4j.io.XMLWriter;
|
||||
import org.springframework.extensions.surf.util.ISO8601DateFormat;
|
||||
@@ -44,7 +48,7 @@ public class XMLTransferReportWriter
|
||||
this.writer.startPrefixMapping(PREFIX, TransferReportModel.TRANSFER_REPORT_MODEL_1_0_URI);
|
||||
|
||||
// Start Transfer Manifest // uri, name, prefix
|
||||
this.writer.startElement(TransferReportModel.TRANSFER_REPORT_MODEL_1_0_URI, TransferReportModel.LOCALNAME_TRANSFER_REPORT, PREFIX + ":" + TransferReportModel.LOCALNAME_TRANSFER_REPORT, EMPTY_ATTRIBUTES);
|
||||
this.writer.startElement(TransferReportModel.TRANSFER_REPORT_MODEL_1_0_URI, TransferReportModel.LOCALNAME_TRANSFER_REPORT, TransferReportModel.LOCALNAME_TRANSFER_REPORT, EMPTY_ATTRIBUTES);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,7 +57,7 @@ public class XMLTransferReportWriter
|
||||
public void endTransferReport() throws SAXException
|
||||
{
|
||||
// End Transfer Manifest
|
||||
writer.endElement(TransferReportModel.TRANSFER_REPORT_MODEL_1_0_URI, TransferReportModel.LOCALNAME_TRANSFER_REPORT, PREFIX + ":" + TransferReportModel.LOCALNAME_TRANSFER_REPORT);
|
||||
writer.endElement(TransferReportModel.TRANSFER_REPORT_MODEL_1_0_URI, TransferReportModel.LOCALNAME_TRANSFER_REPORT, TransferReportModel.LOCALNAME_TRANSFER_REPORT);
|
||||
writer.endPrefixMapping(PREFIX);
|
||||
writer.endDocument();
|
||||
}
|
||||
@@ -83,6 +87,18 @@ public class XMLTransferReportWriter
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the definition to the report
|
||||
*/
|
||||
public void writeException(Exception e) throws SAXException
|
||||
{
|
||||
AttributesImpl attributes = new AttributesImpl();
|
||||
attributes.addAttribute(TransferReportModel.TRANSFER_REPORT_MODEL_1_0_URI, "type", "type", "String", e.getClass().getName());
|
||||
attributes.addAttribute(TransferReportModel.TRANSFER_REPORT_MODEL_1_0_URI, "message", "message", "String", e.getMessage());
|
||||
writer.startElement(TransferReportModel.TRANSFER_REPORT_MODEL_1_0_URI, TransferReportModel.LOCALNAME_EXCEPTION, PREFIX + ":" + TransferReportModel.LOCALNAME_EXCEPTION, attributes);
|
||||
writer.endElement(TransferReportModel.TRANSFER_REPORT_MODEL_1_0_URI, TransferReportModel.LOCALNAME_EXCEPTION, PREFIX + ":" + TransferReportModel.LOCALNAME_EXCEPTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the transfer manifest header
|
||||
*/
|
||||
@@ -99,6 +115,57 @@ public class XMLTransferReportWriter
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the transfer manifest header
|
||||
*/
|
||||
public void writeNodeSummary(TransferManifestNode node) throws SAXException
|
||||
{
|
||||
AttributesImpl attributes = new AttributesImpl();
|
||||
attributes.addAttribute("uri", "nodeRef", "nodeRef", "String", node.getNodeRef().toString());
|
||||
writer.startElement(TransferReportModel.TRANSFER_REPORT_MODEL_1_0_URI, TransferReportModel.LOCALNAME_TRANSFER_NODE, PREFIX + ":" + TransferReportModel.LOCALNAME_TRANSFER_NODE, attributes);
|
||||
|
||||
if(node.getPrimaryParentAssoc() != null)
|
||||
{
|
||||
writePrimaryParent(node.getPrimaryParentAssoc(), node.getParentPath());
|
||||
}
|
||||
|
||||
writer.endElement(TransferReportModel.TRANSFER_REPORT_MODEL_1_0_URI, TransferReportModel.LOCALNAME_TRANSFER_NODE, PREFIX + ":" + TransferReportModel.LOCALNAME_TRANSFER_NODE);
|
||||
}
|
||||
|
||||
private void writePrimaryParent(ChildAssociationRef parentAssoc, Path parentPath) throws SAXException
|
||||
{
|
||||
writer.startElement(TransferReportModel.TRANSFER_REPORT_MODEL_1_0_URI, TransferReportModel.LOCALNAME_TRANSFER_PRIMARY_PARENT, PREFIX + ":" + TransferReportModel.LOCALNAME_TRANSFER_PRIMARY_PARENT, EMPTY_ATTRIBUTES);
|
||||
|
||||
writeParentAssoc(parentAssoc);
|
||||
|
||||
writer.startElement(TransferReportModel.TRANSFER_REPORT_MODEL_1_0_URI, TransferReportModel.LOCALNAME_TRANSFER_PRIMARY_PATH, PREFIX + ":" + TransferReportModel.LOCALNAME_TRANSFER_PRIMARY_PATH, EMPTY_ATTRIBUTES);
|
||||
if(parentPath != null)
|
||||
{
|
||||
String path = parentPath.toString();
|
||||
writer.characters(path.toCharArray(), 0, path.length());
|
||||
}
|
||||
writer.endElement(TransferReportModel.TRANSFER_REPORT_MODEL_1_0_URI, TransferReportModel.LOCALNAME_TRANSFER_PRIMARY_PATH, PREFIX + ":" + ManifestModel.LOCALNAME_ELEMENT_PRIMARY_PATH);
|
||||
|
||||
writer.endElement(TransferReportModel.TRANSFER_REPORT_MODEL_1_0_URI, TransferReportModel.LOCALNAME_TRANSFER_PRIMARY_PARENT, PREFIX + ":" + ManifestModel.LOCALNAME_ELEMENT_PRIMARY_PARENT);
|
||||
}
|
||||
|
||||
private void writeParentAssoc(ChildAssociationRef assoc) throws SAXException
|
||||
{
|
||||
if(assoc != null)
|
||||
{
|
||||
AttributesImpl attributes = new AttributesImpl();
|
||||
attributes.addAttribute(TransferModel.TRANSFER_MODEL_1_0_URI, "from", "from", "String", assoc.getParentRef().toString());
|
||||
attributes.addAttribute(TransferModel.TRANSFER_MODEL_1_0_URI, "type", "type", "String", formatQName(assoc.getTypeQName()));
|
||||
attributes.addAttribute(TransferModel.TRANSFER_MODEL_1_0_URI, "type", "isPrimary", "Boolean", assoc.isPrimary()?"true":"false");
|
||||
writer.startElement(TransferModel.TRANSFER_MODEL_1_0_URI, ManifestModel.LOCALNAME_ELEMENT_PARENT_ASSOC, PREFIX + ":" + ManifestModel.LOCALNAME_ELEMENT_PARENT_ASSOC, attributes);
|
||||
String name= formatQName(assoc.getQName());
|
||||
writer.characters(name.toCharArray(), 0, name.length());
|
||||
assoc.isPrimary();
|
||||
|
||||
writer.endElement(TransferModel.TRANSFER_MODEL_1_0_URI, ManifestModel.LOCALNAME_ELEMENT_PARENT_ASSOC, PREFIX + ":" + ManifestModel.LOCALNAME_ELEMENT_PARENT_ASSOC);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the transfer manifest header
|
||||
*/
|
||||
@@ -116,4 +183,10 @@ public class XMLTransferReportWriter
|
||||
}
|
||||
writer.endElement(TransferReportModel.TRANSFER_REPORT_MODEL_1_0_URI, TransferReportModel.LOCALNAME_TRANSFER_EVENT, PREFIX + ":" + TransferReportModel.LOCALNAME_TRANSFER_EVENT);
|
||||
}
|
||||
|
||||
private String formatQName(QName qname)
|
||||
{
|
||||
return qname.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,18 @@
|
||||
package org.alfresco.service.cmr.transfer;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
public interface NodeCrawler
|
||||
{
|
||||
|
||||
public abstract Set<NodeRef> crawl(NodeRef... nodes);
|
||||
|
||||
public abstract Set<NodeRef> crawl(Set<NodeRef> startingNodes);
|
||||
|
||||
public abstract void setNodeFinders(NodeFinder... finders);
|
||||
|
||||
public abstract void setNodeFilters(NodeFilter... filters);
|
||||
|
||||
}
|
@@ -25,6 +25,9 @@
|
||||
package org.alfresco.service.cmr.transfer;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
@@ -49,9 +52,14 @@ public class TransferDefinition implements Serializable
|
||||
* Set which nodes to transfer
|
||||
* @param nodes
|
||||
*/
|
||||
public void setNodes(Set<NodeRef> nodes)
|
||||
public void setNodes(Collection<NodeRef> nodes)
|
||||
{
|
||||
this.nodes = nodes;
|
||||
this.nodes = new HashSet<NodeRef>(nodes);
|
||||
}
|
||||
|
||||
public void setNodes(NodeRef...nodes)
|
||||
{
|
||||
this.setNodes(new HashSet<NodeRef>(Arrays.asList(nodes)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 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 recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.service.cmr.transfer;
|
||||
|
||||
import org.alfresco.repo.transfer.TransferEventImpl;
|
||||
|
||||
/**
|
||||
* TransferEventBegin is produced when a transfer has started.
|
||||
*/
|
||||
public class TransferEventBegin extends TransferEventImpl
|
||||
{
|
||||
private String transferId;
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "TransferEventBegin: " + transferId;
|
||||
}
|
||||
|
||||
public void setTransferId(String transferId)
|
||||
{
|
||||
this.transferId = transferId;
|
||||
}
|
||||
|
||||
public String getTransferId()
|
||||
{
|
||||
return transferId;
|
||||
}
|
||||
}
|
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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.service.cmr.transfer;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author brian
|
||||
*
|
||||
*/
|
||||
public class TransferProgress
|
||||
{
|
||||
public enum Status
|
||||
{
|
||||
PRE_COMMIT, COMMIT_REQUESTED, COMMITTING, COMPLETE, ERROR, CANCELLED
|
||||
};
|
||||
|
||||
private static Set<Status> terminalStatuses = Collections.unmodifiableSet(new HashSet<Status>(Arrays.asList(
|
||||
Status.COMPLETE, Status.ERROR, Status.CANCELLED)));
|
||||
|
||||
private Status status;
|
||||
private int currentPosition;
|
||||
private int endPosition;
|
||||
private Throwable error;
|
||||
|
||||
/**
|
||||
*
|
||||
* @return The statuses that mark the end of the transfer. Once a transfer reaches one of these statuses
|
||||
* it can never move into a different status.
|
||||
*/
|
||||
public static Set<Status> getTerminalStatuses()
|
||||
{
|
||||
return terminalStatuses;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return true if the current status is one of the terminal statuses.
|
||||
*/
|
||||
public boolean isFinished()
|
||||
{
|
||||
return terminalStatuses.contains(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the status
|
||||
*/
|
||||
public Status getStatus()
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param status
|
||||
* the status to set
|
||||
*/
|
||||
public void setStatus(Status status)
|
||||
{
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the currentPosition
|
||||
*/
|
||||
public int getCurrentPosition()
|
||||
{
|
||||
return currentPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param currentPosition
|
||||
* the currentPosition to set
|
||||
*/
|
||||
public void setCurrentPosition(int currentPosition)
|
||||
{
|
||||
this.currentPosition = currentPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the endPosition
|
||||
*/
|
||||
public int getEndPosition()
|
||||
{
|
||||
return endPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param endPosition
|
||||
* the endPosition to set
|
||||
*/
|
||||
public void setEndPosition(int endPosition)
|
||||
{
|
||||
this.endPosition = endPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the error
|
||||
*/
|
||||
public Throwable getError()
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param error
|
||||
* the error to set
|
||||
*/
|
||||
public void setError(Throwable error)
|
||||
{
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
}
|
@@ -28,6 +28,7 @@ package org.alfresco.service.cmr.transfer;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.alfresco.repo.transfer.TransferProgressMonitor;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
/**
|
||||
@@ -96,7 +97,14 @@ public interface TransferReceiver
|
||||
* @param transferId
|
||||
* @throws TransferException
|
||||
*/
|
||||
void abort(String transferId) throws TransferException;
|
||||
void cancel(String transferId) throws TransferException;
|
||||
|
||||
/**
|
||||
* Commit asynchronously
|
||||
* @param transferId
|
||||
* @throws TransferException
|
||||
*/
|
||||
void commitAsync(String transferId) throws TransferException;
|
||||
|
||||
/**
|
||||
* Commit
|
||||
@@ -104,4 +112,8 @@ public interface TransferReceiver
|
||||
* @throws TransferException
|
||||
*/
|
||||
void commit(String transferId) throws TransferException;
|
||||
|
||||
TransferProgress getStatus(String transferId) throws TransferException;
|
||||
|
||||
TransferProgressMonitor getProgressMonitor();
|
||||
}
|
@@ -25,6 +25,7 @@
|
||||
|
||||
package org.alfresco.service.cmr.transfer;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
@@ -63,24 +64,55 @@ public interface TransferService
|
||||
* @throws TransferException
|
||||
* @return the node reference of the transfer report
|
||||
*/
|
||||
public NodeRef transfer(String targetName, TransferDefinition definition, Set<TransferCallback> callback) throws TransferException;
|
||||
public NodeRef transfer(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.
|
||||
*
|
||||
* Please also be aware that the asychronous transfer does not have access to uncommitted
|
||||
* data in the calling transaction.
|
||||
* 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.
|
||||
* @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.
|
||||
* @param callbacks - a list of callback handlers that will be called as transfer proceeds. May be null.
|
||||
* @throws TransferException
|
||||
* @return the node reference of the transfer report
|
||||
*/
|
||||
public void transferAsync(String targetName, TransferDefinition definition, Set<TransferCallback> callback) throws TransferException;
|
||||
public NodeRef transfer(String targetName, TransferDefinition definition, TransferCallback... callbacks) 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 callback - a collection of callback handlers that will be called as transfer proceeds. May be null.
|
||||
*
|
||||
* @throws TransferException
|
||||
*/
|
||||
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
|
||||
*/
|
||||
public void transferAsync(String targetName, TransferDefinition definition, TransferCallback... callbacks) throws TransferException;
|
||||
|
||||
/**
|
||||
* Verify a target is available and that the configured credentials correctly identify an admin user.
|
||||
@@ -119,6 +151,13 @@ public interface TransferService
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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
|
||||
@@ -153,4 +192,23 @@ public interface TransferService
|
||||
*/
|
||||
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 handle is returned by a TransferEventBegin event callback.
|
||||
*
|
||||
* @param transferId the unique identifier for the instance of the transfer to cancel.
|
||||
*
|
||||
* @see TransferEventBegin;
|
||||
*/
|
||||
public void cancelAsync(String transferId);
|
||||
|
||||
}
|
||||
|
@@ -63,6 +63,8 @@ public abstract class BaseAlfrescoSpringTest extends BaseSpringTest
|
||||
protected ActionService actionService;
|
||||
protected TransactionService transactionService;
|
||||
|
||||
protected AuthenticationComponent authenticationComponent;
|
||||
|
||||
/**
|
||||
* On setup in transaction override
|
||||
*/
|
||||
@@ -79,7 +81,7 @@ public abstract class BaseAlfrescoSpringTest extends BaseSpringTest
|
||||
this.transactionService = (TransactionService)this.applicationContext.getBean("transactionComponent");
|
||||
|
||||
// Authenticate as the system user
|
||||
AuthenticationComponent authenticationComponent = (AuthenticationComponent) this.applicationContext
|
||||
authenticationComponent = (AuthenticationComponent) this.applicationContext
|
||||
.getBean("authenticationComponent");
|
||||
authenticationComponent.setSystemUserAsCurrentUser();
|
||||
|
||||
|
Reference in New Issue
Block a user