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


Reply via email to