diff --git a/mvn-build/core/src/main/java/org/springframework/ldap/core/ContextSource.java b/mvn-build/core/src/main/java/org/springframework/ldap/core/ContextSource.java index 87656e44..5c142d13 100644 --- a/mvn-build/core/src/main/java/org/springframework/ldap/core/ContextSource.java +++ b/mvn-build/core/src/main/java/org/springframework/ldap/core/ContextSource.java @@ -21,7 +21,10 @@ import javax.naming.directory.DirContext; import org.springframework.ldap.NamingException; /** - * Interface used by {@link LdapTemplate} to create LDAP contexts. + * A ContextSource is responsible for configuring and creating + * DirContext instances. It is typically used from + * {@link LdapTemplate} to acquiring contexts for LDAP operations, but may be + * used standalone to perform LDAP authentication. * * @see org.springframework.ldap.core.LdapTemplate * @@ -30,22 +33,34 @@ import org.springframework.ldap.NamingException; */ public interface ContextSource { - /** - * Gets a read-only DirContext. The returned DirContext must be possible to - * perform read-only operations on. - * - * @return A DirContext instance, never null. - * @throws NamingException - * if some error occurs creating an DirContext. - */ - public DirContext getReadOnlyContext() throws NamingException; + /** + * Gets a read-only DirContext. The returned + * DirContext must be possible to perform read-only operations + * on. + * + * @return A DirContext instance, never null. + * @throws NamingException if some error occurs creating an DirContext. + */ + public DirContext getReadOnlyContext() throws NamingException; - /** - * Gets a read-write DirContext. - * - * @return A DirContext instance, never null. - * @throws NamingException - * if some error occurs creating an DirContext. - */ - public DirContext getReadWriteContext() throws NamingException; + /** + * Gets a read-write DirContext instance. + * + * @return A DirContext instance, never null. + * @throws NamingException if some error occurs creating an + * DirContext. + */ + public DirContext getReadWriteContext() throws NamingException; + + /** + * Gets a DirContext instance authenticated using the supplied + * principal and credentials. + * + * @param principal The principal (typically a distinguished name of a user + * in the LDAP tree) to use for authentication. + * @param credentials The credentials to use for authentication. + * @return an authenticated DirContext instance, never + * null. + */ + public DirContext getContext(String principal, String credentials) throws NamingException; } \ No newline at end of file diff --git a/mvn-build/core/src/main/java/org/springframework/ldap/core/support/AbstractContextSource.java b/mvn-build/core/src/main/java/org/springframework/ldap/core/support/AbstractContextSource.java index d1149fcb..b16a88af 100644 --- a/mvn-build/core/src/main/java/org/springframework/ldap/core/support/AbstractContextSource.java +++ b/mvn-build/core/src/main/java/org/springframework/ldap/core/support/AbstractContextSource.java @@ -38,15 +38,16 @@ import org.springframework.ldap.support.LdapUtils; * returns an authenticated * DirContext implementation for both read-only and * read-write operations. To have an anonymous environment created for read-only - * operations, set the anonymousReadOnly property to true. + * operations, set the anonymousReadOnly property to + * true. *

