Reworked transaction package structure and refactored to extract generic compensating transaction functionality.

This commit is contained in:
Mattias Arthursson
2007-04-20 17:45:47 +00:00
parent 96fa2e3afa
commit bdc14b05ba
67 changed files with 996 additions and 704 deletions

View File

@@ -50,5 +50,6 @@
<classpathentry kind="lib" path="lib/test/aopalliance.jar"/>
<classpathentry kind="lib" path="lib/test/spring-aop.jar" sourcepath="lib/source/spring-src.zip"/>
<classpathentry kind="lib" path="lib/test/hsqldb.jar"/>
<classpathentry kind="lib" path="lib/test/commons-collections.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@@ -1,108 +1,135 @@
<?xml version="1.0" encoding="UTF-8"?>
<ivy-module version="1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<ivy-module version="1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.jayasoft.org/misc/ivy/samples/ivy.xsd">
<info organisation="org.springframework" module="spring-ldap" />
<info organisation="org.springframework" module="spring-ldap" />
<configurations>
<conf name="default" extends="global" />
<conf name="global" visibility="private" />
<conf name="buildtime" visibility="private" />
<conf name="test" visibility="private" />
<conf name="source" visibility="public" />
</configurations>
<configurations>
<conf name="default" extends="global" />
<conf name="global" visibility="private" />
<conf name="buildtime" visibility="private" />
<conf name="test" visibility="private" />
<conf name="source" visibility="public" />
</configurations>
<publications>
<artifact name="spring-ldap" type="jar" conf="default" />
<artifact name="spring-ldap-src" type="zip" conf="source" />
</publications>
<dependencies defaultconf="global->default">
<!-- global (core) dependencies -->
<dependency org="commons-logging" name="commons-logging" rev="1.0.4" />
<dependency org="commons-lang" name="commons-lang" rev="2.1" />
<dependency org="org.springframework" name="spring-beans" rev="2.0.4"/>
<dependency org="org.springframework" name="spring-core" rev="2.0.4"/>
<dependency org="org.springframework" name="spring-context" rev="2.0.4"/>
<dependency org="org.springframework" name="spring-dao" rev="2.0.4"/>
<dependency org="org.springframework" name="spring-src" rev="2.0.4" conf="source->source">
<artifact name="spring-src" type="zip"/>
</dependency>
<dependency org="com.sun" name="ldapbp" rev="1.0" />
<!-- build time only dependencies -->
<dependency org="org.acegisecurity" name="acegi-security" rev="1.0.1"
conf="buildtime->default" />
<!-- kind of nasty, acegi needs some 1.2.7 stuff, so we override with newer! -->
<dependency org="org.springframework" name="spring-jdbc" rev="2.0.4"
conf="buildtime->default" />
<dependency org="org.springframework" name="spring-remoting" rev="2.0.4"
conf="buildtime->default" />
<dependency org="org.springframework" name="spring-support" rev="2.0.4"
conf="buildtime->default" />
<dependencies defaultconf="global->default">
<!-- global (core) dependencies -->
<dependency org="commons-logging" name="commons-logging"
rev="1.0.4" />
<dependency org="commons-lang" name="commons-lang" rev="2.1" />
<dependency org="org.springframework" name="spring-beans"
rev="2.0.4" />
<dependency org="org.springframework" name="spring-core"
rev="2.0.4" />
<dependency org="org.springframework" name="spring-context"
rev="2.0.4" />
<dependency org="org.springframework" name="spring-dao"
rev="2.0.4" />
<dependency org="org.springframework" name="spring-src"
rev="2.0.4" conf="source->source">
<artifact name="spring-src" type="zip" />
</dependency>
<dependency org="com.sun" name="ldapbp" rev="1.0" />
<!-- build time only dependencies -->
<dependency org="org.acegisecurity" name="acegi-security"
rev="1.0.1" conf="buildtime->default" />
<!-- kind of nasty, acegi needs some 1.2.7 stuff, so we override with newer! -->
<dependency org="org.springframework" name="spring-jdbc"
rev="2.0.4" conf="buildtime->default" />
<dependency org="org.springframework" name="spring-remoting"
rev="2.0.4" conf="buildtime->default" />
<dependency org="org.springframework" name="spring-support"
rev="2.0.4" conf="buildtime->default" />
<dependency org="org.tigris" name="svnant" rev="1.0.0"
conf="buildtime->default">
<artifact name="svnant" type="jar" />
<artifact name="svnClientAdapter" type="jar" />
<artifact name="svnjavahl" type="jar" />
</dependency>
<dependency org="org.tigris" name="svnant" rev="1.0.0" conf="buildtime->default">
<artifact name="svnant" type="jar"/>
<artifact name="svnClientAdapter" type="jar"/>
<artifact name="svnjavahl" type="jar"/>
</dependency>
<!-- test time only dependencies -->
<dependency org="commons-collections" name="commons-collections"
rev="3.1" conf="test->default" />
<dependency org="com.cenqua.clover" name="clover" rev="1.3.12"
conf="test->default" />
<dependency org="org.springframework" name="spring-mock"
rev="2.0.4" conf="test->default" />
<dependency org="gsbase" name="gsbase" rev="2.0.1"
conf="test->default" />
<dependency org="junit" name="junit" rev="3.8.1"
conf="test->default" />
<dependency org="junit-addons" name="junit-addons" rev="1.4"
conf="test->default" />
<dependency org="junitperf" name="junitperf" rev="1.8"
conf="test->default" />
<dependency org="easymock" name="easymock" rev="1.2_Java1.3"
conf="test->default" />
<dependency org="ehcache" name="ehcache" rev="1.1"
conf="test->default" />
<dependency org="net.sf.ehcache" name="ehcache-constructs"
rev="0.6" conf="test->default" />
<dependency org="jexcelapi" name="jxl" rev="2.5.9"
conf="test->default" />
<dependency org="org.ddsteps" name="DDSteps" rev="1.1"
conf="test->default" />
<dependency org="cglib" name="cglib-nodep" rev="2.1_3"
conf="test->default" />
<dependency org="org.springframework" name="spring-aop"
rev="2.0.4" conf="test->default" />
<dependency org="aopalliance" name="aopalliance" rev="1.0"
conf="test->default" />
<dependency org="hsqldb" name="hsqldb" rev="1.8.0.7"
conf="test->default" />
<!-- test time only dependencies -->
<dependency org="com.cenqua.clover" name="clover" rev="1.3.12" conf="test->default" />
<dependency org="org.springframework" name="spring-mock" rev="2.0.4"
conf="test->default"/>
<dependency org="gsbase" name="gsbase" rev="2.0.1" conf="test->default"/>
<dependency org="junit" name="junit" rev="3.8.1" conf="test->default"/>
<dependency org="junit-addons" name="junit-addons" rev="1.4" conf="test->default"/>
<dependency org="junitperf" name="junitperf" rev="1.8" conf="test->default"/>
<dependency org="easymock" name="easymock" rev="1.2_Java1.3" conf="test->default"/>
<dependency org="ehcache" name="ehcache" rev="1.1" conf="test->default" />
<dependency org="net.sf.ehcache" name="ehcache-constructs" rev="0.6" conf="test->default" />
<dependency org="jexcelapi" name="jxl" rev="2.5.9" conf="test->default" />
<dependency org="org.ddsteps" name="DDSteps" rev="1.1" conf="test->default" />
<dependency org="cglib" name="cglib-nodep" rev="2.1_3" conf="test->default"/>
<dependency org="org.springframework" name="spring-aop" rev="2.0.4" conf="test->default" />
<dependency org="aopalliance" name="aopalliance" rev="1.0" conf="test->default" />
<dependency org="hsqldb" name="hsqldb" rev="1.8.0.7" conf="test->default" />
<!-- Test dependencies for Apache Directory Server -->
<dependency org="org.apache.directory.server" name="apacheds-core" rev="1.0.0"
conf="test->default"/>
<dependency org="org.apache.directory.server" name="apacheds-core-shared" rev="1.0.0"
conf="test->default"/>
<dependency org="org.apache.directory.server" name="apacheds-server-jndi" rev="1.0.0"
conf="test->default"/>
<dependency org="org.apache.directory.server" name="apacheds-server-main" rev="1.0.0"
conf="test->default"/>
<dependency org="org.apache.directory.server" name="apacheds-protocol-shared" rev="1.0.0"
conf="test->default"/>
<dependency org="org.apache.directory.server" name="apacheds-protocol-changepw" rev="1.0.0"
conf="test->default"/>
<dependency org="org.apache.directory.server" name="apacheds-protocol-kerberos" rev="1.0.0"
conf="test->default"/>
<dependency org="org.apache.directory.server" name="apacheds-kerberos-shared" rev="1.0.0"
conf="test->default"/>
<dependency org="org.apache.directory.server" name="apacheds-protocol-ldap" rev="1.0.0"
conf="test->default"/>
<!-- Test dependencies for Apache Directory Server -->
<dependency org="org.apache.directory.server"
name="apacheds-core" rev="1.0.0" conf="test->default" />
<dependency org="org.apache.directory.server"
name="apacheds-core-shared" rev="1.0.0" conf="test->default" />
<dependency org="org.apache.directory.server"
name="apacheds-server-jndi" rev="1.0.0" conf="test->default" />
<dependency org="org.apache.directory.server"
name="apacheds-server-main" rev="1.0.0" conf="test->default" />
<dependency org="org.apache.directory.server"
name="apacheds-protocol-shared" rev="1.0.0" conf="test->default" />
<dependency org="org.apache.directory.server"
name="apacheds-protocol-changepw" rev="1.0.0" conf="test->default" />
<dependency org="org.apache.directory.server"
name="apacheds-protocol-kerberos" rev="1.0.0" conf="test->default" />
<dependency org="org.apache.directory.server"
name="apacheds-kerberos-shared" rev="1.0.0" conf="test->default" />
<dependency org="org.apache.directory.server"
name="apacheds-protocol-ldap" rev="1.0.0" conf="test->default" />
<dependency org="org.apache.directory.shared" name="shared-asn1" rev="0.9.5.3"
conf="test->default"/>
<dependency org="org.apache.directory.shared" name="shared-asn1-codec" rev="0.9.5.3"
conf="test->default"/>
<dependency org="org.apache.directory.shared" name="shared-ldap" rev="0.9.5.3"
conf="test->default"/>
<dependency org="org.apache.directory.shared" name="shared-asn1"
rev="0.9.5.3" conf="test->default" />
<dependency org="org.apache.directory.shared"
name="shared-asn1-codec" rev="0.9.5.3" conf="test->default" />
<dependency org="org.apache.directory.shared" name="shared-ldap"
rev="0.9.5.3" conf="test->default" />
<dependency org="log4j" name="log4j" rev="1.2.9" conf="test->default" />
<dependency org="antlr" name="antlr" rev="2.7.2" conf="test->default" />
<dependency org="jdbm" name="jdbm" rev="1.0" conf="test->default" />
<dependency org="org.slf4j" name="slf4j-log4j12" rev="1.0"
conf="test->default" />
<dependency org="org.apache.mina" name="mina-core" rev="1.0.0"
conf="test->default"/>
<dependency org="org.apache.mina" name="mina-filter-ssl" rev="1.0.0"
conf="test->default"/>
<!-- End test dependencies for Apache Directory Server -->
<dependency org="log4j" name="log4j" rev="1.2.9"
conf="test->default" />
<dependency org="antlr" name="antlr" rev="2.7.2"
conf="test->default" />
<dependency org="jdbm" name="jdbm" rev="1.0"
conf="test->default" />
<dependency org="org.slf4j" name="slf4j-log4j12" rev="1.0"
conf="test->default" />
<dependency org="org.apache.mina" name="mina-core" rev="1.0.0"
conf="test->default" />
<dependency org="org.apache.mina" name="mina-filter-ssl"
rev="1.0.0" conf="test->default" />
<!-- End test dependencies for Apache Directory Server -->
</dependencies>
</dependencies>
</ivy-module>

