Applied Eric's second patch:

- fixes most of the javadoc errors
- removes JDK4 enum pattern for WhenExhaustedAction (won't be easy to use for Spring-based configuration)
- changed the code to use the values exposed by Commons-Pool directly
- documentation updated to reflect the changes
This commit is contained in:
Ulrik Sandberg
2007-12-02 20:16:29 +00:00
parent 2d1dced405
commit 3749f816a6
10 changed files with 145 additions and 133 deletions

View File

@@ -254,7 +254,7 @@
</entry>
<entry>
<literal>BLOCK</literal>
<literal>1</literal> (BLOCK)
</entry>
<entry>
@@ -264,7 +264,7 @@
<listitem>
<para>
The
<literal>FAIL</literal>
FAIL (<literal>0</literal>)
option will throw a
<literal>
NoSuchElementException
@@ -273,32 +273,32 @@
</para>
</listitem>
<listitem>
<para>
The
<literal>GROW</literal>
option will create and return a
new object (essentially making
<literal>maxActive</literal>
meaningless).
</para>
</listitem>
<listitem>
<para>
The
BLOCK (<literal>1</literal>)
option will wait until a new
object is available. If
<literal>maxWait</literal>
is positive a
<literal>
NoSuchElementException
</literal>
is thrown if no new object is
available after the
<literal>maxWait</literal>
time expires.
</para>
</listitem>
<listitem>
<para>
The
<literal>BLOCK</literal>
option will wait until a new
object is available. If
<literal>maxWait</literal>
is positive a
<literal>
NoSuchElementException
</literal>
is thrown if no new object is
available after the
<literal>maxWait</literal>
time expires.
GROW (<literal>2</literal>)
option will create and return a
new object (essentially making
<literal>maxActive</literal>
meaningless).
</para>
</listitem>
</itemizedlist>

View File

@@ -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.");

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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

View File

@@ -62,6 +62,9 @@ import org.springframework.ldap.pool.validation.DirContextValidator;
* href="mailto:eric.dalquist@doit.wisc.edu">eric.dalquist@doit.wisc.edu</a>
*/
class DirContextPoolableObjectFactory extends BaseKeyedPoolableObjectFactory {
/**
* Logger for this class and subclasses
*/
protected final Log logger = LogFactory.getLog(this.getClass());
private ContextSource contextSource;

View File

@@ -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;
* <td valign="top">whenExhaustedAction</td>
* <td valign="top">{@link GenericKeyedObjectPool#setWhenExhaustedAction(byte)}</td>
* <td valign="top">No</td>
* <td valign="top">{@link GenericObjectPool#WHEN_EXHAUSTED_BLOCK}</td>
* <td valign="top">{@link GenericKeyedObjectPool#WHEN_EXHAUSTED_BLOCK}</td>
* </tr>
* <tr>
* <td valign="top">testOnBorrow</td>
@@ -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);
}
}

View File

@@ -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");

View File

@@ -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;
/**

View File

@@ -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);