Author: markt Date: Fri Jul 26 09:04:35 2013 New Revision: 1507228 URL: http://svn.apache.org/r1507228 Log: Use some reflection trickery on the factory to work out what type of objects are being handled by the pool.
Modified: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPoolMXBean.java commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/PoolImplUtils.java Modified: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java?rev=1507228&r1=1507227&r2=1507228&view=diff ============================================================================== --- commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java (original) +++ commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPool.java Fri Jul 26 09:04:35 2013 @@ -910,6 +910,8 @@ public class GenericObjectPool<T> extend //--- JMX support ---------------------------------------------------------- + private volatile String factoryType = null; + /** * Return an estimate of the number of threads currently blocked waiting for * an object from the pool. This is intended for monitoring only, not for @@ -924,8 +926,37 @@ public class GenericObjectPool<T> extend } } + /** + * Return the type - included the specific type rather than the generic - of + * the factory. + */ + @Override + public String getFactoryType() { + // Not thread safe. Accept that there may be multiple evaluations. + if (factoryType == null) { + StringBuilder result = new StringBuilder(); + result.append(factory.getClass().getName()); + result.append('<'); + Class<?> pooledObjectType = + PoolImplUtils.getFactoryType(factory.getClass()); + result.append(pooledObjectType.getName()); + result.append('>'); + factoryType = result.toString(); + } + return factoryType; + } + + /** + * Provides information on all the objects in the pool, both idle (waiting + * to be borrowed) and active (currently borrowed). + * <p> + * Note: This is named listAllObjects so it is presented as an operation via + * JMX. That means it won't be invoked unless the explicitly requested + * whereas all attributes will be automatically requested when viewing the + * attributes for an object in a tool like JConsole. + */ @Override - public Set<DefaultPooledObjectInfo> getAllObjects() { + public Set<DefaultPooledObjectInfo> listAllObjects() { Set<DefaultPooledObjectInfo> result = new HashSet<DefaultPooledObjectInfo>(allObjects.size()); for (PooledObject<T> p : allObjects.values()) { Modified: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPoolMXBean.java URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPoolMXBean.java?rev=1507228&r1=1507227&r2=1507228&view=diff ============================================================================== --- commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPoolMXBean.java (original) +++ commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/GenericObjectPoolMXBean.java Fri Jul 26 09:04:35 2013 @@ -163,7 +163,11 @@ public interface GenericObjectPoolMXBean */ int getRemoveAbandonedTimeout(); /** - * See {@link GenericObjectPool#getAllObjects()} + * See {@link GenericObjectPool#getFactoryType()} */ - Set<DefaultPooledObjectInfo> getAllObjects(); + public String getFactoryType(); + /** + * See {@link GenericObjectPool#listAllObjects()} + */ + Set<DefaultPooledObjectInfo> listAllObjects(); } Modified: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/PoolImplUtils.java URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/PoolImplUtils.java?rev=1507228&r1=1507227&r2=1507228&view=diff ============================================================================== --- commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/PoolImplUtils.java (original) +++ commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/impl/PoolImplUtils.java Fri Jul 26 09:04:35 2013 @@ -16,6 +16,10 @@ */ package org.apache.commons.pool2.impl; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; + import org.apache.commons.pool2.KeyedPoolableObjectFactory; import org.apache.commons.pool2.KeyedPooledObjectFactory; import org.apache.commons.pool2.PoolableObjectFactory; @@ -47,6 +51,80 @@ public class PoolImplUtils { } + /** + * Identifies the concrete type of object that an object factory creates. + */ + @SuppressWarnings("rawtypes") + static Class<?> getFactoryType(Class<? extends PooledObjectFactory> factory) { + return (Class<?>) getGenericType(PooledObjectFactory.class, factory); + } + + + private static <T> Object getGenericType(Class<T> type, + Class<? extends T> clazz) { + + // Look to see if this class implements the generic interface + + // Get all the interfaces + Type[] interfaces = clazz.getGenericInterfaces(); + for (Type iface : interfaces) { + // Only need to check interfaces that use generics + if (iface instanceof ParameterizedType) { + ParameterizedType pi = (ParameterizedType) iface; + // Look for the generic interface + if (pi.getRawType() instanceof Class) { + if (type.isAssignableFrom((Class<?>) pi.getRawType())) { + return getTypeParameter( + clazz, pi.getActualTypeArguments()[0]); + } + } + } + } + + // Interface not found on this class. Look at the superclass. + Class<? extends T> superClazz = + (Class<? extends T>) clazz.getSuperclass(); + + Object result = getGenericType(type, superClazz); + if (result instanceof Class<?>) { + // Superclass implements interface and defines explicit type for + // generic + return result; + } else if (result instanceof Integer) { + // Superclass implements interface and defines unknown type for + // generic + // Map that unknown type to the generic types defined in this class + ParameterizedType superClassType = + (ParameterizedType) clazz.getGenericSuperclass(); + return getTypeParameter(clazz, + superClassType.getActualTypeArguments()[ + ((Integer) result).intValue()]); + } else { + // Error will be logged further up the call stack + return null; + } + } + + + /* + * For a generic parameter, return either the Class used or if the type + * is unknown, the index for the type in definition of the class + */ + private static Object getTypeParameter(Class<?> clazz, Type argType) { + if (argType instanceof Class<?>) { + return argType; + } else { + TypeVariable<?>[] tvs = clazz.getTypeParameters(); + for (int i = 0; i < tvs.length; i++) { + if (tvs[i].equals(argType)) { + return Integer.valueOf(i); + } + } + return null; + } + } + + private static class PoolableObjectFactoryWrapper<T> implements PooledObjectFactory<T> {