mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Initial work on Replication Service
This covers most of the key interfaces, some initial definition load/save, along with the bootstrap+patch to create the new definition storage area in the data dictionary. No action logic is included yet. Most things are based on the best practices from the Rendition Service. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@20947 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -10,6 +10,7 @@
|
|||||||
<import resource="classpath*:alfresco/portlets-context.xml"/>
|
<import resource="classpath*:alfresco/portlets-context.xml"/>
|
||||||
<import resource="classpath:alfresco/blog-context.xml"/>
|
<import resource="classpath:alfresco/blog-context.xml"/>
|
||||||
<import resource="classpath:alfresco/rendition-services-context.xml"/>
|
<import resource="classpath:alfresco/rendition-services-context.xml"/>
|
||||||
|
<import resource="classpath:alfresco/replication-services-context.xml"/>
|
||||||
<import resource="classpath:alfresco/thumbnail-service-context.xml"/>
|
<import resource="classpath:alfresco/thumbnail-service-context.xml"/>
|
||||||
<import resource="classpath:alfresco/preference-service-context.xml"/>
|
<import resource="classpath:alfresco/preference-service-context.xml"/>
|
||||||
<import resource="classpath:alfresco/swf-transform-context.xml"/>
|
<import resource="classpath:alfresco/swf-transform-context.xml"/>
|
||||||
|
18
config/alfresco/bootstrap/replicationActionSpace.xml
Normal file
18
config/alfresco/bootstrap/replicationActionSpace.xml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<view:view xmlns:view="http://www.alfresco.org/view/repository/1.0"
|
||||||
|
xmlns:d="http://www.alfresco.org/model/dictionary/1.0" xmlns:cm="http://www.alfresco.org/model/content/1.0"
|
||||||
|
xmlns:sys="http://www.alfresco.org/model/system/1.0" xmlns="">
|
||||||
|
|
||||||
|
<cm:folder view:childName="${spaces.replication.replication_actions.childname}">
|
||||||
|
<view:properties>
|
||||||
|
<sys:store-protocol>workspace</sys:store-protocol>
|
||||||
|
<sys:store-identifier>SpacesStore</sys:store-identifier>
|
||||||
|
<sys:node-uuid>replication_actions_space</sys:node-uuid>
|
||||||
|
<cm:name>${spaces.replication.replication_actions.name}</cm:name>
|
||||||
|
<cm:title>${spaces.replication.replication_actions.name}</cm:title>
|
||||||
|
<cm:description>${spaces.replication.replication_actions.description}</cm:description>
|
||||||
|
</view:properties>
|
||||||
|
</cm:folder>
|
||||||
|
|
||||||
|
</view:view>
|
||||||
|
|
@@ -357,6 +357,7 @@
|
|||||||
<prop key="spaces.emailActions.childname">${spaces.emailActions.childname}</prop>
|
<prop key="spaces.emailActions.childname">${spaces.emailActions.childname}</prop>
|
||||||
<prop key="spaces.searchAction.childname">${spaces.searchAction.childname}</prop>
|
<prop key="spaces.searchAction.childname">${spaces.searchAction.childname}</prop>
|
||||||
<prop key="spaces.rendition.rendering_actions.childname">${spaces.rendition.rendering_actions.childname}</prop>
|
<prop key="spaces.rendition.rendering_actions.childname">${spaces.rendition.rendering_actions.childname}</prop>
|
||||||
|
<prop key="spaces.replication.replication_actions.childname">${spaces.replication.replication_actions.childname}</prop>
|
||||||
<prop key="spaces.wcm_deployed.childname">${spaces.wcm_deployed.childname}</prop>
|
<prop key="spaces.wcm_deployed.childname">${spaces.wcm_deployed.childname}</prop>
|
||||||
</props>
|
</props>
|
||||||
</property>
|
</property>
|
||||||
|
@@ -39,6 +39,9 @@ spaces.templates.rss.description=RSS templates
|
|||||||
spaces.rendition.rendering_actions.name=Rendering Actions Space
|
spaces.rendition.rendering_actions.name=Rendering Actions Space
|
||||||
spaces.rendition.rendering_actions.description=A space used by the system to persist rendering actions.
|
spaces.rendition.rendering_actions.description=A space used by the system to persist rendering actions.
|
||||||
|
|
||||||
|
spaces.replication.replication_actions.name=Replication Actions Space
|
||||||
|
spaces.replication.replication_actions.description=A space used by the system to persist replication actions.
|
||||||
|
|
||||||
spaces.savedsearches.name=Saved Searches
|
spaces.savedsearches.name=Saved Searches
|
||||||
spaces.savedsearches.description=Saved Searches
|
spaces.savedsearches.description=Saved Searches
|
||||||
|
|
||||||
|
@@ -115,6 +115,10 @@ patch.rendition.rendering_actions.exists=The Rendering Actions folder already ex
|
|||||||
patch.rendition.rendering_actions.created=The Rendering Actions folder was successfully created: {0}
|
patch.rendition.rendering_actions.created=The Rendering Actions folder was successfully created: {0}
|
||||||
patch.rendition.rendering_actions.description=Creates the Rendering Actions folder.
|
patch.rendition.rendering_actions.description=Creates the Rendering Actions folder.
|
||||||
|
|
||||||
|
patch.replication.replication_actions.exists=The Replication Actions folder already exists: {0}.
|
||||||
|
patch.replication.replication_actions.created=The Replication Actions folder was successfully created: {0}
|
||||||
|
patch.replication.replication_actions.description=Creates the Replication Actions folder.
|
||||||
|
|
||||||
patch.uifacetsAspectRemovalPatch.description=Removes the incorrectly applied uifacets aspect from presentation template files.
|
patch.uifacetsAspectRemovalPatch.description=Removes the incorrectly applied uifacets aspect from presentation template files.
|
||||||
patch.uifacetsAspectRemovalPatch.updated=Successfully removed the uifacets aspect from {0} presentation template files.
|
patch.uifacetsAspectRemovalPatch.updated=Successfully removed the uifacets aspect from {0} presentation template files.
|
||||||
|
|
||||||
|
@@ -2345,4 +2345,26 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="patch.replication.replication_actions" class="org.alfresco.repo.admin.patch.impl.GenericBootstrapPatch" parent="basePatch" >
|
||||||
|
<property name="id"><value>patch.replication.replication_actions</value></property>
|
||||||
|
<property name="description"><value>patch.replication.replication_actions.description</value></property>
|
||||||
|
<property name="fixesFromSchema"><value>0</value></property>
|
||||||
|
<property name="fixesToSchema"><value>4107</value></property>
|
||||||
|
<property name="targetSchema"><value>4108</value></property>
|
||||||
|
<!-- bootstrap view -->
|
||||||
|
<property name="importerBootstrap">
|
||||||
|
<ref bean="spacesBootstrap" />
|
||||||
|
</property>
|
||||||
|
<property name="checkPath">
|
||||||
|
<value>/${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.replication.replication_actions.childname}</value>
|
||||||
|
</property>
|
||||||
|
<property name="bootstrapView">
|
||||||
|
<props>
|
||||||
|
<prop key="path">/${spaces.company_home.childname}/${spaces.dictionary.childname}</prop>
|
||||||
|
<prop key="location">alfresco/bootstrap/replicationActionSpace.xml</prop>
|
||||||
|
<prop key="messages">alfresco/messages/bootstrap-spaces</prop>
|
||||||
|
</props>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
</beans>
|
</beans>
|
80
config/alfresco/replication-services-context.xml
Normal file
80
config/alfresco/replication-services-context.xml
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
<?xml version='1.0' encoding='UTF-8'?>
|
||||||
|
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
|
||||||
|
|
||||||
|
<beans>
|
||||||
|
|
||||||
|
<!-- Replication Service -->
|
||||||
|
|
||||||
|
<bean id="ReplicationService" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||||
|
<property name="proxyInterfaces">
|
||||||
|
<value>org.alfresco.service.cmr.replication.ReplicationService</value>
|
||||||
|
</property>
|
||||||
|
<property name="target">
|
||||||
|
<ref bean="replicationService" />
|
||||||
|
</property>
|
||||||
|
<property name="interceptorNames">
|
||||||
|
<list>
|
||||||
|
<idref local="ReplicationService_transaction" />
|
||||||
|
<idref bean="AuditMethodInterceptor" />
|
||||||
|
<idref bean="exceptionTranslator" />
|
||||||
|
<idref local="ReplicationService_security" />
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!-- Replication service transaction bean -->
|
||||||
|
<bean id="ReplicationService_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>
|
||||||
|
|
||||||
|
<!-- Replication service security bean -->
|
||||||
|
<bean id="ReplicationService_security"
|
||||||
|
class="org.alfresco.repo.security.permissions.impl.AlwaysProceedMethodInterceptor" />
|
||||||
|
|
||||||
|
<!-- Replication Service base bean -->
|
||||||
|
<bean id="replicationService" class="org.alfresco.repo.replication.ReplicationServiceImpl" >
|
||||||
|
<property name="nodeService" ref="NodeService" />
|
||||||
|
<property name="actionService" ref="ActionService"/>
|
||||||
|
<property name="dictionaryService" ref="dictionaryService" />
|
||||||
|
<property name="transferService" ref="TransferService" />
|
||||||
|
<property name="replicationDefinitionPersister" ref="replicationDefinitionPersister" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<bean id="perform-replication" class="org.alfresco.repo.replication.PerformReplicationActionExecuter" parent="action-executer">
|
||||||
|
<property name="publicAction">
|
||||||
|
<value>false</value>
|
||||||
|
</property>
|
||||||
|
<property name="nodeService" ref="NodeService" />
|
||||||
|
<property name="actionService" ref="ActionService"/>
|
||||||
|
<property name="replicationService" ref="replicationService" />
|
||||||
|
<property name="transferService" ref="TransferService" />
|
||||||
|
</bean>
|
||||||
|
-->
|
||||||
|
|
||||||
|
<bean id="replicationDefinitionPersister" class="org.alfresco.repo.replication.ReplicationDefinitionPersisterImpl" >
|
||||||
|
<property name="runtimeActionService" ref="actionService" />
|
||||||
|
<property name="nodeService" ref="NodeService" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- JavaScript API support -->
|
||||||
|
<!--
|
||||||
|
<bean id="replicationServiceScript" parent="baseJavaScriptExtension"
|
||||||
|
class="org.alfresco.repo.replication.script.ScriptReplicationService">
|
||||||
|
<property name="extensionName">
|
||||||
|
<value>replicationService</value>
|
||||||
|
</property>
|
||||||
|
<property name="serviceRegistry" ref="ServiceRegistry"/>
|
||||||
|
</bean>
|
||||||
|
-->
|
||||||
|
|
||||||
|
</beans>
|
@@ -305,6 +305,7 @@ spaces.user_homes.childname=app:user_homes
|
|||||||
spaces.sites.childname=st:sites
|
spaces.sites.childname=st:sites
|
||||||
spaces.templates.email.invite.childname=cm:invite
|
spaces.templates.email.invite.childname=cm:invite
|
||||||
spaces.rendition.rendering_actions.childname=app:rendering_actions
|
spaces.rendition.rendering_actions.childname=app:rendering_actions
|
||||||
|
spaces.replication.replication_actions.childname=app:replication_actions
|
||||||
spaces.wcm_deployed.childname=cm:wcm_deployed
|
spaces.wcm_deployed.childname=cm:wcm_deployed
|
||||||
spaces.transfers.childname=app:transfers
|
spaces.transfers.childname=app:transfers
|
||||||
spaces.transfer_groups.childname=app:transfer_groups
|
spaces.transfer_groups.childname=app:transfer_groups
|
||||||
|
@@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.alfresco.repo.replication;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.alfresco.repo.action.ActionImpl;
|
||||||
|
import org.alfresco.service.cmr.action.Action;
|
||||||
|
import org.alfresco.service.cmr.replication.ReplicationDefinition;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Nick Burch
|
||||||
|
* @since 3.4
|
||||||
|
*/
|
||||||
|
public class ReplicationDefinitionImpl extends ActionImpl implements ReplicationDefinition
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Serial version UID
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 3183721054220388564L;
|
||||||
|
|
||||||
|
public static final String REPLICATION_DEFINITION_NAME = "replicationActionName";
|
||||||
|
|
||||||
|
public String description;
|
||||||
|
public String targetName;
|
||||||
|
public List<NodeRef> payload;
|
||||||
|
public NodeRef localTransferReport;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param id
|
||||||
|
* the action id
|
||||||
|
* @param replicationName
|
||||||
|
* a unique name for the replication action.
|
||||||
|
*/
|
||||||
|
public ReplicationDefinitionImpl(String id, QName replicationName)
|
||||||
|
{
|
||||||
|
this(id, replicationName, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param id
|
||||||
|
* the action id
|
||||||
|
* @param replicationName
|
||||||
|
* a unique name for the replication action.
|
||||||
|
* @param description
|
||||||
|
* a description of the replication
|
||||||
|
*/
|
||||||
|
public ReplicationDefinitionImpl(String id, QName replicationName, String description)
|
||||||
|
{
|
||||||
|
super(null, id);
|
||||||
|
setParameterValue(REPLICATION_DEFINITION_NAME, replicationName);
|
||||||
|
setDescription(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReplicationDefinitionImpl(Action action)
|
||||||
|
{
|
||||||
|
super(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.alfresco.service.cmr.replication.ReplicationDefinition#getReplicationName()
|
||||||
|
*/
|
||||||
|
public QName getReplicationName()
|
||||||
|
{
|
||||||
|
Serializable parameterValue = getParameterValue(REPLICATION_DEFINITION_NAME);
|
||||||
|
return (QName) parameterValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see
|
||||||
|
* org.alfresco.service.cmr.replication.ReplicationDefinition#getPayload()
|
||||||
|
*/
|
||||||
|
public List<NodeRef> getPayload() {
|
||||||
|
if(this.payload == null) {
|
||||||
|
this.payload = new ArrayList<NodeRef>();
|
||||||
|
}
|
||||||
|
return this.payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see
|
||||||
|
* org.alfresco.service.cmr.replication.ReplicationDefinition#getTargetName()
|
||||||
|
*/
|
||||||
|
public String getTargetName() {
|
||||||
|
return this.targetName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see
|
||||||
|
* org.alfresco.service.cmr.replication.ReplicationDefinition#setTargetName(String)
|
||||||
|
*/
|
||||||
|
public void setTargetName(String targetName) {
|
||||||
|
this.targetName = targetName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see
|
||||||
|
* org.alfresco.service.cmr.replication.ReplicationDefinition#getLocalTransferReport()
|
||||||
|
*/
|
||||||
|
public NodeRef getLocalTransferReport() {
|
||||||
|
return localTransferReport;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see
|
||||||
|
* org.alfresco.service.cmr.replication.ReplicationDefinition#setLocalTransferReport(NodeRef)
|
||||||
|
*/
|
||||||
|
public void setLocalTransferReport(NodeRef report) {
|
||||||
|
this.localTransferReport = report;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.alfresco.repo.replication;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.replication.ReplicationDefinition;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class provides the implementation of ReplicationDefinition persistence.
|
||||||
|
*
|
||||||
|
* @author Nick Burch
|
||||||
|
* @since 3.4
|
||||||
|
*/
|
||||||
|
public interface ReplicationDefinitionPersister
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* This method serializes the {@link ReplicationDefinition} and stores it in
|
||||||
|
* the repository. {@link ReplicationDefinition}s saved in this way may be
|
||||||
|
* retrieved using the <code>load()</code> method.
|
||||||
|
*
|
||||||
|
* @param replicationDefinition The {@link ReplicationDefinition} to be
|
||||||
|
* persisted.
|
||||||
|
*/
|
||||||
|
void saveReplicationDefinition(ReplicationDefinition replicationDefinition);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method retrieves a {@link ReplicationDefinition} that has been stored
|
||||||
|
* in the repository using the <code>save()</code> method. If no
|
||||||
|
* {@link ReplicationDefinition} exists in the repository with the specified
|
||||||
|
* rendition name then this method returns null.
|
||||||
|
*
|
||||||
|
* @param replicationName The unique identifier used to specify the
|
||||||
|
* {@link ReplicationDefinition} to retrieve.
|
||||||
|
* @return The specified {@link ReplicationDefinition} or null.
|
||||||
|
*/
|
||||||
|
ReplicationDefinition loadReplicationDefinition(QName replicationName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method retrieves the {@link ReplicationDefinition}s that have been
|
||||||
|
* stored in the repository using the <code>save()</code> method.
|
||||||
|
* <P/>
|
||||||
|
* If there are no such {@link ReplicationDefinition}s, an empty list is
|
||||||
|
* returned.
|
||||||
|
*
|
||||||
|
* @return The {@link ReplicationDefinition}s.
|
||||||
|
*/
|
||||||
|
List<ReplicationDefinition> loadReplicationDefinitions();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method retrieves the stored {@link ReplicationDefinition}s that have
|
||||||
|
* been registered for the specified transfer target name.
|
||||||
|
* <P/>
|
||||||
|
* If there are no such rendering {@link ReplicationDefinition}s, an empty
|
||||||
|
* list is returned.
|
||||||
|
*
|
||||||
|
* @param targetName the name of a target.
|
||||||
|
* @return The {@link ReplicationDefinition}s.
|
||||||
|
* @throws NullPointerException if the target is null.
|
||||||
|
* @see #saveReplicationDefinition(ReplicationDefinition)
|
||||||
|
*/
|
||||||
|
List<ReplicationDefinition> loadReplicationDefinitions(String targetName);
|
||||||
|
}
|
@@ -0,0 +1,192 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.alfresco.repo.replication;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.action.ActionModel;
|
||||||
|
import org.alfresco.repo.action.RuntimeActionService;
|
||||||
|
import org.alfresco.service.cmr.action.Action;
|
||||||
|
import org.alfresco.service.cmr.replication.ReplicationDefinition;
|
||||||
|
import org.alfresco.service.cmr.replication.ReplicationServiceException;
|
||||||
|
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.repository.StoreRef;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class provides the implementation of ReplicationDefinition persistence.
|
||||||
|
*
|
||||||
|
* @author Nick Burch
|
||||||
|
* @since 3.4
|
||||||
|
*/
|
||||||
|
public class ReplicationDefinitionPersisterImpl implements ReplicationDefinitionPersister
|
||||||
|
{
|
||||||
|
/** Reference to the replication action space node */
|
||||||
|
private static final StoreRef SPACES_STORE = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore");
|
||||||
|
protected static final NodeRef REPLICATION_ACTION_ROOT_NODE_REF = new NodeRef(SPACES_STORE, "replication_actions_space");
|
||||||
|
|
||||||
|
/* Injected services */
|
||||||
|
private NodeService nodeService;
|
||||||
|
private RuntimeActionService runtimeActionService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injects the NodeService bean.
|
||||||
|
*
|
||||||
|
* @param nodeService the NodeService.
|
||||||
|
*/
|
||||||
|
public void setNodeService(NodeService nodeService)
|
||||||
|
{
|
||||||
|
this.nodeService = nodeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injects the RuntimeActionService bean.
|
||||||
|
*
|
||||||
|
* @param runtimeActionService the RuntimeActionService.
|
||||||
|
*/
|
||||||
|
public void setRuntimeActionService(RuntimeActionService runtimeActionService)
|
||||||
|
{
|
||||||
|
this.runtimeActionService = runtimeActionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ReplicationDefinition> loadReplicationDefinitions()
|
||||||
|
{
|
||||||
|
checkReplicationActionRootNodeExists();
|
||||||
|
|
||||||
|
// Note that in the call to getChildAssocs below, only the specified
|
||||||
|
// types are included.
|
||||||
|
// Subtypes of the type action:action will not be returned.
|
||||||
|
Set<QName> actionTypes = new HashSet<QName>();
|
||||||
|
actionTypes.add(ActionModel.TYPE_ACTION);
|
||||||
|
|
||||||
|
List<ChildAssociationRef> childAssocs = nodeService.getChildAssocs(REPLICATION_ACTION_ROOT_NODE_REF, actionTypes);
|
||||||
|
|
||||||
|
List<ReplicationDefinition> renderingActions = new ArrayList<ReplicationDefinition>(childAssocs.size());
|
||||||
|
for (ChildAssociationRef actionAssoc : childAssocs)
|
||||||
|
{
|
||||||
|
Action nextAction = runtimeActionService.createAction(actionAssoc.getChildRef());
|
||||||
|
renderingActions.add(new ReplicationDefinitionImpl(nextAction));
|
||||||
|
}
|
||||||
|
|
||||||
|
return renderingActions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ReplicationDefinition> loadReplicationDefinitions(String targetName)
|
||||||
|
{
|
||||||
|
if (targetName == null)
|
||||||
|
{
|
||||||
|
throw new NullPointerException("Unexpected null target");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ReplicationDefinition> allReplicationDefinitions = this.loadReplicationDefinitions();
|
||||||
|
|
||||||
|
List<ReplicationDefinition> filteredReplicationDefinitions = new ArrayList<ReplicationDefinition>();
|
||||||
|
for (ReplicationDefinition replicationAction : allReplicationDefinitions)
|
||||||
|
{
|
||||||
|
if (targetName.equals(replicationAction.getTargetName()))
|
||||||
|
{
|
||||||
|
filteredReplicationDefinitions.add(replicationAction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filteredReplicationDefinitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ReplicationDefinition loadReplicationDefinition(QName replicationDefinitionName)
|
||||||
|
{
|
||||||
|
NodeRef actionNode = findActionNode(replicationDefinitionName);
|
||||||
|
if (actionNode != null)
|
||||||
|
{
|
||||||
|
Action action = runtimeActionService.createAction(actionNode);
|
||||||
|
return new ReplicationDefinitionImpl(action);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveReplicationDefinition(ReplicationDefinition replicationAction)
|
||||||
|
{
|
||||||
|
NodeRef actionNodeRef = findOrCreateActionNode(replicationAction);
|
||||||
|
|
||||||
|
// TODO Serialize using JSON content instead.
|
||||||
|
// The current serialization mechanism creates a complex content model
|
||||||
|
// structure which is verbose and a JSON-based approach using a simplified
|
||||||
|
// content model perhaps could offer performance improvements.
|
||||||
|
runtimeActionService.saveActionImpl(actionNodeRef, replicationAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
private NodeRef findActionNode(QName replicationDefinitionName)
|
||||||
|
{
|
||||||
|
checkReplicationActionRootNodeExists();
|
||||||
|
List<ChildAssociationRef> childAssocs = nodeService.getChildAssocs(//
|
||||||
|
REPLICATION_ACTION_ROOT_NODE_REF,//
|
||||||
|
ContentModel.ASSOC_CONTAINS,//
|
||||||
|
replicationDefinitionName);
|
||||||
|
if (childAssocs.isEmpty())
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (childAssocs.size() > 1)
|
||||||
|
{
|
||||||
|
throw new ReplicationServiceException("Multiple replication definitions with the name: "
|
||||||
|
+ replicationDefinitionName + " exist!");
|
||||||
|
}
|
||||||
|
return childAssocs.get(0).getChildRef();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private NodeRef findOrCreateActionNode(ReplicationDefinition replicationAction)
|
||||||
|
{
|
||||||
|
QName actionName = replicationAction.getReplicationName();
|
||||||
|
NodeRef actionNode = findActionNode(actionName);
|
||||||
|
if (actionNode == null)
|
||||||
|
{
|
||||||
|
actionNode = runtimeActionService.createActionNodeRef(//
|
||||||
|
replicationAction,//
|
||||||
|
REPLICATION_ACTION_ROOT_NODE_REF,//
|
||||||
|
ContentModel.ASSOC_CONTAINS,//
|
||||||
|
actionName);
|
||||||
|
}
|
||||||
|
return actionNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method checks whether the folder containing Replication Action nodes
|
||||||
|
* exists.
|
||||||
|
*
|
||||||
|
* @throws ReplicationServiceException if the folder node does not exist.
|
||||||
|
*/
|
||||||
|
private void checkReplicationActionRootNodeExists()
|
||||||
|
{
|
||||||
|
if (nodeService.exists(REPLICATION_ACTION_ROOT_NODE_REF) == false)
|
||||||
|
{
|
||||||
|
throw new ReplicationServiceException("Unable to find replication action root node.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.replication;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.action.ActionService;
|
||||||
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
|
import org.alfresco.service.cmr.replication.ReplicationDefinition;
|
||||||
|
import org.alfresco.service.cmr.replication.ReplicationService;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeService;
|
||||||
|
import org.alfresco.service.cmr.transfer.TransferService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.util.GUID;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @author Nick Burch
|
||||||
|
* @since 3.4
|
||||||
|
*/
|
||||||
|
public class ReplicationServiceImpl implements ReplicationService, ReplicationDefinitionPersister {
|
||||||
|
private static final Log log = LogFactory.getLog(ReplicationServiceImpl.class);
|
||||||
|
|
||||||
|
private ActionService actionService;
|
||||||
|
private DictionaryService dictionaryService;
|
||||||
|
private TransferService transferService;
|
||||||
|
private NodeService nodeService;
|
||||||
|
|
||||||
|
private ReplicationDefinitionPersisterImpl replicationDefinitionPersister;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injects the ReplicationDefinitionPersister bean.
|
||||||
|
* @param replicationDefinitionPersister
|
||||||
|
*/
|
||||||
|
public void setReplicationDefinitionPersister(ReplicationDefinitionPersisterImpl replicationDefinitionPersister)
|
||||||
|
{
|
||||||
|
this.replicationDefinitionPersister = replicationDefinitionPersister;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injects the TransferService bean
|
||||||
|
* @param transferService
|
||||||
|
*/
|
||||||
|
public void setTransferService(TransferService transferService)
|
||||||
|
{
|
||||||
|
this.transferService = transferService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injects the NodeService bean.
|
||||||
|
* @param nodeService
|
||||||
|
*/
|
||||||
|
public void setNodeService(NodeService nodeService)
|
||||||
|
{
|
||||||
|
this.nodeService = nodeService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injects the ActionService bean.
|
||||||
|
* @param actionService
|
||||||
|
*/
|
||||||
|
public void setActionService(ActionService actionService)
|
||||||
|
{
|
||||||
|
this.actionService = actionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Injects the DictionaryService bean.
|
||||||
|
* @param dictionaryService
|
||||||
|
*/
|
||||||
|
public void setDictionaryService(DictionaryService dictionaryService)
|
||||||
|
{
|
||||||
|
this.dictionaryService = dictionaryService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see
|
||||||
|
* org.alfresco.service.cmr.replication.ReplicationService#createReplicationDefinition
|
||||||
|
* (org.alfresco.service.namespace.QName, java.lang.String)
|
||||||
|
*/
|
||||||
|
public ReplicationDefinition createReplicationDefinition(
|
||||||
|
QName replicationDefinitionName, String description) {
|
||||||
|
if (log.isDebugEnabled())
|
||||||
|
{
|
||||||
|
StringBuilder msg = new StringBuilder();
|
||||||
|
msg.append("Creating replication definition ")
|
||||||
|
.append(replicationDefinitionName);
|
||||||
|
log.debug(msg.toString());
|
||||||
|
}
|
||||||
|
return new ReplicationDefinitionImpl(GUID.generate(), replicationDefinitionName, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see
|
||||||
|
* org.alfresco.service.cmr.replication.ReplicationService#loadReplicationDefinition
|
||||||
|
* (org.alfresco.service.namespace.QName)
|
||||||
|
*/
|
||||||
|
public ReplicationDefinition loadReplicationDefinition(QName replicationDefinitionName) {
|
||||||
|
return replicationDefinitionPersister.loadReplicationDefinition(replicationDefinitionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see
|
||||||
|
* org.alfresco.service.cmr.replication.ReplicationService#loadReplicationDefinitions()
|
||||||
|
*/
|
||||||
|
public List<ReplicationDefinition> loadReplicationDefinitions() {
|
||||||
|
return replicationDefinitionPersister.loadReplicationDefinitions();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see
|
||||||
|
* org.alfresco.service.cmr.replication.ReplicationService#loadReplicationDefinitions
|
||||||
|
* (String)
|
||||||
|
*/
|
||||||
|
public List<ReplicationDefinition> loadReplicationDefinitions(String target) {
|
||||||
|
return replicationDefinitionPersister.loadReplicationDefinitions(target); // TODO is this right
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see
|
||||||
|
* org.alfresco.service.cmr.replication.ReplicationService#saveReplicationDefinition
|
||||||
|
* (ReplicationDefinition)
|
||||||
|
*/
|
||||||
|
public void saveReplicationDefinition(
|
||||||
|
ReplicationDefinition replicationDefinition) {
|
||||||
|
replicationDefinitionPersister.saveReplicationDefinition(replicationDefinition);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
* @see
|
||||||
|
* org.alfresco.service.cmr.replication.ReplicationService#replication
|
||||||
|
* (ReplicationDefinition)
|
||||||
|
*/
|
||||||
|
public void replicate(ReplicationDefinition replicationDefinition) {
|
||||||
|
// TODO Implement the replication work
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.service.cmr.replication;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.action.Action;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is used to fully specify an inter-repository replication. It
|
||||||
|
* specifies which node(s) should be transfered, which associated content
|
||||||
|
* should be sent with them, and which target they should be sent to.
|
||||||
|
* <P/>
|
||||||
|
* Every ReplicationDefinition has a <code>replicationName</code> attribute
|
||||||
|
* which uniquely identifies it. It also has a single target.
|
||||||
|
*
|
||||||
|
* @author Nick Burch
|
||||||
|
*/
|
||||||
|
public interface ReplicationDefinition extends Action, Serializable {
|
||||||
|
/**
|
||||||
|
* @return the name which uniquely identifies this replication definition.
|
||||||
|
*/
|
||||||
|
QName getReplicationName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the name of the target repository.
|
||||||
|
*/
|
||||||
|
String getTargetName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the name of the target repository.
|
||||||
|
*/
|
||||||
|
void setTargetName(String targetName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of Nodes to be transfered. This
|
||||||
|
* list can be edited as required.
|
||||||
|
* @return An editable list of the nodes to be transfered
|
||||||
|
*/
|
||||||
|
List<NodeRef> getPayload();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the local side of the report on
|
||||||
|
* the transfer.
|
||||||
|
* The transfer service generates two reports,
|
||||||
|
* one on the local repository, and one on the
|
||||||
|
* remote repository. This returns the
|
||||||
|
* local version of the report.
|
||||||
|
* @return The transfer report on the local repository
|
||||||
|
*/
|
||||||
|
NodeRef getLocalTransferReport();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Records the location on the local repository
|
||||||
|
* of the transfer service report on the
|
||||||
|
* replication.
|
||||||
|
*/
|
||||||
|
void setLocalTransferReport(NodeRef report);
|
||||||
|
|
||||||
|
// TODO Persistent action bits of last start, last finish, worked
|
||||||
|
|
||||||
|
// TODO Replication options, such as permissions and rules
|
||||||
|
}
|
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.service.cmr.replication;
|
||||||
|
|
||||||
|
import org.alfresco.repo.replication.ReplicationDefinitionPersister;
|
||||||
|
import org.alfresco.service.NotAuditable;
|
||||||
|
import org.alfresco.service.PublicService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Replication service.
|
||||||
|
* @author Nick Burch
|
||||||
|
*/
|
||||||
|
@PublicService
|
||||||
|
public interface ReplicationService extends ReplicationDefinitionPersister {
|
||||||
|
/**
|
||||||
|
* Creates a new {@link ReplicationDefinition} and sets the replication
|
||||||
|
* name and description to the specified values.
|
||||||
|
* @param replicationName A unique identifier used to specify the created
|
||||||
|
* {@link ReplicationDefinition}
|
||||||
|
* @param description A description of the replication
|
||||||
|
* @return the created {@link ReplicationDefinition}
|
||||||
|
*/
|
||||||
|
@NotAuditable
|
||||||
|
ReplicationDefinition createReplicationDefinition(QName replicationName, String description);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the specified replication.
|
||||||
|
* @param replicationDefinition The replication to run
|
||||||
|
*/
|
||||||
|
@NotAuditable
|
||||||
|
void replicate(ReplicationDefinition replicationDefinition);
|
||||||
|
}
|
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2010 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This file is part of Alfresco
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package org.alfresco.service.cmr.replication;
|
||||||
|
|
||||||
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replication Service Exception Class
|
||||||
|
*
|
||||||
|
* @author Nick Burch
|
||||||
|
*/
|
||||||
|
public class ReplicationServiceException extends AlfrescoRuntimeException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 3961767729869569556L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a Replication Service Exception with the specified message.
|
||||||
|
*
|
||||||
|
* @param message the message string
|
||||||
|
*/
|
||||||
|
public ReplicationServiceException(String message)
|
||||||
|
{
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a Replication Service Exception with the specified message and source exception.
|
||||||
|
*
|
||||||
|
* @param message the message string
|
||||||
|
* @param source the source exception
|
||||||
|
*/
|
||||||
|
public ReplicationServiceException(String message, Throwable source)
|
||||||
|
{
|
||||||
|
super(message, source);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user