diff --git a/spring-ldap/docs/reference/src/pooling.xml b/spring-ldap/docs/reference/src/pooling.xml index c63e9503..7d7d2ddd 100644 --- a/spring-ldap/docs/reference/src/pooling.xml +++ b/spring-ldap/docs/reference/src/pooling.xml @@ -254,7 +254,7 @@ - BLOCK + 1 (BLOCK) @@ -264,7 +264,7 @@ The - FAIL + FAIL (0) option will throw a NoSuchElementException @@ -273,32 +273,32 @@ - - - The - GROW - option will create and return a - new object (essentially making - maxActive - meaningless). - - + + + The + BLOCK (1) + option will wait until a new + object is available. If + maxWait + is positive a + + NoSuchElementException + + is thrown if no new object is + available after the + maxWait + time expires. + + The - BLOCK - option will wait until a new - object is available. If - maxWait - is positive a - - NoSuchElementException - - is thrown if no new object is - available after the - maxWait - time expires. + GROW (2) + option will create and return a + new object (essentially making + maxActive + meaningless). diff --git a/spring-ldap/src/main/java/org/springframework/ldap/pool/DelegatingContext.java b/spring-ldap/src/main/java/org/springframework/ldap/pool/DelegatingContext.java index 729baece..1d51315e 100644 --- a/spring-ldap/src/main/java/org/springframework/ldap/pool/DelegatingContext.java +++ b/spring-ldap/src/main/java/org/springframework/ldap/pool/DelegatingContext.java @@ -26,8 +26,13 @@ import javax.naming.NamingException; import org.apache.commons.lang.Validate; import org.apache.commons.pool.KeyedObjectPool; +import org.springframework.ldap.pool.factory.PoolingContextSource; /** + * Used by {@link PoolingContextSource} to wrap a {@link Context}, delegating most methods + * to the underlying context, retains a reference to the pool the context was checked out + * from and returns itself to the pool when {@link #close()} is called. + * * @author Eric Dalquist */ public class DelegatingContext implements Context { @@ -36,6 +41,14 @@ public class DelegatingContext implements Context { private final DirContextType dirContextType; + /** + * Create a new delegating context for the specified pool, context and context type. + * + * @param keyedObjectPool The pool the delegate context was checked out from. + * @param delegateContext The context to delegate operations to. + * @param dirContextType The type of context, used as a key for the pool. + * @throws IllegalArgumentException if any of the arguments are null + */ public DelegatingContext(KeyedObjectPool keyedObjectPool, Context delegateContext, DirContextType dirContextType) { Validate.notNull(keyedObjectPool, "keyedObjectPool may not be null"); Validate.notNull(delegateContext, "delegateContext may not be null"); @@ -49,21 +62,31 @@ public class DelegatingContext implements Context { //***** Helper Methods *****// + /** + * @return The direct delegate for this context proxy + */ public Context getDelegateContext() { return this.delegateContext; } + /** + * Recursivley inspect delegates until a non-delegating context is found. + * + * @return The innermost (real) Context that is being delegated to. + */ public Context getInnermostDelegateContext() { final Context delegateContext = this.getDelegateContext(); if (delegateContext instanceof DelegatingContext) { return ((DelegatingContext)delegateContext).getInnermostDelegateContext(); } - else { - return delegateContext; - } + + return delegateContext; } + /** + * @throws NamingException If the delegate is null, {@link #close()} has been called. + */ protected void assertOpen() throws NamingException { if (this.delegateContext == null) { throw new NamingException("Context is closed."); diff --git a/spring-ldap/src/main/java/org/springframework/ldap/pool/DelegatingDirContext.java b/spring-ldap/src/main/java/org/springframework/ldap/pool/DelegatingDirContext.java index 334672d1..defa0d00 100644 --- a/spring-ldap/src/main/java/org/springframework/ldap/pool/DelegatingDirContext.java +++ b/spring-ldap/src/main/java/org/springframework/ldap/pool/DelegatingDirContext.java @@ -28,14 +28,27 @@ import javax.naming.directory.SearchControls; import org.apache.commons.lang.Validate; import org.apache.commons.pool.KeyedObjectPool; import org.springframework.ldap.core.DirContextProxy; +import org.springframework.ldap.pool.factory.PoolingContextSource; /** + * Used by {@link PoolingContextSource} to wrap a {@link DirContext}, delegating most methods + * to the underlying context. This class extends {@link DelegatingContext} which handles returning + * the context to the pool on a call to {@link #close()} + * * @author Eric Dalquist */ public class DelegatingDirContext extends DelegatingContext implements DirContext, DirContextProxy { private DirContext delegateDirContext; + /** + * Create a new delegating dir context for the specified pool, context and context type. + * + * @param keyedObjectPool The pool the delegate context was checked out from. + * @param delegateDirContext The dir context to delegate operations to. + * @param dirContextType The type of context, used as a key for the pool. + * @throws IllegalArgumentException if any of the arguments are null + */ public DelegatingDirContext(KeyedObjectPool keyedObjectPool, DirContext delegateDirContext, DirContextType dirContextType) { super(keyedObjectPool, delegateDirContext, dirContextType); Validate.notNull(delegateDirContext, "delegateDirContext may not be null"); @@ -46,6 +59,9 @@ public class DelegatingDirContext extends DelegatingContext implements DirContex //***** Helper Methods *****// + /** + * @return The direct delegate for this dir context proxy + */ public DirContext getDelegateDirContext() { return this.delegateDirContext; } @@ -54,15 +70,19 @@ public class DelegatingDirContext extends DelegatingContext implements DirContex return this.getDelegateDirContext(); } + /** + * Recursivley inspect delegates until a non-delegating dir context is found. + * + * @return The innermost (real) DirContext that is being delegated to. + */ public DirContext getInnermostDelegateDirContext() { final DirContext delegateDirContext = this.getDelegateDirContext(); if (delegateDirContext instanceof DelegatingDirContext) { return ((DelegatingDirContext)delegateDirContext).getInnermostDelegateDirContext(); } - else { - return delegateDirContext; - } + + return delegateDirContext; } protected void assertOpen() throws NamingException { @@ -119,7 +139,7 @@ public class DelegatingDirContext extends DelegatingContext implements DirContex * @see org.springframework.ldap.core.DirContextProxy#getTargetContext() */ public DirContext getTargetContext() { - return this.delegateDirContext; + return this.getInnermostDelegateDirContext(); } @@ -328,7 +348,7 @@ public class DelegatingDirContext extends DelegatingContext implements DirContex } /** - * @see edu.wisc.commons.lcp.pool.DelegatingContext#close() + * @see DelegatingContext#close() */ public void close() throws NamingException { if (this.delegateDirContext == null) { diff --git a/spring-ldap/src/main/java/org/springframework/ldap/pool/DelegatingLdapContext.java b/spring-ldap/src/main/java/org/springframework/ldap/pool/DelegatingLdapContext.java index 99fd6717..1c64a16a 100644 --- a/spring-ldap/src/main/java/org/springframework/ldap/pool/DelegatingLdapContext.java +++ b/spring-ldap/src/main/java/org/springframework/ldap/pool/DelegatingLdapContext.java @@ -25,13 +25,26 @@ import javax.naming.ldap.LdapContext; import org.apache.commons.lang.Validate; import org.apache.commons.pool.KeyedObjectPool; +import org.springframework.ldap.pool.factory.PoolingContextSource; /** + * Used by {@link PoolingContextSource} to wrap a {@link LdapContext}, delegating most methods + * to the underlying context. This class extends {@link DelegatingDirContext} which handles returning + * the context to the pool on a call to {@link #close()} + * * @author Eric Dalquist */ public class DelegatingLdapContext extends DelegatingDirContext implements LdapContext { private LdapContext delegateLdapContext; + /** + * Create a new delegating ldap context for the specified pool, context and context type. + * + * @param keyedObjectPool The pool the delegate context was checked out from. + * @param delegateLdapContext The ldap context to delegate operations to. + * @param dirContextType The type of context, used as a key for the pool. + * @throws IllegalArgumentException if any of the arguments are null + */ public DelegatingLdapContext(KeyedObjectPool keyedObjectPool, LdapContext delegateLdapContext, DirContextType dirContextType) { super(keyedObjectPool, delegateLdapContext, dirContextType); Validate.notNull(delegateLdapContext, "delegateLdapContext may not be null"); @@ -42,6 +55,9 @@ public class DelegatingLdapContext extends DelegatingDirContext implements LdapC //***** Helper Methods *****// + /** + * @return The direct delegate for this ldap context proxy + */ public LdapContext getDelegateLdapContext() { return this.delegateLdapContext; } @@ -51,15 +67,19 @@ public class DelegatingLdapContext extends DelegatingDirContext implements LdapC return this.getDelegateLdapContext(); } + /** + * Recursivley inspect delegates until a non-delegating ldap context is found. + * + * @return The innermost (real) DirContext that is being delegated to. + */ public LdapContext getInnermostDelegateLdapContext() { final LdapContext delegateLdapContext = this.getDelegateLdapContext(); if (delegateLdapContext instanceof DelegatingLdapContext) { return ((DelegatingLdapContext)delegateLdapContext).getInnermostDelegateLdapContext(); } - else { - return delegateLdapContext; - } + + return delegateLdapContext; } protected void assertOpen() throws NamingException { @@ -166,7 +186,7 @@ public class DelegatingLdapContext extends DelegatingDirContext implements LdapC } /** - * @see edu.wisc.commons.lcp.pool.DelegatingContext#close() + * @see DelegatingDirContext#close() */ public void close() throws NamingException { if (this.delegateLdapContext == null) { diff --git a/spring-ldap/src/main/java/org/springframework/ldap/pool/DirContextType.java b/spring-ldap/src/main/java/org/springframework/ldap/pool/DirContextType.java index 18e96c96..93b5ae50 100644 --- a/spring-ldap/src/main/java/org/springframework/ldap/pool/DirContextType.java +++ b/spring-ldap/src/main/java/org/springframework/ldap/pool/DirContextType.java @@ -16,6 +16,10 @@ package org.springframework.ldap.pool; +import javax.naming.directory.DirContext; + +import org.springframework.ldap.core.ContextSource; + /** * An enum representing the two types of {@link DirContext}s that can be returned by a diff --git a/spring-ldap/src/main/java/org/springframework/ldap/pool/factory/DirContextPoolableObjectFactory.java b/spring-ldap/src/main/java/org/springframework/ldap/pool/factory/DirContextPoolableObjectFactory.java index 2ffe4e0f..b71e82c9 100644 --- a/spring-ldap/src/main/java/org/springframework/ldap/pool/factory/DirContextPoolableObjectFactory.java +++ b/spring-ldap/src/main/java/org/springframework/ldap/pool/factory/DirContextPoolableObjectFactory.java @@ -62,6 +62,9 @@ import org.springframework.ldap.pool.validation.DirContextValidator; * href="mailto:eric.dalquist@doit.wisc.edu">eric.dalquist@doit.wisc.edu */ class DirContextPoolableObjectFactory extends BaseKeyedPoolableObjectFactory { + /** + * Logger for this class and subclasses + */ protected final Log logger = LogFactory.getLog(this.getClass()); private ContextSource contextSource; diff --git a/spring-ldap/src/main/java/org/springframework/ldap/pool/factory/PoolingContextSource.java b/spring-ldap/src/main/java/org/springframework/ldap/pool/factory/PoolingContextSource.java index 6e8009b7..1e5b1f87 100644 --- a/spring-ldap/src/main/java/org/springframework/ldap/pool/factory/PoolingContextSource.java +++ b/spring-ldap/src/main/java/org/springframework/ldap/pool/factory/PoolingContextSource.java @@ -16,9 +16,6 @@ package org.springframework.ldap.pool.factory; -import java.util.HashMap; -import java.util.Map; - import javax.naming.directory.DirContext; import javax.naming.ldap.LdapContext; @@ -100,7 +97,7 @@ import org.springframework.ldap.pool.validation.DirContextValidator; * whenExhaustedAction * {@link GenericKeyedObjectPool#setWhenExhaustedAction(byte)} * No - * {@link GenericObjectPool#WHEN_EXHAUSTED_BLOCK} + * {@link GenericKeyedObjectPool#WHEN_EXHAUSTED_BLOCK} * * * testOnBorrow @@ -144,73 +141,18 @@ import org.springframework.ldap.pool.validation.DirContextValidator; * @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()); private final GenericKeyedObjectPool keyedObjectPool; private final DirContextPoolableObjectFactory dirContextPoolableObjectFactory; - public static final class WhenExhaustedAction { - - static { - values = new HashMap(); - } - - /** - * A "when exhausted action" type indicating that when the pool is - * exhausted (i.e., the maximum number of active objects has - * been reached), the {@link #borrowObject} - * method should fail, throwing a {@link NoSuchElementException}. - */ - public static final WhenExhaustedAction FAIL = new WhenExhaustedAction("FAIL", GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL); - - /** - * A "when exhausted action" type indicating that when the pool - * is exhausted (i.e., the maximum number - * of active objects has been reached), the {@link #borrowObject} - * method should block until a new object is available, or the - * {@link #getMaxWait maximum wait time} has been reached. - */ - public static final WhenExhaustedAction BLOCK = new WhenExhaustedAction("BLOCK", GenericKeyedObjectPool.WHEN_EXHAUSTED_BLOCK); - - /** - * A "when exhausted action" type indicating that when the pool is - * exhausted (i.e., the maximum number - * of active objects has been reached), the {@link #borrowObject} - * method should simply create a new object anyway. - */ - public static final WhenExhaustedAction GROW = new WhenExhaustedAction("GROW", GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW); - - private static Map values; - - private final byte commonsPoolId; - - private final String name; - - private WhenExhaustedAction(String name, byte id) { - this.name = name; - this.commonsPoolId = id; - values.put(new Byte(id), this); - } - - /* - * @see java.lang.Object#toString() - */ - public String toString() { - return name; - } - - /** - * The appropriate {@link GenericKeyedObjectPool} constant for the {@link GenericKeyedObjectPool#setWhenExhaustedAction(byte)} - */ - public byte getCommonsPoolId() { - return this.commonsPoolId; - } - - public static WhenExhaustedAction getActionForId(byte id) { - return (WhenExhaustedAction) values.get(new Byte(id)); - } - } - + /** + * 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(); @@ -301,9 +243,8 @@ public class PoolingContextSource implements ContextSource, DisposableBean { /** * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#getWhenExhaustedAction() */ - public WhenExhaustedAction getWhenExhaustedAction() { - final byte whenExhaustedAction = this.keyedObjectPool.getWhenExhaustedAction(); - return WhenExhaustedAction.getActionForId(whenExhaustedAction); + public byte getWhenExhaustedAction() { + return this.keyedObjectPool.getWhenExhaustedAction(); } /** * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setMaxActive(int) @@ -374,12 +315,8 @@ public class PoolingContextSource implements ContextSource, DisposableBean { /** * @see org.apache.commons.pool.impl.GenericKeyedObjectPool#setWhenExhaustedAction(byte) */ - public void setWhenExhaustedAction(WhenExhaustedAction whenExhaustedAction) { - if (whenExhaustedAction == null) { - throw new IllegalArgumentException("whenExhaustedAction may not be null"); - } - - this.keyedObjectPool.setWhenExhaustedAction(whenExhaustedAction.getCommonsPoolId()); + public void setWhenExhaustedAction(byte whenExhaustedAction) { + this.keyedObjectPool.setWhenExhaustedAction(whenExhaustedAction); } @@ -430,21 +367,28 @@ public class PoolingContextSource implements ContextSource, DisposableBean { //***** ContextSource interface methods *****// - /** - * @see org.springframework.ldap.ContextSource#getReadOnlyContext() + /* + * @see ContextSource#getReadOnlyContext() */ public DirContext getReadOnlyContext() throws NamingException { return this.getContext(DirContextType.READ_ONLY); } - /** - * @see org.springframework.ldap.ContextSource#getReadWriteContext() + /* + * @see ContextSource#getReadWriteContext() */ public DirContext getReadWriteContext() throws NamingException { return this.getContext(DirContextType.READ_WRITE); } - protected DirContext getContext(DirContextType dirContextType) throws NamingException { + /** + * 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); @@ -456,8 +400,7 @@ public class PoolingContextSource implements ContextSource, DisposableBean { if (dirContext instanceof LdapContext) { return new DelegatingLdapContext(this.keyedObjectPool, (LdapContext)dirContext, dirContextType); } - else { - return new DelegatingDirContext(this.keyedObjectPool, dirContext, dirContextType); - } + + return new DelegatingDirContext(this.keyedObjectPool, dirContext, dirContextType); } } diff --git a/spring-ldap/src/main/java/org/springframework/ldap/pool/validation/DefaultDirContextValidator.java b/spring-ldap/src/main/java/org/springframework/ldap/pool/validation/DefaultDirContextValidator.java index 92af8ae3..450e88e4 100644 --- a/spring-ldap/src/main/java/org/springframework/ldap/pool/validation/DefaultDirContextValidator.java +++ b/spring-ldap/src/main/java/org/springframework/ldap/pool/validation/DefaultDirContextValidator.java @@ -73,12 +73,19 @@ import org.springframework.ldap.pool.DirContextType; * @author Eric Dalquist */ public class DefaultDirContextValidator implements DirContextValidator { + /** + * Logger for this class and sub-classes + */ protected final Log logger = LogFactory.getLog(this.getClass()); private String base; private String filter; private SearchControls searchControls; + /** + * Create the default validator, creates {@link SearchControls} with a countLimit of 1, returningAttributes of + * objectclass and timeLimit of 500. The default base is an empty string and the default filter is objectclass=* + */ public DefaultDirContextValidator() { this.searchControls = new SearchControls(); this.searchControls.setCountLimit(1); @@ -137,7 +144,7 @@ public class DefaultDirContextValidator implements DirContextValidator { /** - * @see edu.wisc.commons.lcp.validation.DirContextValidator#validateDirContext(edu.wisc.commons.lcp.pool.DirContextType, javax.naming.directory.DirContext) + * @see DirContextValidator#validateDirContext(DirContextType, javax.naming.directory.DirContext) */ public boolean validateDirContext(DirContextType contextType, DirContext dirContext) { Validate.notNull(contextType, "contextType may not be null"); diff --git a/spring-ldap/src/main/java/org/springframework/ldap/pool/validation/DirContextValidator.java b/spring-ldap/src/main/java/org/springframework/ldap/pool/validation/DirContextValidator.java index 494140a5..5eab0faf 100644 --- a/spring-ldap/src/main/java/org/springframework/ldap/pool/validation/DirContextValidator.java +++ b/spring-ldap/src/main/java/org/springframework/ldap/pool/validation/DirContextValidator.java @@ -18,6 +18,7 @@ package org.springframework.ldap.pool.validation; import javax.naming.directory.DirContext; +import org.springframework.ldap.core.ContextSource; import org.springframework.ldap.pool.DirContextType; /** diff --git a/spring-ldap/src/test/java/org/springframework/ldap/pool/factory/PoolingContextSourceTest.java b/spring-ldap/src/test/java/org/springframework/ldap/pool/factory/PoolingContextSourceTest.java index 175a1b17..00b8dc2d 100644 --- a/spring-ldap/src/test/java/org/springframework/ldap/pool/factory/PoolingContextSourceTest.java +++ b/spring-ldap/src/test/java/org/springframework/ldap/pool/factory/PoolingContextSourceTest.java @@ -18,11 +18,11 @@ package org.springframework.ldap.pool.factory; import javax.naming.directory.DirContext; import javax.naming.ldap.LdapContext; +import org.apache.commons.pool.impl.GenericKeyedObjectPool; import org.easymock.MockControl; import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.ldap.core.ContextSource; import org.springframework.ldap.pool.AbstractPoolTestCase; -import org.springframework.ldap.pool.factory.PoolingContextSource.WhenExhaustedAction; import org.springframework.ldap.pool.validation.DirContextValidator; /** @@ -101,18 +101,9 @@ public class PoolingContextSourceTest extends AbstractPoolTestCase { final long timeBetweenEvictionRunsMillis = poolingContextSource.getTimeBetweenEvictionRunsMillis(); assertEquals(120000L, timeBetweenEvictionRunsMillis); - try { - poolingContextSource.setWhenExhaustedAction(null); - fail("PoolingContextSource.setWhenExhaustedAction should have thrown an IllegalArgumentException"); - } - catch (IllegalArgumentException iae) { - // Expected - } - poolingContextSource.setWhenExhaustedAction(PoolingContextSource.WhenExhaustedAction.BLOCK); - final WhenExhaustedAction whenExhaustedAction = poolingContextSource.getWhenExhaustedAction(); - assertEquals(PoolingContextSource.WhenExhaustedAction.BLOCK, whenExhaustedAction); - - assertNull(PoolingContextSource.WhenExhaustedAction.getActionForId(Byte.MAX_VALUE)); + poolingContextSource.setWhenExhaustedAction(GenericKeyedObjectPool.WHEN_EXHAUSTED_BLOCK); + final byte whenExhaustedAction = poolingContextSource.getWhenExhaustedAction(); + assertEquals(GenericKeyedObjectPool.WHEN_EXHAUSTED_BLOCK, whenExhaustedAction); final int numActive = poolingContextSource.getNumActive(); assertEquals(0, numActive);