View File

@@ -31,7 +31,7 @@
</bean>
<bean id="contextSource"
class="org.springframework.ldap.transaction.support.TransactionAwareContextSourceProxy">
class="org.springframework.ldap.transaction.core.TransactionAwareContextSourceProxy">
<constructor-arg ref="contextSourceTarget" />
</bean>
@@ -47,21 +47,21 @@
<!--
<bean id="ldapTransactionManager"
class="org.springframework.ldap.transaction.support.ContextSourceTransactionManager">
class="org.springframework.ldap.transaction.core.ContextSourceTransactionManager">
<property name="contextSource" ref="contextSourceTarget" />
</bean>
-->
<bean id="transactionManager"
class="org.springframework.ldap.transaction.support.ContextSourceAndDataSourceTransactionManager">
class="org.springframework.ldap.transaction.core.ContextSourceAndDataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
<property name="contextSource" ref="contextSource" />
</bean>
<bean name="dummyDaoTarget"
class="org.springframework.ldap.transaction.support.LdapAndJdbcDummyDaoImpl">
class="org.springframework.ldap.transaction.core.LdapAndJdbcDummyDaoImpl">
<property name="ldapTemplate" ref="ldapTemplate" />
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>

View File

@@ -23,7 +23,7 @@
</bean>
<bean id="contextSource"
class="org.springframework.ldap.transaction.support.TransactionAwareContextSourceProxy">
class="org.springframework.ldap.transaction.core.TransactionAwareContextSourceProxy">
<constructor-arg ref="contextSourceTarget" />
</bean>
@@ -33,13 +33,13 @@
</bean>
<bean id="transactionManager"
class="org.springframework.ldap.transaction.support.ContextSourceTransactionManager">
class="org.springframework.ldap.transaction.core.ContextSourceTransactionManager">
<property name="contextSource" ref="contextSource" />
</bean>
<bean name="dummyDaoTarget"
class="org.springframework.ldap.transaction.support.LdapDummyDaoImpl">
class="org.springframework.ldap.transaction.core.LdapDummyDaoImpl">
<property name="ldapTemplate" ref="ldapTemplate" />
</bean>

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.support;
package org.springframework.ldap.transaction.core;
import java.sql.ResultSet;
import java.sql.SQLException;
@@ -30,7 +30,7 @@ import org.springframework.ldap.LdapServerManager;
import org.springframework.ldap.NameNotFoundException;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.transaction.support.ContextSourceAndDataSourceTransactionManager;
import org.springframework.ldap.transaction.core.ContextSourceAndDataSourceTransactionManager;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
import org.springframework.transaction.support.TransactionSynchronizationManager;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.support;
package org.springframework.ldap.transaction.core;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
@@ -24,7 +24,7 @@ import org.springframework.ldap.LdapServerManager;
import org.springframework.ldap.NameNotFoundException;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.transaction.support.ContextSourceAndDataSourceTransactionManager;
import org.springframework.ldap.transaction.core.ContextSourceAndDataSourceTransactionManager;
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
import org.springframework.transaction.support.TransactionSynchronizationManager;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.support;
package org.springframework.ldap.transaction.core;
public interface DummyDao {
void createWithException(String country, String company, String fullname,

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.support;
package org.springframework.ldap.transaction.core;
public class DummyException extends RuntimeException {
public DummyException(String message) {

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.support;
package org.springframework.ldap.transaction.core;
public class DummyServiceImpl {
private DummyDao dummyDaoImpl;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.support;
package org.springframework.ldap.transaction.core;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.ldap.core.DirContextAdapter;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.support;
package org.springframework.ldap.transaction.core;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DistinguishedName;

View File

@@ -13,15 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction;
package org.springframework.ldap.core;
import javax.naming.directory.DirContext;
import org.springframework.ldap.transaction.support.TransactionAwareContextSourceProxy;
/**
* Helper interface to be able to get hold of the target DirContext from proxies
* created by {@link TransactionAwareContextSourceProxy}.
* created by ContextSource proxies.
*
* @author Mattias Arthursson
*/

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import javax.naming.Name;
import javax.naming.directory.Attributes;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import javax.naming.Name;
import javax.naming.directory.Attributes;
@@ -57,7 +57,7 @@ public class BindOperationRecorder implements
throw new IllegalArgumentException(
"Invalid arguments for bind operation");
}
Name dn = TransactionUtils.getFirstArgumentAsName(args);
Name dn = LdapTransactionUtils.getFirstArgumentAsName(args);
Object object = args[1];
Attributes attributes = null;
if (args[2] != null && !(args[2] instanceof Attributes)) {

View File

@@ -13,14 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import javax.naming.directory.DirContext;
import org.springframework.transaction.compensating.CompensatingTransactionOperationFactory;
import org.springframework.transaction.compensating.CompensatingTransactionOperationManager;
import org.springframework.transaction.compensating.DefaultCompensatingTransactionOperationManager;
import org.springframework.transaction.support.ResourceHolderSupport;
import org.springframework.transaction.compensating.support.CompensatingTransactionHolderSupport;
/**
* Keeps track of the transaction DirContext. The same DirContext instance will
@@ -32,13 +31,9 @@ import org.springframework.transaction.support.ResourceHolderSupport;
* @author Mattias Arthursson
*
*/
public class DirContextHolder extends ResourceHolderSupport {
public class DirContextHolder extends CompensatingTransactionHolderSupport {
private DirContext ctx;
private CompensatingTransactionOperationManager transactionOperationManager;
private CompensatingTransactionOperationFactory operationFactory;
private TempEntryRenamingStrategy renamingStrategy;
/**
@@ -51,8 +46,7 @@ public class DirContextHolder extends ResourceHolderSupport {
TempEntryRenamingStrategy renamingStrategy) {
this.ctx = ctx;
this.renamingStrategy = renamingStrategy;
this.transactionOperationManager = new DefaultCompensatingTransactionOperationManager(
createOperationFactory());
refreshTransactionOperationManager();
}
/**
@@ -63,19 +57,10 @@ public class DirContextHolder extends ResourceHolderSupport {
*/
public void setCtx(DirContext ctx) {
this.ctx = ctx;
this.transactionOperationManager = new DefaultCompensatingTransactionOperationManager(
createOperationFactory());
refreshTransactionOperationManager();
}
/**
* Factory method to create a
* {@link CompensatingTransactionOperationFactory} using the settings and
* current state of this object.
*
* @return a new {@link LdapCompensatingTransactionOperationFactory}
* referncing the current transaction context.
*/
private CompensatingTransactionOperationFactory createOperationFactory() {
protected CompensatingTransactionOperationFactory createOperationFactory() {
return new LdapCompensatingTransactionOperationFactory(ctx,
renamingStrategy);
}
@@ -87,38 +72,6 @@ public class DirContextHolder extends ResourceHolderSupport {
return ctx;
}
public void clear() {
super.clear();
transactionOperationManager = null;
operationFactory = null;
}
/**
* Get the CompensatingTransactionOperationManager to handle the data for
* the current transaction.
*
* @return the CompensatingTransactionOperationManager.
*/
public CompensatingTransactionOperationManager getTransactionOperationManager() {
return transactionOperationManager;
}
/**
* Set the CompensatingTransactionOperationManager. For testing purposes
* only.
*
* @param transactionOperationManager
* the CompensatingTransactionOperationManager to use.
*/
public void setTransactionOperationManager(
CompensatingTransactionOperationManager transactionOperationManager) {
this.transactionOperationManager = transactionOperationManager;
}
public CompensatingTransactionOperationFactory getOperationFactory() {
return operationFactory;
}
public TempEntryRenamingStrategy getRenamingStrategy() {
return renamingStrategy;
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
@@ -27,6 +27,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.ldap.NamingException;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.core.DirContextProxy;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.transaction.compensating.CompensatingTransactionOperationFactory;
@@ -61,19 +62,19 @@ public class LdapCompensatingTransactionOperationFactory implements
public CompensatingTransactionOperationRecorder createRecordingOperation(
String operation) {
if (StringUtils.equals(operation, TransactionUtils.BIND_METHOD_NAME)) {
if (StringUtils.equals(operation, LdapTransactionUtils.BIND_METHOD_NAME)) {
log.debug("Bind operation recorded");
return new BindOperationRecorder(ldapOperations);
} else if (StringUtils.equals(operation, TransactionUtils.REBIND_METHOD_NAME)) {
} else if (StringUtils.equals(operation, LdapTransactionUtils.REBIND_METHOD_NAME)) {
log.debug("Rebind operation recorded");
return new RebindOperationRecorder(ldapOperations, renamingStrategy);
} else if (StringUtils.equals(operation, TransactionUtils.RENAME_METHOD_NAME)) {
} else if (StringUtils.equals(operation, LdapTransactionUtils.RENAME_METHOD_NAME)) {
log.debug("Rename operation recorded");
return new RenameOperationRecorder(ldapOperations);
} else if (StringUtils.equals(operation,
TransactionUtils.MODIFY_ATTRIBUTES_METHOD_NAME)) {
LdapTransactionUtils.MODIFY_ATTRIBUTES_METHOD_NAME)) {
return new ModifyAttributesOperationRecorder(ldapOperations);
} else if (StringUtils.equals(operation, TransactionUtils.UNBIND_METHOD_NAME)) {
} else if (StringUtils.equals(operation, LdapTransactionUtils.UNBIND_METHOD_NAME)) {
return new UnbindOperationRecorder(ldapOperations, renamingStrategy);
}
@@ -124,7 +125,7 @@ public class LdapCompensatingTransactionOperationFactory implements
private DirContext getNonClosingDirContextProxy(DirContext context) {
return (DirContext) Proxy.newProxyInstance(DirContextProxy.class
.getClassLoader(), new Class[] {
TransactionUtils.getActualTargetClass(context),
LdapTransactionUtils.getActualTargetClass(context),
DirContextProxy.class },
new NonClosingDirContextInvocationHandler(context));

View File

@@ -14,10 +14,7 @@
* limitations under the License.
*/
package org.springframework.ldap.transaction;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
package org.springframework.ldap.transaction.compensating;
import javax.naming.Name;
import javax.naming.directory.DirContext;
@@ -29,7 +26,6 @@ import org.apache.commons.logging.LogFactory;
import org.springframework.ldap.NamingException;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.transaction.compensating.CompensatingTransactionOperationManager;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;
@@ -39,9 +35,10 @@ import org.springframework.util.Assert;
* @author Mattias Arthursson
* @since 1.2
*/
public final class TransactionUtils {
public final class LdapTransactionUtils {
private static final Log logger = LogFactory.getLog(TransactionUtils.class);
private static final Log logger = LogFactory
.getLog(LdapTransactionUtils.class);
public static final String REBIND_METHOD_NAME = "rebind";
@@ -56,7 +53,7 @@ public final class TransactionUtils {
/**
* Not to be instantiated.
*/
private TransactionUtils() {
private LdapTransactionUtils() {
}
@@ -160,37 +157,6 @@ public final class TransactionUtils {
}
/**
* Perform the specified operation, storing the state prior to the
* operation, to enable commit/rollback later.
*
* @param contextSource
* the ContextSource we are operating on.
* @param targetContext TODO
* @param method
* name of the method to be invoked.
* @param args
* arguments with which the operation is invoked.
*/
public static void performOperation(ContextSource contextSource,
DirContext targetContext, Method method, Object[] args) throws Throwable {
DirContextHolder transactionContextHolder = (DirContextHolder) TransactionSynchronizationManager
.getResource(contextSource);
if (transactionContextHolder != null) {
CompensatingTransactionOperationManager transactionDataManager = transactionContextHolder
.getTransactionOperationManager();
transactionDataManager.performOperation(method.getName(), args);
} else {
// Perform the target operation
try {
method.invoke(targetContext, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
}
/**
* Get the actual class of the supplied DirContext instance; LdapContext or
* DirContext.

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import javax.naming.Name;
import javax.naming.directory.ModificationItem;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import java.util.HashSet;
import java.util.Set;
@@ -56,7 +56,7 @@ public class ModifyAttributesOperationRecorder implements
public CompensatingTransactionOperationExecutor recordOperation(
Object[] args) {
Assert.notNull(args);
Name dn = TransactionUtils.getFirstArgumentAsName(args);
Name dn = LdapTransactionUtils.getFirstArgumentAsName(args);
if (args.length != 2 || !(args[1] instanceof ModificationItem[])) {
throw new IllegalArgumentException(
"Unexpected arguments to ModifyAttributes operation");

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
import org.springframework.transaction.compensating.CompensatingTransactionOperationManager;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import javax.naming.Name;
import javax.naming.directory.Attributes;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import javax.naming.Name;
import javax.naming.directory.Attributes;
@@ -63,7 +63,7 @@ public class RebindOperationRecorder implements
throw new IllegalArgumentException(
"Invalid arguments for bind operation");
}
Name dn = TransactionUtils.getFirstArgumentAsName(args);
Name dn = LdapTransactionUtils.getFirstArgumentAsName(args);
Object object = args[1];
Attributes attributes = null;
if (args[2] != null && !(args[2] instanceof Attributes)) {

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import javax.naming.Name;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import javax.naming.Name;
@@ -63,8 +63,8 @@ public class RenameOperationRecorder implements
// This really shouldn't happen.
throw new IllegalArgumentException("Illegal argument length");
}
Name oldDn = TransactionUtils.getArgumentAsName(args[0]);
Name newDn = TransactionUtils.getArgumentAsName(args[1]);
Name oldDn = LdapTransactionUtils.getArgumentAsName(args[0]);
Name newDn = LdapTransactionUtils.getArgumentAsName(args[1]);
return new RenameOperationExecutor(ldapOperations, oldDn, newDn);
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import javax.naming.Name;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import javax.naming.Name;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import javax.naming.Name;
@@ -59,7 +59,7 @@ public class UnbindOperationRecorder implements
*/
public CompensatingTransactionOperationExecutor recordOperation(
Object[] args) {
Name dn = TransactionUtils.getFirstArgumentAsName(args);
Name dn = LdapTransactionUtils.getFirstArgumentAsName(args);
Name temporaryDn = renamingStrategy.getTemporaryName(dn);
return new UnbindOperationExecutor(ldapOperations, dn, temporaryDn);

View File

@@ -0,0 +1,7 @@
<html>
<body>
LDAP specific implementations of the Compensating Transaction interfaces.
</body>
</html>

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.support;
package org.springframework.ldap.transaction.compensating.support;
import java.util.List;
@@ -22,7 +22,7 @@ import javax.naming.Name;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapRdn;
import org.springframework.ldap.core.LdapRdnComponent;
import org.springframework.ldap.transaction.TempEntryRenamingStrategy;
import org.springframework.ldap.transaction.compensating.TempEntryRenamingStrategy;
/**
* Default implementation of {@link TempEntryRenamingStrategy}. This

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.support;
package org.springframework.ldap.transaction.compensating.support;
import java.util.List;
@@ -22,7 +22,7 @@ import javax.naming.Name;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapRdn;
import org.springframework.ldap.core.LdapRdnComponent;
import org.springframework.ldap.transaction.TempEntryRenamingStrategy;
import org.springframework.ldap.transaction.compensating.TempEntryRenamingStrategy;
/**
* A {@link TempEntryRenamingStrategy} that moves the entry to a different

View File

@@ -0,0 +1,7 @@
<html>
<body>
Useful helper implementations for client side Compensating LDAP Transactions.
</body>
</html>

View File

@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.support;
package org.springframework.ldap.transaction.core;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.transaction.TempEntryRenamingStrategy;
import org.springframework.ldap.transaction.compensating.TempEntryRenamingStrategy;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionSuspensionNotSupportedException;

View File

@@ -13,16 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.support;
package org.springframework.ldap.transaction.core;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.transaction.TempEntryRenamingStrategy;
import org.springframework.ldap.transaction.UnbindOperationExecutor;
import org.springframework.ldap.transaction.compensating.TempEntryRenamingStrategy;
import org.springframework.ldap.transaction.compensating.UnbindOperationExecutor;
import org.springframework.ldap.transaction.compensating.support.DefaultTempEntryRenamingStrategy;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
import org.springframework.transaction.compensating.CompensatingTransactionOperationRecorder;
import org.springframework.transaction.compensating.DefaultCompensatingTransactionOperationManager;
import org.springframework.transaction.compensating.support.DefaultCompensatingTransactionOperationManager;
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
import org.springframework.transaction.support.DefaultTransactionStatus;

View File

@@ -0,0 +1,109 @@
/*
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.core;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.transaction.compensating.DirContextHolder;
import org.springframework.ldap.transaction.compensating.TempEntryRenamingStrategy;
import org.springframework.ldap.transaction.compensating.support.DefaultTempEntryRenamingStrategy;
import org.springframework.transaction.compensating.support.AbstractCompensatingTransactionManagerDelegate;
import org.springframework.transaction.compensating.support.CompensatingTransactionHolderSupport;
/**
* This delegate performs all the work for the
* {@link ContextSourceTransactionManager}. The work is delegated in order to
* be able to perform the exact same work for the LDAP part in
* {@link ContextSourceAndDataSourceTransactionManager}.
*
* @author Mattias Arthursson
* @see ContextSourceTransactionManager
* @see ContextSourceAndDataSourceTransactionManager
*/
public class ContextSourceTransactionManagerDelegate extends
AbstractCompensatingTransactionManagerDelegate {
private static final Log log = LogFactory
.getLog(ContextSourceTransactionManagerDelegate.class);
private ContextSource contextSource;
private TempEntryRenamingStrategy renamingStrategy = new DefaultTempEntryRenamingStrategy();
/**
* Set the ContextSource to work on. Even though the actual ContextSource
* sent to the LdapTemplate instance should be a
* {@link TransactionAwareContextSourceProxy}, the one sent to this method
* should be the target of that proxy. If it is not, the target will be
* extracted and used instead.
*
* @param contextSource
* the ContextSource to work on.
*/
public void setContextSource(ContextSource contextSource) {
if (contextSource instanceof TransactionAwareContextSourceProxy) {
TransactionAwareContextSourceProxy proxy = (TransactionAwareContextSourceProxy) contextSource;
this.contextSource = proxy.getTarget();
} else {
this.contextSource = contextSource;
}
}
public ContextSource getContextSource() {
return contextSource;
}
protected Object getTransactionSynchronizationKey() {
return getContextSource();
}
protected CompensatingTransactionHolderSupport getNewHolder() {
DirContext newCtx = getContextSource().getReadOnlyContext();
DirContextHolder contextHolder = new DirContextHolder(newCtx,
renamingStrategy);
return contextHolder;
}
protected void closeTargetResource(
CompensatingTransactionHolderSupport transactionHolderSupport) {
DirContextHolder contextHolder = (DirContextHolder) transactionHolderSupport;
DirContext ctx = contextHolder.getCtx();
try {
log.debug("Closing target context");
ctx.close();
} catch (NamingException e) {
log.warn("Failed to close target context", e);
}
}
/**
* Set the {@link TempEntryRenamingStrategy} to be used when renaming
* temporary entries in unbind and rebind operations. Default value is a
* {@link DefaultTempEntryRenamingStrategy}.
*
* @param renamingStrategy
* the {@link TempEntryRenamingStrategy} to use.
*/
public void setRenamingStrategy(TempEntryRenamingStrategy renamingStrategy) {
this.renamingStrategy = renamingStrategy;
}
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.support;
package org.springframework.ldap.transaction.core;
import java.lang.reflect.Proxy;
@@ -21,9 +21,9 @@ import javax.naming.directory.DirContext;
import org.springframework.ldap.NamingException;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.transaction.DirContextHolder;
import org.springframework.ldap.transaction.DirContextProxy;
import org.springframework.ldap.transaction.TransactionUtils;
import org.springframework.ldap.core.DirContextProxy;
import org.springframework.ldap.transaction.compensating.DirContextHolder;
import org.springframework.ldap.transaction.compensating.LdapTransactionUtils;
import org.springframework.transaction.support.TransactionSynchronizationManager;
/**
@@ -71,7 +71,7 @@ public class TransactionAwareContextSourceProxy implements ContextSource {
ContextSource target) {
return (DirContext) Proxy
.newProxyInstance(DirContextProxy.class.getClassLoader(),
new Class[] { TransactionUtils.getActualTargetClass(context),
new Class[] { LdapTransactionUtils.getActualTargetClass(context),
DirContextProxy.class },
new TransactionAwareDirContextInvocationHandler(
context, target));

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.support;
package org.springframework.ldap.transaction.core;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
@@ -22,8 +22,9 @@ import java.lang.reflect.Method;
import javax.naming.directory.DirContext;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.transaction.DirContextHolder;
import org.springframework.ldap.transaction.TransactionUtils;
import org.springframework.ldap.transaction.compensating.DirContextHolder;
import org.springframework.ldap.transaction.compensating.LdapTransactionUtils;
import org.springframework.transaction.compensating.support.CompensatingTransactionUtils;
/**
* Proxy implementation for DirContext, making sure that the instance is not
@@ -73,11 +74,13 @@ public class TransactionAwareDirContextInvocationHandler implements
// Use hashCode of Connection proxy.
return new Integer(proxy.hashCode());
} else if (methodName.equals("close")) {
TransactionUtils.doCloseConnection(target, contextSource);
LdapTransactionUtils.doCloseConnection(target, contextSource);
return null;
} else if (TransactionUtils.isSupportedWriteTransactionOperation(methodName)) {
} else if (LdapTransactionUtils
.isSupportedWriteTransactionOperation(methodName)) {
// Store transaction data and allow operation to proceed.
TransactionUtils.performOperation(contextSource, target, method, args);
CompensatingTransactionUtils.performOperation(contextSource,
target, method, args);
return null;
} else {
try {

View File

@@ -0,0 +1,7 @@
<html>
<body>
The core implementation classes for client-side LDAP transactions.
</body>
</html>

View File

@@ -1,165 +0,0 @@
/*
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.support;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.transaction.DirContextHolder;
import org.springframework.ldap.transaction.TempEntryRenamingStrategy;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.support.DefaultTransactionStatus;
import org.springframework.transaction.support.TransactionSynchronizationManager;
/**
* This delegate performs all the work for the
* {@link ContextSourceTransactionManager}. The work is delegated in order to
* be able to perform the exact same work for the LDAP part in
* {@link ContextSourceAndDataSourceTransactionManager}.
*
* @author Mattias Arthursson
* @see ContextSourceTransactionManager
* @see ContextSourceAndDataSourceTransactionManager
*/
public class ContextSourceTransactionManagerDelegate {
private static Log log = LogFactory
.getLog(ContextSourceTransactionManager.class);
private ContextSource contextSource;
private TempEntryRenamingStrategy renamingStrategy = new DefaultTempEntryRenamingStrategy();
/**
* Set the ContextSource to work on. Even though the actual ContextSource
* sent to the LdapTemplate instance should be a
* {@link TransactionAwareContextSourceProxy}, the one sent to this method
* should be the target of that proxy. If it is not, the target will be
* extracted and used instead.
*
* @param contextSource
* the ContextSource to work on.
*/
public void setContextSource(ContextSource contextSource) {
if (contextSource instanceof TransactionAwareContextSourceProxy) {
TransactionAwareContextSourceProxy proxy = (TransactionAwareContextSourceProxy) contextSource;
this.contextSource = proxy.getTarget();
} else {
this.contextSource = contextSource;
}
}
public ContextSource getContextSource() {
return contextSource;
}
/*
* (non-Javadoc)
*
* @see org.springframework.transaction.support.AbstractPlatformTransactionManager#doGetTransaction()
*/
public Object doGetTransaction() throws TransactionException {
DirContextHolder contextHolder = (DirContextHolder) TransactionSynchronizationManager
.getResource(this.contextSource);
ContextSourceTransactionObject txObject = new ContextSourceTransactionObject(
contextHolder);
return txObject;
}
/*
* (non-Javadoc)
*
* @see org.springframework.transaction.support.AbstractPlatformTransactionManager#doBegin(java.lang.Object,
* org.springframework.transaction.TransactionDefinition)
*/
public void doBegin(Object transaction, TransactionDefinition definition)
throws TransactionException {
ContextSourceTransactionObject txObject = (ContextSourceTransactionObject) transaction;
if (txObject.getContextHolder() == null) {
DirContext newCtx = getContextSource().getReadOnlyContext();
DirContextHolder contextHolder = new DirContextHolder(newCtx,
renamingStrategy);
txObject.setContextHolder(contextHolder);
TransactionSynchronizationManager.bindResource(getContextSource(),
contextHolder);
}
}
/*
* (non-Javadoc)
*
* @see org.springframework.transaction.support.AbstractPlatformTransactionManager#doCommit(org.springframework.transaction.support.DefaultTransactionStatus)
*/
public void doCommit(DefaultTransactionStatus status)
throws TransactionException {
ContextSourceTransactionObject txObject = (ContextSourceTransactionObject) status
.getTransaction();
txObject.getContextHolder().getTransactionOperationManager().commit();
}
/*
* (non-Javadoc)
*
* @see org.springframework.transaction.support.AbstractPlatformTransactionManager#doRollback(org.springframework.transaction.support.DefaultTransactionStatus)
*/
public void doRollback(DefaultTransactionStatus status)
throws TransactionException {
ContextSourceTransactionObject txObject = (ContextSourceTransactionObject) status
.getTransaction();
txObject.getContextHolder().getTransactionOperationManager().rollback();
}
/*
* (non-Javadoc)
*
* @see org.springframework.transaction.support.AbstractPlatformTransactionManager#doCleanupAfterCompletion(java.lang.Object)
*/
public void doCleanupAfterCompletion(Object transaction) {
log.debug("Cleaning stored ContextHolder");
TransactionSynchronizationManager.unbindResource(contextSource);
ContextSourceTransactionObject txObject = (ContextSourceTransactionObject) transaction;
DirContext ctx = txObject.getContextHolder().getCtx();
try {
log.debug("Closing target context");
ctx.close();
} catch (NamingException e) {
e.printStackTrace();
}
txObject.getContextHolder().clear();
}
/**
* Set the {@link TempEntryRenamingStrategy} to be used when renaming
* temporary entries in unbind and rebind operations. Default value is a
* {@link DefaultTempEntryRenamingStrategy}.
*
* @param renamingStrategy
* the {@link TempEntryRenamingStrategy} to use.
*/
public void setRenamingStrategy(TempEntryRenamingStrategy renamingStrategy) {
this.renamingStrategy = renamingStrategy;
}
}

View File

@@ -1,57 +0,0 @@
/*
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.support;
import org.springframework.ldap.transaction.DirContextHolder;
/**
* Transaction object for ContextSourceTransactionManager. Keeps a reference to
* the {@link DirContextHolder} associated with the current transaction.
*
* @author Mattias Arthursson
*/
public class ContextSourceTransactionObject {
private DirContextHolder contextHolder;
/**
* Constructor.
*
* @param contextHolder
* the DirContextHolder associated with the current transaction.
*/
public ContextSourceTransactionObject(DirContextHolder contextHolder) {
this.contextHolder = contextHolder;
}
/**
* Get the DirContextHolder.
*
* @return the DirContextHolder.
*/
public DirContextHolder getContextHolder() {
return contextHolder;
}
/**
* Set the DirContextHolder associated with the current transaction.s
*
* @param contextHolder
* the DirContextHolder associated with the current transaction.
*/
public void setContextHolder(DirContextHolder contextHolder) {
this.contextHolder = contextHolder;
}
}

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.transaction.compensating;
import org.springframework.transaction.compensating.support.DefaultCompensatingTransactionOperationManager;
/**
* Factory interface for creating
* {@link CompensatingTransactionOperationRecorder} objects based on operation

View File

@@ -0,0 +1,8 @@
<html>
<body>
Interface definitions for a general Compensating Transaction framework
based on PlatformTransactionManager.
</body>
</html>

View File

@@ -0,0 +1,142 @@
/*
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.transaction.compensating.support;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.ldap.transaction.core.ContextSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.support.DefaultTransactionStatus;
import org.springframework.transaction.support.TransactionSynchronizationManager;
/**
* Abstract superclass for Compensating TransactionManager delegates. The actual
* transaction work is extracted to a delegate to enable composite Transaction
* Managers.
*
* @author Mattias Arthursson
*
*/
public abstract class AbstractCompensatingTransactionManagerDelegate {
private static Log log = LogFactory
.getLog(ContextSourceTransactionManager.class);
/**
* Close the target resource - the implementation specific resource held in
* the specified {@link CompensatingTransactionHolderSupport}.
*
* @param transactionHolderSupport
* the {@link CompensatingTransactionHolderSupport} that holds
* the transaction specific target resource.
*/
protected abstract void closeTargetResource(
CompensatingTransactionHolderSupport transactionHolderSupport);
/**
* Get a new implementation specific
* {@link CompensatingTransactionHolderSupport} instance.
*
* @return a new {@link CompensatingTransactionHolderSupport} instance.
*/
protected abstract CompensatingTransactionHolderSupport getNewHolder();
/**
* Get the key (normally, a DataSource or similar) that should be used for
* transaction synchronization.
*
* @return the transaction synchronization key
*/
protected abstract Object getTransactionSynchronizationKey();
/*
* (non-Javadoc)
*
* @see org.springframework.jdbc.datasource.DataSourceTransactionManager#doGetTransaction()
*/
public Object doGetTransaction() throws TransactionException {
CompensatingTransactionHolderSupport holder = (CompensatingTransactionHolderSupport) TransactionSynchronizationManager
.getResource(getTransactionSynchronizationKey());
CompensatingTransactionObject txObject = new CompensatingTransactionObject(
holder);
return txObject;
}
/*
* (non-Javadoc)
*
* @see org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin(java.lang.Object,
* org.springframework.transaction.TransactionDefinition)
*/
public void doBegin(Object transaction, TransactionDefinition definition)
throws TransactionException {
CompensatingTransactionObject txObject = (CompensatingTransactionObject) transaction;
if (txObject.getHolder() == null) {
CompensatingTransactionHolderSupport contextHolder = getNewHolder();
txObject.setHolder(contextHolder);
TransactionSynchronizationManager.bindResource(
getTransactionSynchronizationKey(), contextHolder);
}
}
/*
* (non-Javadoc)
*
* @see org.springframework.jdbc.datasource.DataSourceTransactionManager#doCommit(org.springframework.transaction.support.DefaultTransactionStatus)
*/
public void doCommit(DefaultTransactionStatus status)
throws TransactionException {
CompensatingTransactionObject txObject = (CompensatingTransactionObject) status
.getTransaction();
txObject.getHolder().getTransactionOperationManager().commit();
}
/*
* (non-Javadoc)
*
* @see org.springframework.jdbc.datasource.DataSourceTransactionManager#doRollback(org.springframework.transaction.support.DefaultTransactionStatus)
*/
public void doRollback(DefaultTransactionStatus status)
throws TransactionException {
CompensatingTransactionObject txObject = (CompensatingTransactionObject) status
.getTransaction();
txObject.getHolder().getTransactionOperationManager().rollback();
}
/*
* (non-Javadoc)
*
* @see org.springframework.jdbc.datasource.DataSourceTransactionManager#doCleanupAfterCompletion(java.lang.Object)
*/
public void doCleanupAfterCompletion(Object transaction) {
log.debug("Cleaning stored transaction synchronization");
TransactionSynchronizationManager
.unbindResource(getTransactionSynchronizationKey());
CompensatingTransactionObject txObject = (CompensatingTransactionObject) transaction;
CompensatingTransactionHolderSupport transactionHolderSupport = (CompensatingTransactionHolderSupport) txObject
.getHolder();
closeTargetResource(transactionHolderSupport);
txObject.getHolder().clear();
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.transaction.compensating.support;
import org.springframework.ldap.transaction.compensating.LdapCompensatingTransactionOperationFactory;
import org.springframework.transaction.compensating.CompensatingTransactionOperationFactory;
import org.springframework.transaction.compensating.CompensatingTransactionOperationManager;
import org.springframework.transaction.support.ResourceHolderSupport;
/**
* Base class for compensating transaction resource holders.
*
* @author Mattias Arthursson
*/
public abstract class CompensatingTransactionHolderSupport extends
ResourceHolderSupport {
private CompensatingTransactionOperationManager transactionOperationManager;
/**
* This method creates a new TransactionOperationManager instance. To be
* called by subclass in case the target object has changed.
*/
protected void refreshTransactionOperationManager() {
setTransactionOperationManager(new DefaultCompensatingTransactionOperationManager(
createOperationFactory()));
}
/**
* Factory method to create a
* {@link CompensatingTransactionOperationFactory} using the settings and
* current state of this object.
*
* @return a new {@link LdapCompensatingTransactionOperationFactory}
* referncing the current transaction context.
*/
protected abstract CompensatingTransactionOperationFactory createOperationFactory();
public void clear() {
super.clear();
transactionOperationManager = null;
}
/**
* Get the CompensatingTransactionOperationManager to handle the data for
* the current transaction.
*
* @return the CompensatingTransactionOperationManager.
*/
public CompensatingTransactionOperationManager getTransactionOperationManager() {
return transactionOperationManager;
}
/**
* Set the CompensatingTransactionOperationManager. For testing purposes
* only.
*
* @param transactionOperationManager
* the CompensatingTransactionOperationManager to use.
*/
public void setTransactionOperationManager(
CompensatingTransactionOperationManager transactionOperationManager) {
this.transactionOperationManager = transactionOperationManager;
}
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.transaction.compensating.support;
import org.springframework.ldap.transaction.compensating.DirContextHolder;
/**
* Transaction object for ContextSourceTransactionManager. Keeps a reference to
* the {@link DirContextHolder} associated with the current transaction.
*
* @author Mattias Arthursson
*/
public class CompensatingTransactionObject {
private CompensatingTransactionHolderSupport holder;
/**
* Constructor.
*
* @param holder
* the {@link CompensatingTransactionHolderSupport} associated
* with the current transaction.
*/
public CompensatingTransactionObject(
CompensatingTransactionHolderSupport holder) {
this.holder = holder;
}
/**
* Get the DirContextHolder.
*
* @return the DirContextHolder.
*/
public CompensatingTransactionHolderSupport getHolder() {
return holder;
}
/**
* Set the {@link CompensatingTransactionHolderSupport} associated with the
* current transaction.
*
* @param holder
* the {@link CompensatingTransactionHolderSupport} associated
* with the current transaction.
*/
public void setHolder(CompensatingTransactionHolderSupport holder) {
this.holder = holder;
}
}

View File

@@ -0,0 +1,57 @@
package org.springframework.transaction.compensating.support;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.springframework.transaction.compensating.CompensatingTransactionOperationManager;
import org.springframework.transaction.support.TransactionSynchronizationManager;
/**
* Common methods for use with compensating transactions.
*
* @author Mattias Arthursson
*/
public class CompensatingTransactionUtils {
/**
* Not to be instantiated.
*/
private CompensatingTransactionUtils() {
}
/**
* Perform the specified operation, storing the state prior to the
* operation, to enable commit/rollback later. If no transaction is
* currently active, proceed with the original call on the target.
*
* @param synchronizationKey
* the transaction synchronization key we are operating on
* (typically something similar to a DataSource).
* @param target
* the actual target resource that should be used for invoking
* the operation on should no transaction be active.
* @param method
* name of the method to be invoked.
* @param args
* arguments with which the operation is invoked.
*/
public static void performOperation(Object synchronizationKey,
Object target, Method method, Object[] args) throws Throwable {
CompensatingTransactionHolderSupport transactionContextHolder = (CompensatingTransactionHolderSupport) TransactionSynchronizationManager
.getResource(synchronizationKey);
if (transactionContextHolder != null) {
CompensatingTransactionOperationManager transactionDataManager = transactionContextHolder
.getTransactionOperationManager();
transactionDataManager.performOperation(method.getName(), args);
} else {
// Perform the target operation
try {
method.invoke(target, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
}
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.transaction.compensating;
package org.springframework.transaction.compensating.support;
import java.util.Iterator;
import java.util.Stack;
@@ -21,6 +21,10 @@ import java.util.Stack;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.transaction.TransactionSystemException;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
import org.springframework.transaction.compensating.CompensatingTransactionOperationFactory;
import org.springframework.transaction.compensating.CompensatingTransactionOperationManager;
import org.springframework.transaction.compensating.CompensatingTransactionOperationRecorder;
/**
* Default implementation of {@link CompensatingTransactionOperationManager}.

View File

@@ -0,0 +1,9 @@
<html>
<body>
Support package for general Compensating Transaction Framework.
Contains default implementations of core interfaces as well as useful
helper classes.
</body>
</html>

View File

@@ -1,171 +0,0 @@
package org.springframework.ldap.support;
import java.lang.reflect.Method;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.transaction.DirContextHolder;
import org.springframework.ldap.transaction.TransactionUtils;
import org.springframework.transaction.compensating.CompensatingTransactionOperationManager;
import org.springframework.transaction.support.TransactionSynchronizationManager;
public class TransactionUtilsTest extends TestCase {
private MockControl dirContextControl;
private DirContext dirContextMock;
private MockControl contextSourceControl;
private ContextSource contextSourceMock;
private MockControl operationManagerControl;
private CompensatingTransactionOperationManager operationManagerMock;
protected void setUp() throws Exception {
dirContextControl = MockControl.createControl(DirContext.class);
dirContextMock = (DirContext) dirContextControl.getMock();
contextSourceControl = MockControl.createControl(ContextSource.class);
contextSourceMock = (ContextSource) contextSourceControl.getMock();
operationManagerControl = MockControl
.createControl(CompensatingTransactionOperationManager.class);
operationManagerMock = (CompensatingTransactionOperationManager) operationManagerControl
.getMock();
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.clearSynchronization();
}
}
protected void tearDown() throws Exception {
dirContextControl = null;
dirContextMock = null;
contextSourceControl = null;
contextSourceMock = null;
operationManagerControl = null;
operationManagerMock = null;
}
protected void replay() {
dirContextControl.replay();
contextSourceControl.replay();
operationManagerControl.replay();
}
protected void verify() {
dirContextControl.verify();
contextSourceControl.verify();
operationManagerControl.verify();
}
public void testCloseContext() throws NamingException {
dirContextMock.close();
replay();
LdapUtils.closeContext(dirContextMock);
verify();
}
public void testCloseContext_NullContext() throws NamingException {
replay();
LdapUtils.closeContext(null);
verify();
}
public void testDoCloseConnection_NoTransaction() throws NamingException {
dirContextMock.close();
replay();
TransactionUtils.doCloseConnection(dirContextMock, contextSourceMock);
verify();
}
public void testDoCloseConnection_ActiveTransaction()
throws NamingException {
DirContextHolder holder = new DirContextHolder(dirContextMock, null);
TransactionSynchronizationManager.bindResource(contextSourceMock,
holder);
// Context should not be closed.
replay();
TransactionUtils.doCloseConnection(dirContextMock, contextSourceMock);
verify();
}
public void testDoCloseConnection_NotTransactionalContext()
throws NamingException {
DirContextHolder holder = new DirContextHolder(dirContextMock, null);
TransactionSynchronizationManager.bindResource(contextSourceMock,
holder);
MockControl dirContextControl2 = MockControl
.createControl(DirContext.class);
DirContext dirContextMock2 = (DirContext) dirContextControl2.getMock();
dirContextMock2.close();
dirContextControl2.replay();
replay();
TransactionUtils.doCloseConnection(dirContextMock2, contextSourceMock);
verify();
dirContextControl2.verify();
}
public void testIsSupportedWriteTransactionOperation() {
assertTrue(TransactionUtils.isSupportedWriteTransactionOperation("bind"));
assertTrue(TransactionUtils.isSupportedWriteTransactionOperation("rebind"));
assertTrue(TransactionUtils.isSupportedWriteTransactionOperation("unbind"));
assertTrue(TransactionUtils
.isSupportedWriteTransactionOperation("modifyAttributes"));
assertTrue(TransactionUtils.isSupportedWriteTransactionOperation("rename"));
assertFalse(TransactionUtils.isSupportedWriteTransactionOperation("lookup"));
assertFalse(TransactionUtils.isSupportedWriteTransactionOperation("search"));
}
public void testPerformOperation() throws Throwable {
DirContextHolder holder = new DirContextHolder(dirContextMock, null);
holder.setTransactionOperationManager(operationManagerMock);
TransactionSynchronizationManager.bindResource(contextSourceMock,
holder);
Object[] expectedArgs = new Object[] { "someDn" };
operationManagerMock.performOperation("unbind", expectedArgs);
replay();
TransactionUtils.performOperation(contextSourceMock, dirContextMock,
getUnbindMethod(), expectedArgs);
verify();
}
public void testPerformOperation_NoTransaction() throws Throwable {
Object[] expectedArgs = new Object[] { "someDn" };
dirContextMock.unbind("someDn");
replay();
TransactionUtils.performOperation(contextSourceMock, dirContextMock,
getUnbindMethod(), expectedArgs);
verify();
}
private Method getUnbindMethod() throws NoSuchMethodException {
return DirContext.class.getMethod("unbind",
new Class[] { String.class });
}
public void dummyMethod() {
}
}

View File

@@ -1,4 +1,4 @@
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import javax.naming.directory.BasicAttributes;
@@ -7,7 +7,7 @@ import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.ldap.transaction.BindOperationExecutor;
import org.springframework.ldap.transaction.compensating.BindOperationExecutor;
public class BindOperationExecutorTest extends TestCase {
private MockControl ldapOperationsControl;

View File

@@ -1,4 +1,4 @@
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import javax.naming.directory.BasicAttributes;
@@ -7,8 +7,8 @@ import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.ldap.transaction.BindOperationExecutor;
import org.springframework.ldap.transaction.BindOperationRecorder;
import org.springframework.ldap.transaction.compensating.BindOperationExecutor;
import org.springframework.ldap.transaction.compensating.BindOperationRecorder;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
public class BindOperationRecorderTest extends TestCase {

View File

@@ -1,16 +1,16 @@
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.ldap.transaction.BindOperationRecorder;
import org.springframework.ldap.transaction.LdapCompensatingTransactionOperationFactory;
import org.springframework.ldap.transaction.ModifyAttributesOperationRecorder;
import org.springframework.ldap.transaction.RebindOperationRecorder;
import org.springframework.ldap.transaction.RenameOperationRecorder;
import org.springframework.ldap.transaction.TempEntryRenamingStrategy;
import org.springframework.ldap.transaction.UnbindOperationRecorder;
import org.springframework.ldap.transaction.compensating.BindOperationRecorder;
import org.springframework.ldap.transaction.compensating.LdapCompensatingTransactionOperationFactory;
import org.springframework.ldap.transaction.compensating.ModifyAttributesOperationRecorder;
import org.springframework.ldap.transaction.compensating.RebindOperationRecorder;
import org.springframework.ldap.transaction.compensating.RenameOperationRecorder;
import org.springframework.ldap.transaction.compensating.TempEntryRenamingStrategy;
import org.springframework.ldap.transaction.compensating.UnbindOperationRecorder;
import org.springframework.transaction.compensating.CompensatingTransactionOperationRecorder;
public class LdapCompensatingTransactionOperationFactoryTest extends TestCase {

View File

@@ -0,0 +1,136 @@
package org.springframework.ldap.transaction.compensating;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.support.LdapUtils;
import org.springframework.ldap.transaction.compensating.DirContextHolder;
import org.springframework.ldap.transaction.compensating.LdapTransactionUtils;
import org.springframework.transaction.compensating.support.CompensatingTransactionHolderSupport;
import org.springframework.transaction.support.TransactionSynchronizationManager;
public class LdapTransactionUtilsTest extends TestCase {
private MockControl dirContextControl;
private DirContext dirContextMock;
private MockControl contextSourceControl;
private ContextSource contextSourceMock;
protected void setUp() throws Exception {
dirContextControl = MockControl.createControl(DirContext.class);
dirContextMock = (DirContext) dirContextControl.getMock();
contextSourceControl = MockControl.createControl(ContextSource.class);
contextSourceMock = (ContextSource) contextSourceControl.getMock();
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.clearSynchronization();
}
}
protected void tearDown() throws Exception {
dirContextControl = null;
dirContextMock = null;
contextSourceControl = null;
contextSourceMock = null;
}
protected void replay() {
dirContextControl.replay();
contextSourceControl.replay();
}
protected void verify() {
dirContextControl.verify();
contextSourceControl.verify();
}
public void testCloseContext() throws NamingException {
dirContextMock.close();
replay();
LdapUtils.closeContext(dirContextMock);
verify();
}
public void testCloseContext_NullContext() throws NamingException {
replay();
LdapUtils.closeContext(null);
verify();
}
public void testDoCloseConnection_NoTransaction() throws NamingException {
dirContextMock.close();
replay();
LdapTransactionUtils.doCloseConnection(dirContextMock,
contextSourceMock);
verify();
}
public void testDoCloseConnection_ActiveTransaction()
throws NamingException {
CompensatingTransactionHolderSupport holder = new DirContextHolder(
dirContextMock, null);
TransactionSynchronizationManager.bindResource(contextSourceMock,
holder);
// Context should not be closed.
replay();
LdapTransactionUtils.doCloseConnection(dirContextMock,
contextSourceMock);
verify();
}
public void testDoCloseConnection_NotTransactionalContext()
throws NamingException {
CompensatingTransactionHolderSupport holder = new DirContextHolder(
dirContextMock, null);
TransactionSynchronizationManager.bindResource(contextSourceMock,
holder);
MockControl dirContextControl2 = MockControl
.createControl(DirContext.class);
DirContext dirContextMock2 = (DirContext) dirContextControl2.getMock();
dirContextMock2.close();
dirContextControl2.replay();
replay();
LdapTransactionUtils.doCloseConnection(dirContextMock2,
contextSourceMock);
verify();
dirContextControl2.verify();
}
public void testIsSupportedWriteTransactionOperation() {
assertTrue(LdapTransactionUtils
.isSupportedWriteTransactionOperation("bind"));
assertTrue(LdapTransactionUtils
.isSupportedWriteTransactionOperation("rebind"));
assertTrue(LdapTransactionUtils
.isSupportedWriteTransactionOperation("unbind"));
assertTrue(LdapTransactionUtils
.isSupportedWriteTransactionOperation("modifyAttributes"));
assertTrue(LdapTransactionUtils
.isSupportedWriteTransactionOperation("rename"));
assertFalse(LdapTransactionUtils
.isSupportedWriteTransactionOperation("lookup"));
assertFalse(LdapTransactionUtils
.isSupportedWriteTransactionOperation("search"));
}
public void dummyMethod() {
}
}

View File

@@ -1,4 +1,4 @@
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import javax.naming.Name;
import javax.naming.directory.ModificationItem;
@@ -6,7 +6,7 @@ import javax.naming.directory.ModificationItem;
import org.easymock.MockControl;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.ldap.transaction.ModifyAttributesOperationExecutor;
import org.springframework.ldap.transaction.compensating.ModifyAttributesOperationExecutor;
import junit.framework.TestCase;

View File

@@ -1,4 +1,4 @@
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
@@ -14,8 +14,8 @@ import org.easymock.MockControl;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.ldap.transaction.ModifyAttributesOperationExecutor;
import org.springframework.ldap.transaction.ModifyAttributesOperationRecorder;
import org.springframework.ldap.transaction.compensating.ModifyAttributesOperationExecutor;
import org.springframework.ldap.transaction.compensating.ModifyAttributesOperationRecorder;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
public class ModifyAttributesOperationRecorderTest extends TestCase {

View File

@@ -1,4 +1,4 @@
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import javax.naming.directory.BasicAttributes;
@@ -7,7 +7,7 @@ import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.ldap.transaction.RebindOperationExecutor;
import org.springframework.ldap.transaction.compensating.RebindOperationExecutor;
public class RebindOperationExecutorTest extends TestCase {

View File

@@ -1,4 +1,4 @@
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import javax.naming.directory.BasicAttributes;
@@ -7,9 +7,9 @@ import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.ldap.transaction.RebindOperationExecutor;
import org.springframework.ldap.transaction.RebindOperationRecorder;
import org.springframework.ldap.transaction.TempEntryRenamingStrategy;
import org.springframework.ldap.transaction.compensating.RebindOperationExecutor;
import org.springframework.ldap.transaction.compensating.RebindOperationRecorder;
import org.springframework.ldap.transaction.compensating.TempEntryRenamingStrategy;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
public class RebindOperationRecorderTest extends TestCase {

View File

@@ -1,9 +1,9 @@
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import org.easymock.MockControl;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.ldap.transaction.RenameOperationExecutor;
import org.springframework.ldap.transaction.compensating.RenameOperationExecutor;
import junit.framework.TestCase;

View File

@@ -1,11 +1,11 @@
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.ldap.transaction.RenameOperationExecutor;
import org.springframework.ldap.transaction.RenameOperationRecorder;
import org.springframework.ldap.transaction.compensating.RenameOperationExecutor;
import org.springframework.ldap.transaction.compensating.RenameOperationRecorder;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
public class RenameOperationRecorderTest extends TestCase {

View File

@@ -1,11 +1,11 @@
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.ldap.transaction.UnbindOperationExecutor;
import org.springframework.ldap.transaction.compensating.UnbindOperationExecutor;
public class UnbindOperationExecutorTest extends TestCase {
private MockControl ldapOperationsControl;

View File

@@ -1,13 +1,13 @@
package org.springframework.ldap.transaction;
package org.springframework.ldap.transaction.compensating;
import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.ldap.transaction.TempEntryRenamingStrategy;
import org.springframework.ldap.transaction.UnbindOperationExecutor;
import org.springframework.ldap.transaction.UnbindOperationRecorder;
import org.springframework.ldap.transaction.compensating.TempEntryRenamingStrategy;
import org.springframework.ldap.transaction.compensating.UnbindOperationExecutor;
import org.springframework.ldap.transaction.compensating.UnbindOperationRecorder;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
public class UnbindOperationRecorderTest extends TestCase {

View File

@@ -1,9 +1,9 @@
package org.springframework.ldap.transaction.support;
package org.springframework.ldap.transaction.compensating.support;
import javax.naming.Name;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.transaction.support.DefaultTempEntryRenamingStrategy;
import org.springframework.ldap.transaction.compensating.support.DefaultTempEntryRenamingStrategy;
import junit.framework.TestCase;

View File

@@ -1,9 +1,9 @@
package org.springframework.ldap.transaction.support;
package org.springframework.ldap.transaction.compensating.support;
import javax.naming.Name;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.transaction.support.DifferentSubtreeTempEntryRenamingStrategy;
import org.springframework.ldap.transaction.compensating.support.DifferentSubtreeTempEntryRenamingStrategy;
import junit.framework.TestCase;

View File

@@ -1,4 +1,4 @@
package org.springframework.ldap.transaction.support;
package org.springframework.ldap.transaction.core;
import javax.naming.directory.DirContext;
@@ -6,13 +6,14 @@ import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.transaction.DirContextHolder;
import org.springframework.ldap.transaction.TempEntryRenamingStrategy;
import org.springframework.ldap.transaction.support.ContextSourceTransactionManager;
import org.springframework.ldap.transaction.support.ContextSourceTransactionObject;
import org.springframework.ldap.transaction.support.TransactionAwareContextSourceProxy;
import org.springframework.ldap.transaction.compensating.DirContextHolder;
import org.springframework.ldap.transaction.compensating.TempEntryRenamingStrategy;
import org.springframework.ldap.transaction.core.ContextSourceTransactionManager;
import org.springframework.ldap.transaction.core.TransactionAwareContextSourceProxy;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.compensating.CompensatingTransactionOperationManager;
import org.springframework.transaction.compensating.support.CompensatingTransactionHolderSupport;
import org.springframework.transaction.compensating.support.CompensatingTransactionObject;
import org.springframework.transaction.support.DefaultTransactionStatus;
import org.springframework.transaction.support.TransactionSynchronizationManager;
@@ -99,19 +100,19 @@ public class ContextSourceTransactionManagerTest extends TestCase {
Object result = tested.doGetTransaction();
assertNotNull(result);
assertTrue(result instanceof ContextSourceTransactionObject);
ContextSourceTransactionObject transactionObject = (ContextSourceTransactionObject) result;
assertNull(transactionObject.getContextHolder());
assertTrue(result instanceof CompensatingTransactionObject);
CompensatingTransactionObject transactionObject = (CompensatingTransactionObject) result;
assertNull(transactionObject.getHolder());
}
public void testDoGetTransactionTransactionActive() {
DirContextHolder expectedContextHolder = new DirContextHolder(null,
CompensatingTransactionHolderSupport expectedContextHolder = new DirContextHolder(null,
null);
TransactionSynchronizationManager.bindResource(contextSourceMock,
expectedContextHolder);
Object result = tested.doGetTransaction();
assertSame(expectedContextHolder,
((ContextSourceTransactionObject) result).getContextHolder());
((CompensatingTransactionObject) result).getHolder());
}
public void testDoBegin() {
@@ -120,7 +121,7 @@ public class ContextSourceTransactionManagerTest extends TestCase {
contextSourceControl.replay();
ContextSourceTransactionObject expectedTransactionObject = new ContextSourceTransactionObject(
CompensatingTransactionObject expectedTransactionObject = new CompensatingTransactionObject(
null);
tested.doBegin(expectedTransactionObject, transactionDefinitionMock);
@@ -147,9 +148,9 @@ public class ContextSourceTransactionManagerTest extends TestCase {
transactionDataManagerMock.rollback();
transactionDataManagerControl.replay();
ContextSourceTransactionObject transactionObject = new ContextSourceTransactionObject(
CompensatingTransactionObject transactionObject = new CompensatingTransactionObject(
null);
transactionObject.setContextHolder(expectedContextHolder);
transactionObject.setHolder(expectedContextHolder);
tested.doRollback(new DefaultTransactionStatus(transactionObject,
false, false, false, false, null));
transactionDataManagerControl.verify();
@@ -164,7 +165,7 @@ public class ContextSourceTransactionManagerTest extends TestCase {
contextMock.close();
contextControl.replay();
tested.doCleanupAfterCompletion(new ContextSourceTransactionObject(
tested.doCleanupAfterCompletion(new CompensatingTransactionObject(
expectedContextHolder));
contextControl.verify();

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.support;
package org.springframework.ldap.transaction.core;
import javax.naming.directory.DirContext;
import javax.naming.ldap.LdapContext;
@@ -22,8 +22,8 @@ import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.transaction.DirContextProxy;
import org.springframework.ldap.transaction.support.TransactionAwareContextSourceProxy;
import org.springframework.ldap.core.DirContextProxy;
import org.springframework.ldap.transaction.core.TransactionAwareContextSourceProxy;
/**
* Tests for {@link TransactionAwareContextSourceProxy}.

View File

@@ -0,0 +1,107 @@
package org.springframework.transaction.compensating.support;
import java.lang.reflect.Method;
import javax.naming.directory.DirContext;
import junit.framework.TestCase;
import org.easymock.MockControl;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.transaction.compensating.DirContextHolder;
import org.springframework.transaction.compensating.CompensatingTransactionOperationManager;
import org.springframework.transaction.compensating.support.CompensatingTransactionHolderSupport;
import org.springframework.transaction.compensating.support.CompensatingTransactionUtils;
import org.springframework.transaction.support.TransactionSynchronizationManager;
public class CompensatingTransactionUtilsTest extends TestCase {
private MockControl dirContextControl;
private DirContext dirContextMock;
private MockControl contextSourceControl;
private ContextSource contextSourceMock;
private MockControl operationManagerControl;
private CompensatingTransactionOperationManager operationManagerMock;
protected void setUp() throws Exception {
dirContextControl = MockControl.createControl(DirContext.class);
dirContextMock = (DirContext) dirContextControl.getMock();
contextSourceControl = MockControl.createControl(ContextSource.class);
contextSourceMock = (ContextSource) contextSourceControl.getMock();
operationManagerControl = MockControl
.createControl(CompensatingTransactionOperationManager.class);
operationManagerMock = (CompensatingTransactionOperationManager) operationManagerControl
.getMock();
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.clearSynchronization();
}
}
protected void tearDown() throws Exception {
dirContextControl = null;
dirContextMock = null;
contextSourceControl = null;
contextSourceMock = null;
operationManagerControl = null;
operationManagerMock = null;
}
protected void replay() {
dirContextControl.replay();
contextSourceControl.replay();
operationManagerControl.replay();
}
protected void verify() {
dirContextControl.verify();
contextSourceControl.verify();
operationManagerControl.verify();
}
public void testPerformOperation() throws Throwable {
CompensatingTransactionHolderSupport holder = new DirContextHolder(dirContextMock, null);
holder.setTransactionOperationManager(operationManagerMock);
TransactionSynchronizationManager.bindResource(contextSourceMock,
holder);
Object[] expectedArgs = new Object[] { "someDn" };
operationManagerMock.performOperation("unbind", expectedArgs);
replay();
CompensatingTransactionUtils.performOperation(contextSourceMock, dirContextMock,
getUnbindMethod(), expectedArgs);
verify();
}
public void testPerformOperation_NoTransaction() throws Throwable {
Object[] expectedArgs = new Object[] { "someDn" };
dirContextMock.unbind("someDn");
replay();
CompensatingTransactionUtils.performOperation(contextSourceMock, dirContextMock,
getUnbindMethod(), expectedArgs);
verify();
}
private Method getUnbindMethod() throws NoSuchMethodException {
return DirContext.class.getMethod("unbind",
new Class[] { String.class });
}
public void dummyMethod() {
}
}

View File

@@ -1,4 +1,4 @@
package org.springframework.transaction.compensating;
package org.springframework.transaction.compensating.support;
import java.util.Stack;
@@ -9,7 +9,7 @@ import org.springframework.transaction.TransactionSystemException;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
import org.springframework.transaction.compensating.CompensatingTransactionOperationFactory;
import org.springframework.transaction.compensating.CompensatingTransactionOperationRecorder;
import org.springframework.transaction.compensating.DefaultCompensatingTransactionOperationManager;
import org.springframework.transaction.compensating.support.DefaultCompensatingTransactionOperationManager;
public class DefaultCompensatingTransactionOperationManagerTest extends
TestCase {