* Implementing classes need to implement - * {@link #getDirContextInstance(Hashtable)} to create a DirContext instance of - * the desired type. + * {@link #getDirContextInstance(Hashtable)} to create a DirContext + * instance of the desired type. *

- * If an {@link AuthenticationSource} is set, this will be used for getting user principal - * and password for each new connection, otherwise a default one will be created - * using the specified userDn and password. + * If an {@link AuthenticationSource} is set, this will be used for getting user + * principal and password for each new connection, otherwise a default one will + * be created using the specified userDn and password. *

* Note: When using implementations of this class outside of a Spring * Context it is necessary to call {@link #afterPropertiesSet()} when all @@ -99,6 +100,19 @@ public abstract class AbstractContextSource implements BaseLdapPathContextSource private DirContextAuthenticationStrategy authenticationStrategy = new SimpleDirContextAuthenticationStrategy(); + public DirContext getContext(String principal, String credentials) { + DirContext ctx = createContext(getAuthenticatedEnv(principal, credentials)); + + try { + authenticationStrategy.processContextAfterCreation(ctx, principal, credentials); + return ctx; + } + catch (NamingException e) { + closeContext(ctx); + throw LdapUtils.convertLdapException(e); + } + } + /* * (non-Javadoc) * @@ -106,7 +120,7 @@ public abstract class AbstractContextSource implements BaseLdapPathContextSource */ public DirContext getReadOnlyContext() { if (!anonymousReadOnly) { - return createContext(getAuthenticatedEnv()); + return getContext(authenticationSource.getPrincipal(), authenticationSource.getCredentials()); } else { return createContext(getAnonymousEnv()); @@ -119,7 +133,7 @@ public abstract class AbstractContextSource implements BaseLdapPathContextSource * @see org.springframework.ldap.core.ContextSource#getReadWriteContext() */ public DirContext getReadWriteContext() { - return createContext(getAuthenticatedEnv()); + return getContext(authenticationSource.getPrincipal(), authenticationSource.getCredentials()); } /** @@ -129,13 +143,14 @@ public abstract class AbstractContextSource implements BaseLdapPathContextSource * {@link DirContextAuthenticationStrategy} on this instance. * * @param env the environment to modify. + * @param principal the principal to authenticate with. + * @param credentials the credentials to authenticate with. * @see DirContextAuthenticationStrategy * @see #setAuthenticationStrategy(DirContextAuthenticationStrategy) */ - protected void setupAuthenticatedEnvironment(Hashtable env) { + protected void setupAuthenticatedEnvironment(Hashtable env, String principal, String credentials) { try { - authenticationStrategy.setupEnvironment(env, authenticationSource.getPrincipal(), authenticationSource - .getCredentials()); + authenticationStrategy.setupEnvironment(env, principal, credentials); } catch (NamingException e) { throw LdapUtils.convertLdapException(e); @@ -203,7 +218,10 @@ public abstract class AbstractContextSource implements BaseLdapPathContextSource /* * (non-Javadoc) - * @see org.springframework.ldap.core.support.BaseLdapPathSource#getBaseLdapPath() + * + * @see + * org.springframework.ldap.core.support.BaseLdapPathSource#getBaseLdapPath + * () */ public DistinguishedName getBaseLdapPath() { return getBase().immutableDistinguishedName(); @@ -211,7 +229,9 @@ public abstract class AbstractContextSource implements BaseLdapPathContextSource /* * (non-Javadoc) - * @see org.springframework.ldap.core.support.BaseLdapPathSource#getBaseLdapPathAsString() + * + * @seeorg.springframework.ldap.core.support.BaseLdapPathSource# + * getBaseLdapPathAsString() */ public String getBaseLdapPathAsString() { return getBaseLdapPath().toString(); @@ -231,9 +251,6 @@ public abstract class AbstractContextSource implements BaseLdapPathContextSource try { ctx = getDirContextInstance(environment); - authenticationStrategy.processContextAfterCreation(ctx, authenticationSource.getPrincipal(), - authenticationSource.getCredentials()); - if (log.isInfoEnabled()) { Hashtable ctxEnv = ctx.getEnvironment(); String ldapUrl = (String) ctxEnv.get(Context.PROVIDER_URL); @@ -283,8 +300,8 @@ public abstract class AbstractContextSource implements BaseLdapPathContextSource /** * Get the DirObjectFactory to use. * - * @return the DirObjectFactory to be used. null means that - * no DirObjectFactory will be used. + * @return the DirObjectFactory to be used. null means that no + * DirObjectFactory will be used. */ public Class getDirObjectFactory() { return dirObjectFactory; @@ -445,10 +462,10 @@ public abstract class AbstractContextSource implements BaseLdapPathContextSource } } - protected Hashtable getAuthenticatedEnv() { + protected Hashtable getAuthenticatedEnv(String principal, String credentials) { // The authenticated environment should always be rebuilt. Hashtable env = new Hashtable(getAnonymousEnv()); - setupAuthenticatedEnvironment(env); + setupAuthenticatedEnvironment(env, principal, credentials); return env; } @@ -502,8 +519,8 @@ public abstract class AbstractContextSource implements BaseLdapPathContextSource * Get whether an anonymous environment should be used for read-only * operations. * - * @return true if an anonymous environment should be used - * for read-only operations, false otherwise. + * @return true if an anonymous environment should be used for + * read-only operations, false otherwise. */ public boolean isAnonymousReadOnly() { return anonymousReadOnly; @@ -511,8 +528,7 @@ public abstract class AbstractContextSource implements BaseLdapPathContextSource /** * Set the {@link DirContextAuthenticationStrategy} to use for preparing the - * environment and processing the created DirContext - * instances. + * environment and processing the created DirContext instances. * * @param authenticationStrategy the * {@link DirContextAuthenticationStrategy} to use; default is diff --git a/mvn-build/core/src/main/java/org/springframework/ldap/pool/factory/PoolingContextSource.java b/mvn-build/core/src/main/java/org/springframework/ldap/pool/factory/PoolingContextSource.java index fb692584..38f3c992 100644 --- a/mvn-build/core/src/main/java/org/springframework/ldap/pool/factory/PoolingContextSource.java +++ b/mvn-build/core/src/main/java/org/springframework/ldap/pool/factory/PoolingContextSource.java @@ -32,375 +32,408 @@ import org.springframework.ldap.pool.DirContextType; import org.springframework.ldap.pool.validation.DirContextValidator; /** - * A {@link ContextSource} implementation that wraps an object pool and another {@link ContextSource}. - * {@link DirContext}s are retrieved from the pool which maintains them. + * A {@link ContextSource} implementation that wraps an object pool and another + * {@link ContextSource}. {@link DirContext}s are retrieved from the pool which + * maintains them. * * *
*
* Configuration: * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * *
PropertyDescriptionRequiredDefault
contextSource - * The {@link ContextSource} to get {@link DirContext}s from for adding to the pool. - * Yesnull
dirContextValidator - * The {@link DirContextValidator} to use for validating {@link DirContext}s. Required - * if any of the test/validate options are enabled. - * Nonull
minIdle{@link GenericKeyedObjectPool#setMinIdle(int)}No0
maxIdle{@link GenericKeyedObjectPool#setMaxIdle(int)}No8
maxActive{@link GenericKeyedObjectPool#setMaxActive(int)}No8
maxTotal{@link GenericKeyedObjectPool#setMaxTotal(int)}No-1
maxWait{@link GenericKeyedObjectPool#setMaxWait(long)}No-1L
whenExhaustedAction{@link GenericKeyedObjectPool#setWhenExhaustedAction(byte)}No{@link GenericKeyedObjectPool#WHEN_EXHAUSTED_BLOCK}
testOnBorrow{@link GenericKeyedObjectPool#setTestOnBorrow(boolean)}Nofalse
testOnReturn{@link GenericKeyedObjectPool#setTestOnReturn(boolean)}Nofalse
testWhileIdle{@link GenericKeyedObjectPool#setTestWhileIdle(boolean)}Nofalse
timeBetweenEvictionRunsMillis{@link GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis(long)}No-1L
minEvictableIdleTimeMillis{@link GenericKeyedObjectPool#setMinEvictableIdleTimeMillis(long)}No1000L * 60L * 30L
numTestsPerEvictionRun{@link GenericKeyedObjectPool#setNumTestsPerEvictionRun(int)}No3
Property Description Required Default
contextSource + * The {@link ContextSource} to get {@link DirContext}s from for adding to the + * pool.Yesnull
dirContextValidator + * The {@link DirContextValidator} to use for validating {@link DirContext}s. + * Required if any of the test/validate options are enabled.Nonull
minIdle{@link GenericKeyedObjectPool#setMinIdle(int)}No0
maxIdle{@link GenericKeyedObjectPool#setMaxIdle(int)}No8
maxActive{@link GenericKeyedObjectPool#setMaxActive(int)}No8
maxTotal{@link GenericKeyedObjectPool#setMaxTotal(int)}No-1
maxWait{@link GenericKeyedObjectPool#setMaxWait(long)}No-1L
whenExhaustedAction{@link GenericKeyedObjectPool#setWhenExhaustedAction(byte)}No{@link GenericKeyedObjectPool#WHEN_EXHAUSTED_BLOCK}
testOnBorrow{@link GenericKeyedObjectPool#setTestOnBorrow(boolean)}Nofalse
testOnReturn{@link GenericKeyedObjectPool#setTestOnReturn(boolean)}Nofalse
testWhileIdle{@link GenericKeyedObjectPool#setTestWhileIdle(boolean)}Nofalse
timeBetweenEvictionRunsMillis + * {@link GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis(long)}No-1L
minEvictableIdleTimeMillis + * {@link GenericKeyedObjectPool#setMinEvictableIdleTimeMillis(long)}No1000L * 60L * 30L
numTestsPerEvictionRun + * {@link GenericKeyedObjectPool#setNumTestsPerEvictionRun(int)}No3
* * * @author Eric Dalquist */ public class PoolingContextSource implements ContextSource, DisposableBean { - /** - * The logger for this class and sub-classes - */ - protected final Log logger = LogFactory.getLog(this.getClass()); - - protected final GenericKeyedObjectPool keyedObjectPool; - private final DirContextPoolableObjectFactory dirContextPoolableObjectFactory; - - /** - * Creates a new pooling context source, setting up the DirContext object factory - * and generic keyed object pool. - */ - public PoolingContextSource() { - this.dirContextPoolableObjectFactory = new DirContextPoolableObjectFactory(); - this.keyedObjectPool = new GenericKeyedObjectPool(); - this.keyedObjectPool.setFactory(this.dirContextPoolableObjectFactory); - } - - - //***** Pool Property Configuration *****// + /** + * The logger for this class and sub-classes + */ + protected final Log logger = LogFactory.getLog(this.getClass()); - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getMaxActive() - */ - public int getMaxActive() { - return this.keyedObjectPool.getMaxActive(); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getMaxIdle() - */ - public int getMaxIdle() { - return this.keyedObjectPool.getMaxIdle(); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getMaxTotal() - */ - public int getMaxTotal() { - return this.keyedObjectPool.getMaxTotal(); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getMaxWait() - */ - public long getMaxWait() { - return this.keyedObjectPool.getMaxWait(); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getMinEvictableIdleTimeMillis() - */ - public long getMinEvictableIdleTimeMillis() { - return this.keyedObjectPool.getMinEvictableIdleTimeMillis(); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getMinIdle() - */ - public int getMinIdle() { - return this.keyedObjectPool.getMinIdle(); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getNumActive() - */ - public int getNumActive() { - return this.keyedObjectPool.getNumActive(); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getNumIdle() - */ - public int getNumIdle() { - return this.keyedObjectPool.getNumIdle(); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getNumTestsPerEvictionRun() - */ - public int getNumTestsPerEvictionRun() { - return this.keyedObjectPool.getNumTestsPerEvictionRun(); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getTestOnBorrow() - */ - public boolean getTestOnBorrow() { - return this.keyedObjectPool.getTestOnBorrow(); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getTestOnReturn() - */ - public boolean getTestOnReturn() { - return this.keyedObjectPool.getTestOnReturn(); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getTestWhileIdle() - */ - public boolean getTestWhileIdle() { - return this.keyedObjectPool.getTestWhileIdle(); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getTimeBetweenEvictionRunsMillis() - */ - public long getTimeBetweenEvictionRunsMillis() { - return this.keyedObjectPool.getTimeBetweenEvictionRunsMillis(); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getWhenExhaustedAction() - */ - public byte getWhenExhaustedAction() { - return this.keyedObjectPool.getWhenExhaustedAction(); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setMaxActive(int) - */ - public void setMaxActive(int maxActive) { - this.keyedObjectPool.setMaxActive(maxActive); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setMaxIdle(int) - */ - public void setMaxIdle(int maxIdle) { - this.keyedObjectPool.setMaxIdle(maxIdle); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setMaxTotal(int) - */ - public void setMaxTotal(int maxTotal) { - this.keyedObjectPool.setMaxTotal(maxTotal); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setMaxWait(long) - */ - public void setMaxWait(long maxWait) { - this.keyedObjectPool.setMaxWait(maxWait); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setMinEvictableIdleTimeMillis(long) - */ - public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) { - this.keyedObjectPool.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setMinIdle(int) - */ - public void setMinIdle(int poolSize) { - this.keyedObjectPool.setMinIdle(poolSize); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setNumTestsPerEvictionRun(int) - */ - public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) { - this.keyedObjectPool.setNumTestsPerEvictionRun(numTestsPerEvictionRun); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setTestOnBorrow(boolean) - */ - public void setTestOnBorrow(boolean testOnBorrow) { - this.keyedObjectPool.setTestOnBorrow(testOnBorrow); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setTestOnReturn(boolean) - */ - public void setTestOnReturn(boolean testOnReturn) { - this.keyedObjectPool.setTestOnReturn(testOnReturn); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setTestWhileIdle(boolean) - */ - public void setTestWhileIdle(boolean testWhileIdle) { - this.keyedObjectPool.setTestWhileIdle(testWhileIdle); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis(long) - */ - public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) { - this.keyedObjectPool.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); - } - /** - * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setWhenExhaustedAction(byte) - */ - public void setWhenExhaustedAction(byte whenExhaustedAction) { - this.keyedObjectPool.setWhenExhaustedAction(whenExhaustedAction); - } - - - //***** Object Factory Property Configuration *****// - - /** - * @return the contextSource - */ - public ContextSource getContextSource() { - return this.dirContextPoolableObjectFactory.getContextSource(); - } - /** - * @return the dirContextValidator - */ - public DirContextValidator getDirContextValidator() { - return this.dirContextPoolableObjectFactory.getDirContextValidator(); - } - /** - * @param contextSource the contextSource to set - * @Required - */ - public void setContextSource(ContextSource contextSource) { - this.dirContextPoolableObjectFactory.setContextSource(contextSource); - } - /** - * @param dirContextValidator the dirContextValidator to set - * @Required - */ - public void setDirContextValidator(DirContextValidator dirContextValidator) { - this.dirContextPoolableObjectFactory.setDirContextValidator(dirContextValidator); - } + protected final GenericKeyedObjectPool keyedObjectPool; - - //***** DisposableBean interface methods *****// + private final DirContextPoolableObjectFactory dirContextPoolableObjectFactory; - /* (non-Javadoc) - * @see org.springframework.beans.factory.DisposableBean#destroy() - */ - public void destroy() throws Exception { - try { - this.keyedObjectPool.close(); - } - catch (Exception e) { - this.logger.warn("An exception occured while closing the underlying pool.", e); - } - } - - - //***** ContextSource interface methods *****// - - /* - * @see ContextSource#getReadOnlyContext() - */ - public DirContext getReadOnlyContext() throws NamingException { - return this.getContext(DirContextType.READ_ONLY); - } + /** + * Creates a new pooling context source, setting up the DirContext object + * factory and generic keyed object pool. + */ + public PoolingContextSource() { + this.dirContextPoolableObjectFactory = new DirContextPoolableObjectFactory(); + this.keyedObjectPool = new GenericKeyedObjectPool(); + this.keyedObjectPool.setFactory(this.dirContextPoolableObjectFactory); + } - /* - * @see ContextSource#getReadWriteContext() - */ - public DirContext getReadWriteContext() throws NamingException { - return this.getContext(DirContextType.READ_WRITE); - } + // ***** Pool Property Configuration *****// - /** - * Gets a DirContext of the specified type from the keyed object pool. - * - * @param dirContextType The type of context to return. - * @return A wrapped DirContext of the specified type. - * @throws DataAccessResourceFailureException If retreiving the object from the pool throws an exception - */ - protected DirContext getContext(DirContextType dirContextType) { - final DirContext dirContext; - try { - dirContext = (DirContext)this.keyedObjectPool.borrowObject(dirContextType); - } - catch (Exception e) { - throw new DataAccessResourceFailureException("Failed to borrow DirContext from pool.", e); - } - - if (dirContext instanceof LdapContext) { - return new DelegatingLdapContext(this.keyedObjectPool, (LdapContext)dirContext, dirContextType); - } + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getMaxActive() + */ + public int getMaxActive() { + return this.keyedObjectPool.getMaxActive(); + } - return new DelegatingDirContext(this.keyedObjectPool, dirContext, dirContextType); - } + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getMaxIdle() + */ + public int getMaxIdle() { + return this.keyedObjectPool.getMaxIdle(); + } + + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getMaxTotal() + */ + public int getMaxTotal() { + return this.keyedObjectPool.getMaxTotal(); + } + + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getMaxWait() + */ + public long getMaxWait() { + return this.keyedObjectPool.getMaxWait(); + } + + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getMinEvictableIdleTimeMillis() + */ + public long getMinEvictableIdleTimeMillis() { + return this.keyedObjectPool.getMinEvictableIdleTimeMillis(); + } + + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getMinIdle() + */ + public int getMinIdle() { + return this.keyedObjectPool.getMinIdle(); + } + + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getNumActive() + */ + public int getNumActive() { + return this.keyedObjectPool.getNumActive(); + } + + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getNumIdle() + */ + public int getNumIdle() { + return this.keyedObjectPool.getNumIdle(); + } + + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getNumTestsPerEvictionRun() + */ + public int getNumTestsPerEvictionRun() { + return this.keyedObjectPool.getNumTestsPerEvictionRun(); + } + + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getTestOnBorrow() + */ + public boolean getTestOnBorrow() { + return this.keyedObjectPool.getTestOnBorrow(); + } + + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getTestOnReturn() + */ + public boolean getTestOnReturn() { + return this.keyedObjectPool.getTestOnReturn(); + } + + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getTestWhileIdle() + */ + public boolean getTestWhileIdle() { + return this.keyedObjectPool.getTestWhileIdle(); + } + + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getTimeBetweenEvictionRunsMillis() + */ + public long getTimeBetweenEvictionRunsMillis() { + return this.keyedObjectPool.getTimeBetweenEvictionRunsMillis(); + } + + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getWhenExhaustedAction() + */ + public byte getWhenExhaustedAction() { + return this.keyedObjectPool.getWhenExhaustedAction(); + } + + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setMaxActive(int) + */ + public void setMaxActive(int maxActive) { + this.keyedObjectPool.setMaxActive(maxActive); + } + + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setMaxIdle(int) + */ + public void setMaxIdle(int maxIdle) { + this.keyedObjectPool.setMaxIdle(maxIdle); + } + + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setMaxTotal(int) + */ + public void setMaxTotal(int maxTotal) { + this.keyedObjectPool.setMaxTotal(maxTotal); + } + + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setMaxWait(long) + */ + public void setMaxWait(long maxWait) { + this.keyedObjectPool.setMaxWait(maxWait); + } + + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setMinEvictableIdleTimeMillis(long) + */ + public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) { + this.keyedObjectPool.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); + } + + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setMinIdle(int) + */ + public void setMinIdle(int poolSize) { + this.keyedObjectPool.setMinIdle(poolSize); + } + + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setNumTestsPerEvictionRun(int) + */ + public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) { + this.keyedObjectPool.setNumTestsPerEvictionRun(numTestsPerEvictionRun); + } + + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setTestOnBorrow(boolean) + */ + public void setTestOnBorrow(boolean testOnBorrow) { + this.keyedObjectPool.setTestOnBorrow(testOnBorrow); + } + + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setTestOnReturn(boolean) + */ + public void setTestOnReturn(boolean testOnReturn) { + this.keyedObjectPool.setTestOnReturn(testOnReturn); + } + + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setTestWhileIdle(boolean) + */ + public void setTestWhileIdle(boolean testWhileIdle) { + this.keyedObjectPool.setTestWhileIdle(testWhileIdle); + } + + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setTimeBetweenEvictionRunsMillis(long) + */ + public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) { + this.keyedObjectPool.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); + } + + /** + * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setWhenExhaustedAction(byte) + */ + public void setWhenExhaustedAction(byte whenExhaustedAction) { + this.keyedObjectPool.setWhenExhaustedAction(whenExhaustedAction); + } + + // ***** Object Factory Property Configuration *****// + + /** + * @return the contextSource + */ + public ContextSource getContextSource() { + return this.dirContextPoolableObjectFactory.getContextSource(); + } + + /** + * @return the dirContextValidator + */ + public DirContextValidator getDirContextValidator() { + return this.dirContextPoolableObjectFactory.getDirContextValidator(); + } + + /** + * @param contextSource the contextSource to set + * @Required + */ + public void setContextSource(ContextSource contextSource) { + this.dirContextPoolableObjectFactory.setContextSource(contextSource); + } + + /** + * @param dirContextValidator the dirContextValidator to set + * @Required + */ + public void setDirContextValidator(DirContextValidator dirContextValidator) { + this.dirContextPoolableObjectFactory.setDirContextValidator(dirContextValidator); + } + + // ***** DisposableBean interface methods *****// + + /* + * (non-Javadoc) + * + * @see org.springframework.beans.factory.DisposableBean#destroy() + */ + public void destroy() throws Exception { + try { + this.keyedObjectPool.close(); + } + catch (Exception e) { + this.logger.warn("An exception occured while closing the underlying pool.", e); + } + } + + // ***** ContextSource interface methods *****// + + /* + * @see ContextSource#getReadOnlyContext() + */ + public DirContext getReadOnlyContext() throws NamingException { + return this.getContext(DirContextType.READ_ONLY); + } + + /* + * @see ContextSource#getReadWriteContext() + */ + public DirContext getReadWriteContext() throws NamingException { + return this.getContext(DirContextType.READ_WRITE); + } + + /** + * Gets a DirContext of the specified type from the keyed object pool. + * + * @param dirContextType The type of context to return. + * @return A wrapped DirContext of the specified type. + * @throws DataAccessResourceFailureException If retreiving the object from + * the pool throws an exception + */ + protected DirContext getContext(DirContextType dirContextType) { + final DirContext dirContext; + try { + dirContext = (DirContext) this.keyedObjectPool.borrowObject(dirContextType); + } + catch (Exception e) { + throw new DataAccessResourceFailureException("Failed to borrow DirContext from pool.", e); + } + + if (dirContext instanceof LdapContext) { + return new DelegatingLdapContext(this.keyedObjectPool, (LdapContext) dirContext, dirContextType); + } + + return new DelegatingDirContext(this.keyedObjectPool, dirContext, dirContextType); + } + + public DirContext getContext(String principal, String credentials) throws NamingException { + throw new UnsupportedOperationException("Not supported for this implementation"); + } } 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 968b7396..64023b2b 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 @@ -40,155 +40,144 @@ import org.springframework.transaction.compensating.CompensatingTransactionOpera * @author Mattias Arthursson * @since 1.2 */ -public class LdapCompensatingTransactionOperationFactory implements - CompensatingTransactionOperationFactory { - private static Log log = LogFactory - .getLog(LdapCompensatingTransactionOperationFactory.class); +public class LdapCompensatingTransactionOperationFactory implements CompensatingTransactionOperationFactory { + private static Log log = LogFactory.getLog(LdapCompensatingTransactionOperationFactory.class); - private TempEntryRenamingStrategy renamingStrategy; + private TempEntryRenamingStrategy renamingStrategy; - /** - * Constructor. - * - * @param renamingStrategy - * the {@link TempEntryRenamingStrategy} to supply to relevant - * operations. - */ - public LdapCompensatingTransactionOperationFactory( - TempEntryRenamingStrategy renamingStrategy) { - this.renamingStrategy = renamingStrategy; - } + /** + * Constructor. + * + * @param renamingStrategy the {@link TempEntryRenamingStrategy} to supply + * to relevant operations. + */ + public LdapCompensatingTransactionOperationFactory(TempEntryRenamingStrategy renamingStrategy) { + this.renamingStrategy = renamingStrategy; + } - /* - * @see org.springframework.transaction.compensating.CompensatingTransactionOperationFactory#createRecordingOperation(java.lang.Object, - * java.lang.String) - */ - public CompensatingTransactionOperationRecorder createRecordingOperation( - Object resource, String operation) { - if (StringUtils - .equals(operation, LdapTransactionUtils.BIND_METHOD_NAME)) { - log.debug("Bind operation recorded"); - return new BindOperationRecorder( - createLdapOperationsInstance((DirContext) resource)); - } else if (StringUtils.equals(operation, - LdapTransactionUtils.REBIND_METHOD_NAME)) { - log.debug("Rebind operation recorded"); - return new RebindOperationRecorder( - createLdapOperationsInstance((DirContext) resource), - renamingStrategy); - } else if (StringUtils.equals(operation, - LdapTransactionUtils.RENAME_METHOD_NAME)) { - log.debug("Rename operation recorded"); - return new RenameOperationRecorder( - createLdapOperationsInstance((DirContext) resource)); - } else if (StringUtils.equals(operation, - LdapTransactionUtils.MODIFY_ATTRIBUTES_METHOD_NAME)) { - return new ModifyAttributesOperationRecorder( - createLdapOperationsInstance((DirContext) resource)); - } else if (StringUtils.equals(operation, - LdapTransactionUtils.UNBIND_METHOD_NAME)) { - return new UnbindOperationRecorder( - createLdapOperationsInstance((DirContext) resource), - renamingStrategy); - } + /* + * @seeorg.springframework.transaction.compensating. + * CompensatingTransactionOperationFactory + * #createRecordingOperation(java.lang.Object, java.lang.String) + */ + public CompensatingTransactionOperationRecorder createRecordingOperation(Object resource, String operation) { + if (StringUtils.equals(operation, LdapTransactionUtils.BIND_METHOD_NAME)) { + log.debug("Bind operation recorded"); + return new BindOperationRecorder(createLdapOperationsInstance((DirContext) resource)); + } + else if (StringUtils.equals(operation, LdapTransactionUtils.REBIND_METHOD_NAME)) { + log.debug("Rebind operation recorded"); + return new RebindOperationRecorder(createLdapOperationsInstance((DirContext) resource), renamingStrategy); + } + else if (StringUtils.equals(operation, LdapTransactionUtils.RENAME_METHOD_NAME)) { + log.debug("Rename operation recorded"); + return new RenameOperationRecorder(createLdapOperationsInstance((DirContext) resource)); + } + else if (StringUtils.equals(operation, LdapTransactionUtils.MODIFY_ATTRIBUTES_METHOD_NAME)) { + return new ModifyAttributesOperationRecorder(createLdapOperationsInstance((DirContext) resource)); + } + else if (StringUtils.equals(operation, LdapTransactionUtils.UNBIND_METHOD_NAME)) { + return new UnbindOperationRecorder(createLdapOperationsInstance((DirContext) resource), renamingStrategy); + } - log - .warn("No suitable CompensatingTransactionOperationRecorder found for method " - + operation + ". Operation will not be transacted."); - return new NullOperationRecorder(); - } + log.warn("No suitable CompensatingTransactionOperationRecorder found for method " + operation + + ". Operation will not be transacted."); + return new NullOperationRecorder(); + } - LdapOperations createLdapOperationsInstance(DirContext ctx) { - return new LdapTemplate(new SingleContextSource(ctx)); - } + 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; + /** + * 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; - } + /** + * 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#getReadOnlyContext() + */ + public DirContext getReadOnlyContext() throws NamingException { + return getNonClosingDirContextProxy(ctx); + } - /* - * @see org.springframework.ldap.ContextSource#getReadWriteContext() - */ - public DirContext getReadWriteContext() 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)); + private DirContext getNonClosingDirContextProxy(DirContext context) { + return (DirContext) Proxy.newProxyInstance(DirContextProxy.class.getClassLoader(), new Class[] { + LdapTransactionUtils.getActualTargetClass(context), DirContextProxy.class }, + new NonClosingDirContextInvocationHandler(context)); - } - } + } - /** - * 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 { + public DirContext getContext(String principal, String credentials) throws NamingException { + throw new UnsupportedOperationException("Not a valid operation for this type of ContextSource"); + } + } - private DirContext target; + /** + * 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 { - public NonClosingDirContextInvocationHandler(DirContext target) { - this.target = target; - } + private DirContext 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 { + public NonClosingDirContextInvocationHandler(DirContext target) { + this.target = target; + } - 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; - } + /* + * @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 { - try { - return method.invoke(target, args); - } catch (InvocationTargetException e) { - throw e.getTargetException(); - } - } - } + 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(); + } + } + } } diff --git a/mvn-build/core/src/main/java/org/springframework/ldap/transaction/compensating/manager/TransactionAwareContextSourceProxy.java b/mvn-build/core/src/main/java/org/springframework/ldap/transaction/compensating/manager/TransactionAwareContextSourceProxy.java index cacf52d8..97df4ff2 100644 --- a/mvn-build/core/src/main/java/org/springframework/ldap/transaction/compensating/manager/TransactionAwareContextSourceProxy.java +++ b/mvn-build/core/src/main/java/org/springframework/ldap/transaction/compensating/manager/TransactionAwareContextSourceProxy.java @@ -98,4 +98,8 @@ public class TransactionAwareContextSourceProxy implements ContextSource { } return getTransactionAwareDirContextProxy(ctx, target); } + + public DirContext getContext(String principal, String credentials) throws NamingException { + throw new UnsupportedOperationException("Not supported on a transacted ContextSource"); + } } diff --git a/mvn-build/core/src/test/java/org/springframework/ldap/core/support/LdapContextSourceTest.java b/mvn-build/core/src/test/java/org/springframework/ldap/core/support/LdapContextSourceTest.java index abce5c51..c4f1a4de 100644 --- a/mvn-build/core/src/test/java/org/springframework/ldap/core/support/LdapContextSourceTest.java +++ b/mvn-build/core/src/test/java/org/springframework/ldap/core/support/LdapContextSourceTest.java @@ -23,7 +23,6 @@ import javax.naming.Context; import junit.framework.TestCase; -import org.springframework.ldap.core.AuthenticationSource; import org.springframework.ldap.core.DistinguishedName; /** @@ -200,7 +199,7 @@ public class LdapContextSourceTest extends TestCase { tested.setPassword("secret"); tested.afterPropertiesSet(); - Hashtable env = tested.getAuthenticatedEnv(); + Hashtable env = tested.getAuthenticatedEnv("cn=Some User", "secret"); assertEquals("ldap://ldap.example.com:389/dc=example,dc=se", env.get(Context.PROVIDER_URL)); assertEquals("true", env.get(LdapContextSource.SUN_LDAP_POOLING_FLAG)); assertEquals("cn=Some User", env.get(Context.SECURITY_PRINCIPAL)); @@ -210,41 +209,6 @@ public class LdapContextSourceTest extends TestCase { assertEquals(new DistinguishedName("dc=example,dc=se"), env.get(DefaultDirObjectFactory.JNDI_ENV_BASE_PATH_KEY)); } - public void testGetAuthenticatedEnv_DummyAuthenticationProvider() throws Exception { - tested.setBase("dc=example,dc=se"); - tested.setUrl("ldap://ldap.example.com:389"); - tested.setPooled(true); - DummyAuthenticationProvider authenticationProvider = new DummyAuthenticationProvider(); - tested.setAuthenticationSource(authenticationProvider); - authenticationProvider.setPrincipal("cn=Some User"); - authenticationProvider.setCredentials("secret"); - tested.afterPropertiesSet(); - - Hashtable env = tested.getAuthenticatedEnv(); - assertEquals("ldap://ldap.example.com:389/dc=example,dc=se", env.get(Context.PROVIDER_URL)); - assertEquals("true", env.get(LdapContextSource.SUN_LDAP_POOLING_FLAG)); - assertEquals("cn=Some User", env.get(Context.SECURITY_PRINCIPAL)); - assertEquals("secret", env.get(Context.SECURITY_CREDENTIALS)); - } - - public void testGetAuthenticatedEnv_DummyAuthenticationProvider_Changed() throws Exception { - tested.setBase("dc=example,dc=se"); - tested.setUrl("ldap://ldap.example.com:389"); - tested.setPooled(true); - DummyAuthenticationProvider authenticationProvider = new DummyAuthenticationProvider(); - tested.setAuthenticationSource(authenticationProvider); - authenticationProvider.setPrincipal("cn=Some User"); - authenticationProvider.setCredentials("secret"); - tested.afterPropertiesSet(); - - authenticationProvider.setPrincipal("cn=Some Other User"); - authenticationProvider.setCredentials("other secret"); - - Hashtable env = tested.getAuthenticatedEnv(); - assertEquals("cn=Some Other User", env.get(Context.SECURITY_PRINCIPAL)); - assertEquals("other secret", env.get(Context.SECURITY_CREDENTIALS)); - } - public void testGetAnonymousEnvWhenCacheIsOff() throws Exception { tested.setBase("dc=example,dc=se"); tested.setUrl("ldap://ldap.example.com:389"); @@ -263,26 +227,4 @@ public class LdapContextSourceTest extends TestCase { env = tested.getAnonymousEnv(); assertEquals("ldap://ldap2.example.com:389/dc=example,dc=se", env.get(Context.PROVIDER_URL)); } - - private class DummyAuthenticationProvider implements AuthenticationSource { - private String principal; - - private String credentials; - - public void setCredentials(String credentials) { - this.credentials = credentials; - } - - public void setPrincipal(String principal) { - this.principal = principal; - } - - public String getPrincipal() { - return principal; - } - - public String getCredentials() { - return credentials; - } - } } diff --git a/mvn-build/integration-tests-openldap/src/test/resources/conf/ldap.properties b/mvn-build/integration-tests-openldap/src/test/resources/conf/ldap.properties index fee074ac..b7834cce 100644 --- a/mvn-build/integration-tests-openldap/src/test/resources/conf/ldap.properties +++ b/mvn-build/integration-tests-openldap/src/test/resources/conf/ldap.properties @@ -1,4 +1,4 @@ -itest.openldap.serverAddress=127.0.0.1 +itest.openldap.serverAddress=spring-ldap-test.dyndns.org userDn=cn=admin,dc=jayway,dc=se password=secret base=dc=jayway,dc=se diff --git a/mvn-build/integration-tests-openldap/src/test/resources/conf/ldapTemplateTestContext.xml b/mvn-build/integration-tests-openldap/src/test/resources/conf/ldapTemplateTestContext.xml index 5965e369..b8dbc97b 100644 --- a/mvn-build/integration-tests-openldap/src/test/resources/conf/ldapTemplateTestContext.xml +++ b/mvn-build/integration-tests-openldap/src/test/resources/conf/ldapTemplateTestContext.xml @@ -15,6 +15,10 @@ + + + +