diff --git a/spring-ldap/src/main/java/org/springframework/ldap/support/LdapUtils.java b/spring-ldap/src/main/java/org/springframework/ldap/support/LdapUtils.java index 8e8bc539..b65ef37d 100644 --- a/spring-ldap/src/main/java/org/springframework/ldap/support/LdapUtils.java +++ b/spring-ldap/src/main/java/org/springframework/ldap/support/LdapUtils.java @@ -41,7 +41,7 @@ import org.springframework.util.Assert; * @author Ulrik Sandberg * @since 1.2 */ -public abstract class LdapUtils { +public final class LdapUtils { private static final Log logger = LogFactory.getLog(LdapUtils.class); @@ -55,6 +55,13 @@ public abstract class LdapUtils { public static final String MODIFY_ATTRIBUTES_METHOD_NAME = "modifyAttributes"; + /** + * Not to be instantiated. + */ + private LdapUtils() { + + } + /** * Close the given JNDI Context and ignore any thrown exception. This is * useful for typical finally blocks in JNDI code. @@ -313,24 +320,25 @@ public abstract class LdapUtils { * * @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, - Method method, Object[] args) throws Throwable { + DirContext targetContext, Method method, Object[] args) throws Throwable { DirContextHolder transactionContextHolder = (DirContextHolder) TransactionSynchronizationManager .getResource(contextSource); if (transactionContextHolder != null) { CompensatingTransactionOperationManager transactionDataManager = transactionContextHolder - .getTransactionDataManager(); + .getTransactionOperationManager(); transactionDataManager.performOperation(method.getName(), args); } else { // Perform the target operation try { - method.invoke(transactionContextHolder.getCtx(), args); + method.invoke(targetContext, args); } catch (InvocationTargetException e) { throw e.getTargetException(); } diff --git a/spring-ldap/src/main/java/org/springframework/ldap/transaction/core/ContextSourceTransactionManagerDelegate.java b/spring-ldap/src/main/java/org/springframework/ldap/transaction/core/ContextSourceTransactionManagerDelegate.java index c96f436c..e5be0b5a 100644 --- a/spring-ldap/src/main/java/org/springframework/ldap/transaction/core/ContextSourceTransactionManagerDelegate.java +++ b/spring-ldap/src/main/java/org/springframework/ldap/transaction/core/ContextSourceTransactionManagerDelegate.java @@ -110,7 +110,7 @@ public class ContextSourceTransactionManagerDelegate { throws TransactionException { ContextSourceTransactionObject txObject = (ContextSourceTransactionObject) status .getTransaction(); - txObject.getContextHolder().getTransactionDataManager().commit(); + txObject.getContextHolder().getTransactionOperationManager().commit(); } @@ -123,7 +123,7 @@ public class ContextSourceTransactionManagerDelegate { throws TransactionException { ContextSourceTransactionObject txObject = (ContextSourceTransactionObject) status .getTransaction(); - txObject.getContextHolder().getTransactionDataManager().rollback(); + txObject.getContextHolder().getTransactionOperationManager().rollback(); } /* diff --git a/spring-ldap/src/main/java/org/springframework/ldap/transaction/core/DirContextHolder.java b/spring-ldap/src/main/java/org/springframework/ldap/transaction/core/DirContextHolder.java index ccf88221..3365e8ac 100644 --- a/spring-ldap/src/main/java/org/springframework/ldap/transaction/core/DirContextHolder.java +++ b/spring-ldap/src/main/java/org/springframework/ldap/transaction/core/DirContextHolder.java @@ -35,7 +35,7 @@ import org.springframework.transaction.support.ResourceHolderSupport; public class DirContextHolder extends ResourceHolderSupport { private DirContext ctx; - private CompensatingTransactionOperationManager transactionDataManager; + private CompensatingTransactionOperationManager transactionOperationManager; private CompensatingTransactionOperationFactory operationFactory; @@ -51,7 +51,7 @@ public class DirContextHolder extends ResourceHolderSupport { TempEntryRenamingStrategy renamingStrategy) { this.ctx = ctx; this.renamingStrategy = renamingStrategy; - this.transactionDataManager = new DefaultCompensatingTransactionOperationManager( + this.transactionOperationManager = new DefaultCompensatingTransactionOperationManager( createOperationFactory()); } @@ -63,7 +63,7 @@ public class DirContextHolder extends ResourceHolderSupport { */ public void setCtx(DirContext ctx) { this.ctx = ctx; - this.transactionDataManager = new DefaultCompensatingTransactionOperationManager( + this.transactionOperationManager = new DefaultCompensatingTransactionOperationManager( createOperationFactory()); } @@ -89,7 +89,7 @@ public class DirContextHolder extends ResourceHolderSupport { public void clear() { super.clear(); - transactionDataManager = null; + transactionOperationManager = null; operationFactory = null; } @@ -99,20 +99,20 @@ public class DirContextHolder extends ResourceHolderSupport { * * @return the CompensatingTransactionOperationManager. */ - public CompensatingTransactionOperationManager getTransactionDataManager() { - return transactionDataManager; + public CompensatingTransactionOperationManager getTransactionOperationManager() { + return transactionOperationManager; } /** * Set the CompensatingTransactionOperationManager. For testing purposes * only. * - * @param transactionDataManager + * @param transactionOperationManager * the CompensatingTransactionOperationManager to use. */ - void setTransactionDataManager( - CompensatingTransactionOperationManager transactionDataManager) { - this.transactionDataManager = transactionDataManager; + public void setTransactionOperationManager( + CompensatingTransactionOperationManager transactionOperationManager) { + this.transactionOperationManager = transactionOperationManager; } public CompensatingTransactionOperationFactory getOperationFactory() { diff --git a/spring-ldap/src/main/java/org/springframework/ldap/transaction/core/TransactionAwareDirContextInvocationHandler.java b/spring-ldap/src/main/java/org/springframework/ldap/transaction/core/TransactionAwareDirContextInvocationHandler.java index de180f75..f233bb9c 100644 --- a/spring-ldap/src/main/java/org/springframework/ldap/transaction/core/TransactionAwareDirContextInvocationHandler.java +++ b/spring-ldap/src/main/java/org/springframework/ldap/transaction/core/TransactionAwareDirContextInvocationHandler.java @@ -76,7 +76,7 @@ public class TransactionAwareDirContextInvocationHandler implements return null; } else if (LdapUtils.isSupportedWriteTransactionOperation(methodName)) { // Store transaction data and allow operation to proceed. - LdapUtils.performOperation(contextSource, method, args); + LdapUtils.performOperation(contextSource, target, method, args); return null; } else { try { diff --git a/spring-ldap/src/test/java/org/springframework/ldap/support/LdapUtilsTest.java b/spring-ldap/src/test/java/org/springframework/ldap/support/LdapUtilsTest.java new file mode 100644 index 00000000..372077d0 --- /dev/null +++ b/spring-ldap/src/test/java/org/springframework/ldap/support/LdapUtilsTest.java @@ -0,0 +1,170 @@ +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.CompensatingTransactionOperationManager; +import org.springframework.ldap.transaction.core.DirContextHolder; +import org.springframework.transaction.support.TransactionSynchronizationManager; + +public class LdapUtilsTest 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(); + LdapUtils.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(); + LdapUtils.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(); + LdapUtils.doCloseConnection(dirContextMock2, contextSourceMock); + verify(); + dirContextControl2.verify(); + } + + public void testIsSupportedWriteTransactionOperation() { + assertTrue(LdapUtils.isSupportedWriteTransactionOperation("bind")); + assertTrue(LdapUtils.isSupportedWriteTransactionOperation("rebind")); + assertTrue(LdapUtils.isSupportedWriteTransactionOperation("unbind")); + assertTrue(LdapUtils + .isSupportedWriteTransactionOperation("modifyAttributes")); + assertTrue(LdapUtils.isSupportedWriteTransactionOperation("rename")); + assertFalse(LdapUtils.isSupportedWriteTransactionOperation("lookup")); + assertFalse(LdapUtils.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(); + LdapUtils.performOperation(contextSourceMock, dirContextMock, + getUnbindMethod(), expectedArgs); + verify(); + } + + public void testPerformOperation_NoTransaction() throws Throwable { + Object[] expectedArgs = new Object[] { "someDn" }; + dirContextMock.unbind("someDn"); + + replay(); + LdapUtils.performOperation(contextSourceMock, dirContextMock, + getUnbindMethod(), expectedArgs); + verify(); + } + + private Method getUnbindMethod() throws NoSuchMethodException { + return DirContext.class.getMethod("unbind", + new Class[] { String.class }); + } + + public void dummyMethod() { + + } + +} diff --git a/spring-ldap/src/test/java/org/springframework/ldap/transaction/core/ContextSourceTransactionManagerTest.java b/spring-ldap/src/test/java/org/springframework/ldap/transaction/core/ContextSourceTransactionManagerTest.java index 8846f12f..f20ea252 100644 --- a/spring-ldap/src/test/java/org/springframework/ldap/transaction/core/ContextSourceTransactionManagerTest.java +++ b/spring-ldap/src/test/java/org/springframework/ldap/transaction/core/ContextSourceTransactionManagerTest.java @@ -141,7 +141,7 @@ public class ContextSourceTransactionManagerTest extends TestCase { DirContextHolder expectedContextHolder = new DirContextHolder( contextMock, renamingStrategyMock); expectedContextHolder - .setTransactionDataManager(transactionDataManagerMock); + .setTransactionOperationManager(transactionDataManagerMock); TransactionSynchronizationManager.bindResource(contextSourceMock, expectedContextHolder); @@ -170,7 +170,7 @@ public class ContextSourceTransactionManagerTest extends TestCase { contextControl.verify(); assertNull(TransactionSynchronizationManager .getResource(contextSourceMock)); - assertNull(expectedContextHolder.getTransactionDataManager()); + assertNull(expectedContextHolder.getTransactionOperationManager()); } public void testSetContextSource_Proxy() {