Author: markt Date: Mon Oct 14 10:50:28 2013 New Revision: 1531846 URL: http://svn.apache.org/r1531846 Log: Add CGLib proxy implementation and test.
Added: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/proxy/CglibProxyHandler.java (with props) commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/proxy/CglibProxySource.java (with props) commons/proper/pool/trunk/src/test/java/org/apache/commons/pool2/proxy/TestProxiedObjectPoolWithCglibProxy.java (with props) Modified: commons/proper/pool/trunk/pom.xml Modified: commons/proper/pool/trunk/pom.xml URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/pom.xml?rev=1531846&r1=1531845&r2=1531846&view=diff ============================================================================== --- commons/proper/pool/trunk/pom.xml (original) +++ commons/proper/pool/trunk/pom.xml Mon Oct 14 10:50:28 2013 @@ -120,6 +120,19 @@ <version>4.11</version> <scope>test</scope> </dependency> + <dependency> + <groupId>cglib</groupId> + <artifactId>cglib</artifactId> + <version>3.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.ow2.asm</groupId> + <artifactId>asm-util</artifactId> + <version>4.0</version> + <scope>provided</scope> + </dependency> + </dependencies> <distributionManagement> Added: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/proxy/CglibProxyHandler.java URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/proxy/CglibProxyHandler.java?rev=1531846&view=auto ============================================================================== --- commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/proxy/CglibProxyHandler.java (added) +++ commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/proxy/CglibProxyHandler.java Mon Oct 14 10:50:28 2013 @@ -0,0 +1,32 @@ +package org.apache.commons.pool2.proxy; + +import java.lang.reflect.Method; + +import org.apache.commons.pool2.UsageTracking; + +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + + +public class CglibProxyHandler<T> extends BaseProxyHandler<T> + implements MethodInterceptor { + + private final UsageTracking<T> usageTracking; + + CglibProxyHandler(T pooledObject, UsageTracking<T> usageTracking) { + super(pooledObject); + this.usageTracking = usageTracking; + } + + @Override + public Object intercept(Object object, Method method, Object[] args, + MethodProxy methodProxy) throws Throwable { + validateProxiedObject(); + T pooledObject = getPooledObject(); + if (usageTracking != null) { + usageTracking.use(pooledObject); + } + + return method.invoke(pooledObject, args); + } +} Propchange: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/proxy/CglibProxyHandler.java ------------------------------------------------------------------------------ svn:eol-style = native Added: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/proxy/CglibProxySource.java URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/proxy/CglibProxySource.java?rev=1531846&view=auto ============================================================================== --- commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/proxy/CglibProxySource.java (added) +++ commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/proxy/CglibProxySource.java Mon Oct 14 10:50:28 2013 @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.pool2.proxy; + +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.Factory; + +import org.apache.commons.pool2.UsageTracking; + +public class CglibProxySource<T> implements ProxySource<T> { + + private final Class<? extends T> superclass; + + public CglibProxySource(Class<? extends T> superclass) { + this.superclass = superclass; + } + + + @Override + public T createProxy(T pooledObject, UsageTracking<T> usageTracking) { + Enhancer enhancer = new Enhancer(); + enhancer.setSuperclass(superclass); + + CglibProxyHandler<T> proxyInterceptor = + new CglibProxyHandler<T>(pooledObject, usageTracking); + enhancer.setCallback(proxyInterceptor); + + @SuppressWarnings("unchecked") + T proxy = (T) enhancer.create(); + + return proxy; + } + + + @Override + public T resolveProxy(T proxy) { + @SuppressWarnings("unchecked") + BaseProxyHandler<T> proxyInterceptor = + (BaseProxyHandler<T>) ((Factory) proxy).getCallback(0); + T pooledObject = proxyInterceptor.disableProxy(); + return pooledObject; + } +} Propchange: commons/proper/pool/trunk/src/main/java/org/apache/commons/pool2/proxy/CglibProxySource.java ------------------------------------------------------------------------------ svn:eol-style = native Added: commons/proper/pool/trunk/src/test/java/org/apache/commons/pool2/proxy/TestProxiedObjectPoolWithCglibProxy.java URL: http://svn.apache.org/viewvc/commons/proper/pool/trunk/src/test/java/org/apache/commons/pool2/proxy/TestProxiedObjectPoolWithCglibProxy.java?rev=1531846&view=auto ============================================================================== --- commons/proper/pool/trunk/src/test/java/org/apache/commons/pool2/proxy/TestProxiedObjectPoolWithCglibProxy.java (added) +++ commons/proper/pool/trunk/src/test/java/org/apache/commons/pool2/proxy/TestProxiedObjectPoolWithCglibProxy.java Mon Oct 14 10:50:28 2013 @@ -0,0 +1,150 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.commons.pool2.proxy; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.PrintWriter; +import java.io.StringWriter; + +import org.apache.commons.pool2.BasePooledObjectFactory; +import org.apache.commons.pool2.ObjectPool; +import org.apache.commons.pool2.PooledObjectFactory; +import org.apache.commons.pool2.impl.AbandonedConfig; +import org.apache.commons.pool2.impl.GenericObjectPool; +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; + +import org.junit.Before; +import org.junit.Test; + +public class TestProxiedObjectPoolWithCglibProxy { + + private static final String DATA1 = "data1"; + private static final int ABANDONED_TIMEOUT_SECS = 3; + + private ObjectPool<TestObject> pool; + private StringWriter log; + + @Before + public void setup() { + log = new StringWriter(); + + PrintWriter pw = new PrintWriter(log); + AbandonedConfig abandonedConfig = new AbandonedConfig(); + abandonedConfig.setLogAbandoned(true); + abandonedConfig.setRemoveAbandonedOnBorrow(true); + abandonedConfig.setUseUsageTracking(true); + abandonedConfig.setRemoveAbandonedTimeout(ABANDONED_TIMEOUT_SECS); + abandonedConfig.setLogWriter(pw); + + GenericObjectPoolConfig config = new GenericObjectPoolConfig(); + config.setMaxTotal(3); + + PooledObjectFactory<TestObject> factory = new TestObjectFactory(); + + ObjectPool<TestObject> innerPool = + new GenericObjectPool<TestObject>(factory, config, abandonedConfig); + + ProxySource<TestObject> proxySource = + new CglibProxySource<TestObject>(TestObject.class); + pool = new ProxiedObjectPool<TestObject>(innerPool, proxySource); + } + + + @Test + public void testBorrowObject() throws Exception { + TestObject obj = pool.borrowObject(); + assertNotNull(obj); + + // Make sure proxied methods are working + obj.setData(DATA1); + assertEquals(DATA1, obj.getData()); + + pool.returnObject(obj); + } + + + @Test(expected=IllegalStateException.class) + public void testAccessAfterReturn() throws Exception { + TestObject obj = pool.borrowObject(); + assertNotNull(obj); + + // Make sure proxied methods are working + obj.setData(DATA1); + assertEquals(DATA1, obj.getData()); + + pool.returnObject(obj); + + assertNotNull(obj); + + obj.getData(); + } + + + @Test + public void testUsageTracking() throws Exception { + TestObject obj = pool.borrowObject(); + assertNotNull(obj); + + // Use the object to trigger collection of last used stack trace + obj.setData(DATA1); + + // Sleep long enough for the object to be considered abandoned + Thread.sleep((ABANDONED_TIMEOUT_SECS + 2) * 1000); + + // Borrow another object to trigger the abandoned object processing + pool.borrowObject(); + + String logOutput = log.getBuffer().toString(); + + assertTrue(logOutput.contains("Pooled object created")); + assertTrue(logOutput.contains("The last code to use this object was")); + } + + private static class TestObjectFactory extends + BasePooledObjectFactory<TestObject> { + + @Override + public TestObject create() throws Exception { + return new TestObjectImpl(); + } + } + + + private static interface TestObject { + String getData(); + void setData(String data); + } + + + private static class TestObjectImpl implements TestObject { + + private String data; + + @Override + public String getData() { + return data; + } + + @Override + public void setData(String data) { + this.data = data; + } + } +} Propchange: commons/proper/pool/trunk/src/test/java/org/apache/commons/pool2/proxy/TestProxiedObjectPoolWithCglibProxy.java ------------------------------------------------------------------------------ svn:eol-style = native