diff --git a/mvn-build/core/changelog.txt b/mvn-build/core/changelog.txt index 43391bb1..0fad7107 100644 --- a/mvn-build/core/changelog.txt +++ b/mvn-build/core/changelog.txt @@ -13,6 +13,10 @@ http://www.ietf.org/rfc/rfc2696.txt Changes in version 1.3 (XXX 2008) ------------------------------------------- +* Moved SingleContextSource from an obscure inner class to a top-level + class. This class doesn't close the DirContext, but reuses the same. + Useful for scenarios like Paged Results. + * Removed deprecated method setUserName() in AbstractContextSource. * Added a method DistinguishedName.toCompactString that returns a more diff --git a/mvn-build/core/src/main/java/org/springframework/ldap/core/support/SingleContextSource.java b/mvn-build/core/src/main/java/org/springframework/ldap/core/support/SingleContextSource.java new file mode 100644 index 00000000..e9716875 --- /dev/null +++ b/mvn-build/core/src/main/java/org/springframework/ldap/core/support/SingleContextSource.java @@ -0,0 +1,132 @@ +package org.springframework.ldap.core.support; + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +import javax.naming.directory.DirContext; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.jmx.support.JmxUtils; +import org.springframework.ldap.NamingException; +import org.springframework.ldap.core.ContextSource; +import org.springframework.ldap.core.DirContextProxy; +import org.springframework.ldap.support.LdapUtils; +import org.springframework.ldap.transaction.compensating.LdapTransactionUtils; + +/** + * A {@link ContextSource} implementation using returning + * {@link SingleContextSource.NonClosingDirContextInvocationHandler} proxies on + * the same DirContext instance for each call. + * + * @author Mattias Arthursson + */ +public class SingleContextSource implements ContextSource { + + private static final Log log = LogFactory.getLog(SingleContextSource.class); + + /** + * A proxy for DirContext forwarding all operation to the target DirContext, + * but making sure that no close operations will be performed. + * + * @author Mattias Arthursson + */ + public static class NonClosingDirContextInvocationHandler implements + InvocationHandler { + + private DirContext target; + + public NonClosingDirContextInvocationHandler(DirContext target) { + this.target = target; + } + + /* + * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, + * java.lang.reflect.Method, java.lang.Object[]) + */ + public Object invoke(Object proxy, Method method, Object[] args) + throws Throwable { + + String methodName = method.getName(); + if (methodName.equals("getTargetContext")) { + return target; + } + else if (methodName.equals("equals")) { + // Only consider equal when proxies are identical. + return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE); + } + else if (methodName.equals("hashCode")) { + // Use hashCode of Connection proxy. + return new Integer(proxy.hashCode()); + } + else if (methodName.equals("close")) { + // Never close the target context, as this class will only be + // used for operations concerning the compensating transactions. + return null; + } + + try { + return method.invoke(target, args); + } + catch (InvocationTargetException e) { + throw e.getTargetException(); + } + } + } + + private DirContext ctx; + + /** + * Constructor. + * + * @param ctx the target DirContext. + */ + public SingleContextSource(DirContext ctx) { + this.ctx = ctx; + } + + /* + * @see org.springframework.ldap.ContextSource#getReadOnlyContext() + */ + public DirContext getReadOnlyContext() throws NamingException { + return getNonClosingDirContextProxy(ctx); + } + + /* + * @see org.springframework.ldap.ContextSource#getReadWriteContext() + */ + public DirContext getReadWriteContext() throws NamingException { + return getNonClosingDirContextProxy(ctx); + } + + private DirContext getNonClosingDirContextProxy(DirContext context) { + return (DirContext) Proxy.newProxyInstance(DirContextProxy.class + .getClassLoader(), new Class[] { + LdapTransactionUtils.getActualTargetClass(context), + DirContextProxy.class }, + new SingleContextSource.NonClosingDirContextInvocationHandler( + context)); + + } + + public DirContext getContext(String principal, String credentials) + throws NamingException { + throw new UnsupportedOperationException( + "Not a valid operation for this type of ContextSource"); + } + + /** + * Destroy method that allows the target DirContext to be cleaned up when + * the SingleContextSource is not going to be used any more. + */ + public void destroy() { + try { + ctx.close(); + } + catch (javax.naming.NamingException e) { + log.warn(e); + } + } +} \ No newline at end of file diff --git a/mvn-build/core/src/main/java/org/springframework/ldap/transaction/compensating/LdapCompensatingTransactionOperationFactory.java b/mvn-build/core/src/main/java/org/springframework/ldap/transaction/compensating/LdapCompensatingTransactionOperationFactory.java index 64023b2b..55fa4e55 100644 --- a/mvn-build/core/src/main/java/org/springframework/ldap/transaction/compensating/LdapCompensatingTransactionOperationFactory.java +++ b/mvn-build/core/src/main/java/org/springframework/ldap/transaction/compensating/LdapCompensatingTransactionOperationFactory.java @@ -15,21 +15,15 @@ */ package org.springframework.ldap.transaction.compensating; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; import javax.naming.directory.DirContext; import org.apache.commons.lang.StringUtils; 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.ldap.core.support.SingleContextSource; import org.springframework.transaction.compensating.CompensatingTransactionOperationFactory; import org.springframework.transaction.compensating.CompensatingTransactionOperationRecorder; @@ -56,7 +50,7 @@ public class LdapCompensatingTransactionOperationFactory implements Compensating } /* - * @seeorg.springframework.transaction.compensating. + * @see org.springframework.transaction.compensating. * CompensatingTransactionOperationFactory * #createRecordingOperation(java.lang.Object, java.lang.String) */ @@ -88,96 +82,4 @@ public class LdapCompensatingTransactionOperationFactory implements Compensating LdapOperations createLdapOperationsInstance(DirContext ctx) { return new LdapTemplate(new SingleContextSource(ctx)); } - - /** - * A {@link ContextSource} implementation using returning - * {@link NonClosingDirContextInvocationHandler} proxies on the same - * DirContext instance for each call. - * - * @author Mattias Arthursson - */ - static class SingleContextSource implements ContextSource { - private DirContext ctx; - - /** - * Constructor. - * - * @param ctx the target DirContext. - */ - public SingleContextSource(DirContext ctx) { - this.ctx = ctx; - } - - /* - * @see org.springframework.ldap.ContextSource#getReadOnlyContext() - */ - public DirContext getReadOnlyContext() throws NamingException { - return getNonClosingDirContextProxy(ctx); - } - - /* - * @see org.springframework.ldap.ContextSource#getReadWriteContext() - */ - public DirContext getReadWriteContext() throws NamingException { - return getNonClosingDirContextProxy(ctx); - } - - private DirContext getNonClosingDirContextProxy(DirContext context) { - return (DirContext) Proxy.newProxyInstance(DirContextProxy.class.getClassLoader(), new Class[] { - LdapTransactionUtils.getActualTargetClass(context), DirContextProxy.class }, - new NonClosingDirContextInvocationHandler(context)); - - } - - public DirContext getContext(String principal, String credentials) throws NamingException { - throw new UnsupportedOperationException("Not a valid operation for this type of ContextSource"); - } - } - - /** - * A proxy for DirContext forwarding all operation to the target DirContext, - * but making sure that no close operations will be performed. - * - * @author Mattias Arthursson - */ - public static class NonClosingDirContextInvocationHandler implements InvocationHandler { - - private DirContext target; - - public NonClosingDirContextInvocationHandler(DirContext target) { - this.target = target; - } - - /* - * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, - * java.lang.reflect.Method, java.lang.Object[]) - */ - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - - String methodName = method.getName(); - if (methodName.equals("getTargetContext")) { - return target; - } - else if (methodName.equals("equals")) { - // Only consider equal when proxies are identical. - return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE); - } - else if (methodName.equals("hashCode")) { - // Use hashCode of Connection proxy. - return new Integer(proxy.hashCode()); - } - else if (methodName.equals("close")) { - // Never close the target context, as this class will only be - // used for operations concerning the compensating transactions. - return null; - } - - try { - return method.invoke(target, args); - } - catch (InvocationTargetException e) { - throw e.getTargetException(); - } - } - } }