Author: fhanik
Date: Fri Apr 16 00:02:53 2010
New Revision: 934651

URL: http://svn.apache.org/viewvc?rev=934651&view=rev
Log:
Add in statement cache

Added:
    
tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestStatementCache.java
   (with props)
Modified:
    
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PooledConnection.java
    
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java
    
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractQueryReport.java
    
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java
    
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java

Modified: 
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PooledConnection.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PooledConnection.java?rev=934651&r1=934650&r2=934651&view=diff
==============================================================================
--- 
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PooledConnection.java
 (original)
+++ 
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PooledConnection.java
 Fri Apr 16 00:02:53 2010
@@ -19,6 +19,7 @@ package org.apache.tomcat.jdbc.pool;
 
 import java.sql.SQLException;
 import java.sql.Statement;
+import java.util.HashMap;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import org.apache.juli.logging.Log;
@@ -106,6 +107,8 @@ public class PooledConnection {
      * The parent
      */
     protected ConnectionPool parent;
+    
+    private HashMap<Object, Object> attributes = new HashMap<Object, Object>();
 
     /**
      * Weak reference to cache the list of interceptors for this connection
@@ -598,5 +601,9 @@ public class PooledConnection {
     public boolean isReleased() {
         return released.get();
     }
+    
+    public HashMap<Object,Object> getAttributes() {
+        return attributes;
+    }
 
 }

Modified: 
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java?rev=934651&r1=934650&r2=934651&view=diff
==============================================================================
--- 
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java
 (original)
+++ 
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java
 Fri Apr 16 00:02:53 2010
@@ -35,7 +35,7 @@ public abstract class  AbstractCreateSta
     protected static final String PREPARE_STATEMENT     = "prepareStatement";
     protected static final int    PREPARE_STATEMENT_IDX = 1;
     protected static final String PREPARE_CALL          = "prepareCall";
-    protected static final int    PREPARE_IDX           = 2;
+    protected static final int    PREPARE_CALL_IDX      = 2;
 
     protected static final String[] STATEMENT_TYPES = {CREATE_STATEMENT, 
PREPARE_STATEMENT, PREPARE_CALL};
     protected static final int    STATEMENT_TYPE_COUNT = 
STATEMENT_TYPES.length;

Modified: 
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractQueryReport.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractQueryReport.java?rev=934651&r1=934650&r2=934651&view=diff
==============================================================================
--- 
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractQueryReport.java
 (original)
+++ 
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractQueryReport.java
 Fri Apr 16 00:02:53 2010
@@ -182,7 +182,7 @@ public abstract class AbstractQueryRepor
             }else if (compare(PREPARE_CALL,name)) {
                 //prepareCall
                 sql = (String)args[0];
-                constructor = 
getConstructor(PREPARE_IDX,CallableStatement.class);
+                constructor = 
getConstructor(PREPARE_CALL_IDX,CallableStatement.class);
                 prepareCall(sql,time);
             }else {
                 //do nothing, might be a future unsupported method

Modified: 
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java?rev=934651&r1=934650&r2=934651&view=diff
==============================================================================
--- 
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java
 (original)
+++ 
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java
 Fri Apr 16 00:02:53 2010
@@ -18,7 +18,6 @@ package org.apache.tomcat.jdbc.pool.inte
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
-import java.sql.CallableStatement;
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
 import java.sql.Statement;
@@ -36,16 +35,37 @@ public class StatementCache extends Stat
     protected static final String[] CALLABLE_TYPE = new String[] 
{PREPARE_CALL}; 
     protected static final String[] PREPARED_TYPE = new String[] 
{PREPARE_STATEMENT}; 
     protected static final String[] NO_TYPE = new String[] {};
+    
+    protected static final String STATEMENT_CACHE_ATTR = 
StatementCache.class.getName() + ".cache";
 
     /*begin properties for the statement cache*/
     private boolean cachePrepared = true;
     private boolean cacheCallable = false;
     private int maxCacheSize = 50;
-    private ConnectionPool parent;
     private PooledConnection pcon;
     private String[] types;
     
     
+    public boolean isCachePrepared() {
+        return cachePrepared;
+    }
+
+    public boolean isCacheCallable() {
+        return cacheCallable;
+    }
+
+    public int getMaxCacheSize() {
+        return maxCacheSize;
+    }
+
+    public String[] getTypes() {
+        return types;
+    }
+
+    public AtomicInteger getCacheSize() {
+        return cacheSize;
+    }
+
     public void setProperties(Map<String, InterceptorProperty> properties) {
         super.setProperties(properties);
         InterceptorProperty p = properties.get("prepared");
@@ -86,35 +106,36 @@ public class StatementCache extends Stat
     
     /*begin the actual statement cache*/
     
-    private static ConcurrentHashMap<PooledConnection, 
ConcurrentHashMap<String,StatementProxy>> statementCache =
-        new ConcurrentHashMap<PooledConnection, 
ConcurrentHashMap<String,StatementProxy>>();
-    
-    
     public void reset(ConnectionPool parent, PooledConnection con) {
         super.reset(parent, con);
         if (parent==null) {
             cacheSize = null;
-            this.parent = null;
             this.pcon = null;
         } else {
             cacheSize = cacheSizeMap.get(parent);
-            this.parent = parent;
             this.pcon = con;
+            if (!pcon.getAttributes().containsKey(STATEMENT_CACHE_ATTR)) {
+                ConcurrentHashMap<String,CachedStatement> cache = new 
ConcurrentHashMap<String, CachedStatement>();
+                pcon.getAttributes().put(STATEMENT_CACHE_ATTR,cache);
+            }
         }
     }
 
     public void disconnected(ConnectionPool parent, PooledConnection con, 
boolean finalizing) {
-        ConcurrentHashMap<String,StatementProxy> statements = 
statementCache.get(con);
+        ConcurrentHashMap<String,CachedStatement> statements = 
+            
(ConcurrentHashMap<String,CachedStatement>)con.getAttributes().get(STATEMENT_CACHE_ATTR);
+        
         if (statements!=null) {
-            for (Map.Entry<String, StatementProxy> p : statements.entrySet()) {
+            for (Map.Entry<String, CachedStatement> p : statements.entrySet()) 
{
                 closeStatement(p.getValue());
             }
             statements.clear();
         }
+        
         super.disconnected(parent, con, finalizing);
     }
     
-    public void closeStatement(StatementProxy st) {
+    public void closeStatement(CachedStatement st) {
         try {
             if (st==null) return;
             if (((PreparedStatement)st).isClosed()) return;
@@ -125,39 +146,59 @@ public class StatementCache extends Stat
         }
     }
     
+    @Override
+    protected Object createDecorator(Object proxy, Method method, Object[] 
args, 
+                                     Object statement, Constructor<?> 
constructor, String sql) 
+    throws InstantiationException, IllegalAccessException, 
InvocationTargetException {
+        boolean process = process(this.types, method, false);
+        if (process) {
+            Object result = null;
+            CachedStatement statementProxy = new 
CachedStatement((Statement)statement,sql);
+            result = constructor.newInstance(new Object[] { statementProxy });
+            statementProxy.setActualProxy(result);
+            statementProxy.setConnection(proxy);
+            statementProxy.setConstructor(constructor);
+            return result;
+        } else {
+            return super.createDecorator(proxy, method, args, statement, 
constructor, sql);
+        }
+    }
+
+    
     
     public Object invoke(Object proxy, Method method, Object[] args) throws 
Throwable {
         if (compare(CLOSE_VAL,method)) {
             return super.invoke(proxy, method, args);
         } else {
-            boolean process = false;
-            process = process(this.types, method, process);
-            
-            if (process) {
-                //check the cache
-                //if (isCached) {
-                    
-                //} else {
+            boolean process = process(this.types, method, false);
+            if (process && args.length>0 && args[0] instanceof String) {
+                CachedStatement statement = isCached((String)args[0]);
+                if (statement!=null) {
+                    //remove it from the cache since it is used
+                    removeStatement(statement);
+                    return statement.getActualProxy();
+                } else {
                     return super.invoke(proxy, method, args);
-                //}
+                }
             } else {
                 return super.invoke(proxy,method,args);
             }
         }
     }
     
-    public boolean isCached(String sql) {
-        ConcurrentHashMap<String,StatementProxy> cache = 
statementCache.get(pcon);
-        return cache.containsKey(sql);
+    public CachedStatement isCached(String sql) {
+        ConcurrentHashMap<String,CachedStatement> cache = 
+            
(ConcurrentHashMap<String,CachedStatement>)pcon.getAttributes().get(STATEMENT_CACHE_ATTR);
+        return cache.get(sql);
     }
     
-    public boolean cacheStatement(StatementProxy proxy) {
-        ConcurrentHashMap<String,StatementProxy> cache = 
statementCache.get(pcon); 
+    public boolean cacheStatement(CachedStatement proxy) {
+        ConcurrentHashMap<String,CachedStatement> cache = 
+            
(ConcurrentHashMap<String,CachedStatement>)pcon.getAttributes().get(STATEMENT_CACHE_ATTR);
         if (proxy.getSql()==null) {
             return false;
         } else if (cache.containsKey(proxy.getSql())) {
-            cache.put(proxy.getSql(), proxy);
-            return true;
+            return false;
         } else if (cacheSize.get()>=maxCacheSize) {
             return false;
         } else if (cacheSize.incrementAndGet()>maxCacheSize) {
@@ -165,26 +206,55 @@ public class StatementCache extends Stat
             return false;
         } else {
             //cache the statement
+            cache.put(proxy.getSql(), proxy);
             return true;
         }
     }
+
+    public boolean removeStatement(CachedStatement proxy) {
+        ConcurrentHashMap<String,CachedStatement> cache = 
+            
(ConcurrentHashMap<String,CachedStatement>)pcon.getAttributes().get(STATEMENT_CACHE_ATTR);
+        if (cache.remove(proxy.getSql()) != null) {
+            cacheSize.decrementAndGet();
+            return true;
+        } else {
+            return false;
+        }
+    }
     /*end the actual statement cache*/
 
     
-    protected class StatementProxy extends 
StatementDecoratorInterceptor.StatementProxy {
+    protected class CachedStatement extends 
StatementDecoratorInterceptor.StatementProxy<Statement> {
         boolean cached = false;
-        public StatementProxy(Object parent, String sql) {
+        public CachedStatement(Statement parent, String sql) {
             super(parent, sql);
-            cached = cacheStatement(this);
         }
-
-        public void closeInvoked() {
-            super.closedInvoked();
-            if (cached) {
+        
+        @Override
+        public void closedInvoked() {
+            //should we cache it
+            boolean shouldClose = true;
+            if (cacheSize.get() < maxCacheSize) {
                 //cache a proxy so that we don't reuse the facade
-                StatementProxy proxy = new 
StatementProxy(getDelegate(),getSql());
-                proxy.setActualProxy(getActualProxy());
-                proxy.setConnection(getConnection());
+                CachedStatement proxy = new 
CachedStatement(getDelegate(),getSql());
+                try {
+                    //create a new facade
+                    Object actualProxy = getConstructor().newInstance(new 
Object[] { proxy });
+                    proxy.setActualProxy(actualProxy);
+                    proxy.setConnection(getConnection());
+                    proxy.setConstructor(getConstructor());
+                    if (cacheStatement(proxy)) {
+                        proxy.cached = true;
+                        shouldClose = false;
+                    }
+                } catch (Exception x) {
+                    removeStatement(proxy);
+                }
+            } 
+            closed = true;
+            delegate = null;
+            if (shouldClose) {
+                super.closedInvoked();
             }
            
         }
@@ -194,53 +264,6 @@ public class StatementCache extends Stat
             ((Statement)getDelegate()).close();
         }
         
-        public Object invoke(Object proxy, Method method, Object[] args) 
throws Throwable {
-            // get the name of the method for comparison
-            final String name = method.getName();
-            // was close invoked?
-            boolean close = compare(JdbcInterceptor.CLOSE_VAL, name);
-            // allow close to be called multiple times
-            if (close && closed)
-                return null;
-            // are we calling isClosed?
-            if (compare(JdbcInterceptor.ISCLOSED_VAL, name))
-                return Boolean.valueOf(closed);
-            // if we are calling anything else, bail out
-            if (closed)
-                throw new SQLException("Statement closed.");
-            if (name.equals("getConnection")){
-                return getConnection();
-            }
-            boolean process = isExecuteQuery(method);
-            // check to see if we are about to execute a query
-            // if we are executing, get the current time
-            Object result = null;
-            try {
-                if (cached && close) {
-                    //dont invoke actual close
-                } else {
-                    // execute the query
-                    result = method.invoke(delegate, args);
-                }
-            } catch (Throwable t) {
-                if (t instanceof InvocationTargetException) {
-                    InvocationTargetException it = (InvocationTargetException) 
t;
-                    throw it.getCause() != null ? it.getCause() : it;
-                } else {
-                    throw t;
-                }
-            }
-            // perform close cleanup
-            if (close) {
-                closeInvoked();
-            }
-            if (process){
-                Constructor<?> cons = getResultSetConstructor();
-                result = cons.newInstance(new Object[]{new 
ResultSetProxy(getActualProxy(), result)});
-            }
-            return result;
-        }
-        
     }
     
 }

Modified: 
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java?rev=934651&r1=934650&r2=934651&view=diff
==============================================================================
--- 
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java
 (original)
+++ 
tomcat/trunk/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java
 Fri Apr 16 00:02:53 2010
@@ -94,7 +94,6 @@ public class StatementDecoratorIntercept
     @Override
     public Object createStatement(Object proxy, Method method, Object[] args, 
Object statement, long time) {
         try {
-            Object result = null;
             String name = method.getName();
             Constructor<?> constructor = null;
             String sql = null;
@@ -107,24 +106,32 @@ public class StatementDecoratorIntercept
                 sql = (String)args[0];
             } else if (compare(PREPARE_CALL, name)) {
                 // prepareCall
-                constructor = getConstructor(PREPARE_IDX, 
CallableStatement.class);
+                constructor = getConstructor(PREPARE_CALL_IDX, 
CallableStatement.class);
                 sql = (String)args[0];
             } else {
                 // do nothing, might be a future unsupported method
                 // so we better bail out and let the system continue
                 return statement;
             }
-            StatementProxy statementProxy = new StatementProxy(statement,sql);
-            result = constructor.newInstance(new Object[] { statementProxy });
-            statementProxy.setActualProxy(result);
-            statementProxy.setConnection(proxy);
-            return result;
+            return createDecorator(proxy, method, args, statement, 
constructor, sql);
         } catch (Exception x) {
             logger.warn("Unable to create statement proxy for slow query 
report.", x);
         }
         return statement;
     }
 
+    protected Object createDecorator(Object proxy, Method method, Object[] 
args, 
+                                     Object statement, Constructor<?> 
constructor, String sql) 
+    throws InstantiationException, IllegalAccessException, 
InvocationTargetException {
+        Object result = null;
+        StatementProxy statementProxy = new 
StatementProxy<Statement>((Statement)statement,sql);
+        result = constructor.newInstance(new Object[] { statementProxy });
+        statementProxy.setActualProxy(result);
+        statementProxy.setConnection(proxy);
+        statementProxy.setConnection(constructor);
+        return result;
+    }
+
     protected boolean isExecuteQuery(String methodName) {
         return EXECUTE_QUERY_TYPES[0].equals(methodName);
     }
@@ -139,19 +146,20 @@ public class StatementDecoratorIntercept
      * @author fhanik
      * 
      */
-    protected class StatementProxy implements InvocationHandler {
+    protected class StatementProxy<T extends java.sql.Statement> implements 
InvocationHandler {
         
         protected boolean closed = false;
-        protected Object delegate;
+        protected T delegate;
         private Object actualProxy;
         private Object connection;
         private String sql;
+        private Constructor constructor;
 
-        public StatementProxy(Object parent, String sql) {
-            this.delegate = parent;
+        public StatementProxy(T delegate, String sql) {
+            this.delegate = delegate;
             this.sql = sql;
         }
-        public Object getDelegate() {
+        public T getDelegate() {
             return this.delegate;
         }
         
@@ -173,26 +181,40 @@ public class StatementDecoratorIntercept
             return this.actualProxy;
         }
         
+        
+        public Constructor getConstructor() {
+            return constructor;
+        }
+        public void setConstructor(Constructor constructor) {
+            this.constructor = constructor;
+        }
         public void closedInvoked() {
+            if (getDelegate()!=null) {
+                try {
+                    getDelegate().close();
+                }catch (SQLException ignore) {
+                }
+            }
             closed = true;
             delegate = null;
         }
         
         public Object invoke(Object proxy, Method method, Object[] args) 
throws Throwable {
-            // get the name of the method for comparison
-            final String name = method.getName();
+            if (compare(TOSTRING_VAL,method)) {
+                return toString();
+            }
             // was close invoked?
-            boolean close = compare(JdbcInterceptor.CLOSE_VAL, name);
+            boolean close = compare(CLOSE_VAL, method);
             // allow close to be called multiple times
             if (close && closed)
                 return null;
             // are we calling isClosed?
-            if (compare(JdbcInterceptor.ISCLOSED_VAL, name))
+            if (compare(ISCLOSED_VAL, method))
                 return Boolean.valueOf(closed);
             // if we are calling anything else, bail out
             if (closed)
                 throw new SQLException("Statement closed.");
-            if (name.equals("getConnection")){
+            if (compare(GETCONNECTION_VAL,method)){
                 return connection;
             }
             boolean process = isExecuteQuery(method);
@@ -200,8 +222,13 @@ public class StatementDecoratorIntercept
             // if we are executing, get the current time
             Object result = null;
             try {
-                // execute the query
-                result = method.invoke(delegate, args);
+                // perform close cleanup
+                if (close) {
+                    closedInvoked();
+                } else {
+                    // execute the query
+                    result = method.invoke(delegate, args);
+                }
             } catch (Throwable t) {
                 if (t instanceof InvocationTargetException) {
                     InvocationTargetException it = (InvocationTargetException) 
t;
@@ -210,16 +237,26 @@ public class StatementDecoratorIntercept
                     throw t;
                 }
             }
-            // perform close cleanup
-            if (close) {
-                closeInvoked();
-            }
             if (process){
                 Constructor<?> cons = getResultSetConstructor();
                 result = cons.newInstance(new Object[]{new 
ResultSetProxy(actualProxy, result)});
             }
             return result;
         }
+        
+        public String toString() {
+            StringBuffer buf = new 
StringBuffer(StatementProxy.class.getName());
+            buf.append("[Proxy=");
+            buf.append(System.identityHashCode(this));
+            buf.append("; Sql=");
+            buf.append(getSql());
+            buf.append("; Delegate=");
+            buf.append(getDelegate());
+            buf.append("; Connection=");
+            buf.append(getConnection());
+            buf.append("]");
+            return buf.toString();
+        }
     }
 
     protected class ResultSetProxy implements InvocationHandler {

Added: 
tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestStatementCache.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestStatementCache.java?rev=934651&view=auto
==============================================================================
--- 
tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestStatementCache.java
 (added)
+++ 
tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestStatementCache.java
 Fri Apr 16 00:02:53 2010
@@ -0,0 +1,135 @@
+/*
+ * 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.tomcat.jdbc.test;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+
+import org.apache.tomcat.jdbc.pool.interceptor.StatementCache;
+
+public class TestStatementCache extends DefaultTestCase {
+
+    
+    public TestStatementCache(String name) {
+        super(name);
+    }
+    
+    private static volatile TestStatementCacheInterceptor interceptor = null;
+    
+    
+    @Override
+    protected void tearDown() throws Exception {
+        // TODO Auto-generated method stub
+        this.interceptor = null;
+        super.tearDown();
+    }
+
+
+
+
+    private void config(boolean cachePrepared, boolean cacheCallable, int max) 
{
+        
datasource.getPoolProperties().setJdbcInterceptors(TestStatementCacheInterceptor.class.getName()+
+                
"(prepared="+cachePrepared+",callable="+cacheCallable+",max="+max+")");
+    }
+    
+    public void testIsCacheEnabled() throws Exception {
+        init();
+        config(true,true,50);
+        datasource.getConnection().close();
+        assertNotNull("Interceptor was not created.", interceptor);
+    }
+    
+    public void testCacheProperties() throws Exception {
+        init();
+        config(true,true,50);
+        datasource.getConnection().close();
+        assertEquals(true, interceptor.isCacheCallable());
+        assertEquals(true, interceptor.isCachePrepared());
+        assertEquals(50,interceptor.getMaxCacheSize());
+    }
+    
+    public void testCacheProperties2() throws Exception {
+        init();
+        config(false,false,100);
+        datasource.getConnection().close();
+        assertEquals(false, interceptor.isCacheCallable());
+        assertEquals(false, interceptor.isCachePrepared());
+        assertEquals(100,interceptor.getMaxCacheSize());
+    }
+
+    public void testPreparedStatementCache() throws Exception {
+        init();
+        config(true,false,100);
+        Connection con = datasource.getConnection();
+        PreparedStatement ps1 = con.prepareStatement("select 1");
+        PreparedStatement ps2 = con.prepareStatement("select 1");
+        assertEquals(0,interceptor.getCacheSize().get());
+        ps1.close();
+        assertTrue(ps1.isClosed());
+        assertEquals(1,interceptor.getCacheSize().get());
+        PreparedStatement ps3 = con.prepareStatement("select 1");
+        assertEquals(0,interceptor.getCacheSize().get());
+        ps2.close();
+        assertTrue(ps2.isClosed());
+        ps3.close();
+        assertTrue(ps3.isClosed());
+        assertEquals(1,interceptor.getCacheSize().get());
+    }
+
+    public void testPreparedStatementCache2() throws Exception {
+        init();
+        config(false,false,100);
+        Connection con = datasource.getConnection();
+        PreparedStatement ps1 = con.prepareStatement("select 1");
+        PreparedStatement ps2 = con.prepareStatement("select 1");
+        assertEquals(0,interceptor.getCacheSize().get());
+        ps1.close();
+        assertTrue(ps1.isClosed());
+        assertEquals(0,interceptor.getCacheSize().get());
+        PreparedStatement ps3 = con.prepareStatement("select 1");
+        assertEquals(0,interceptor.getCacheSize().get());
+        ps2.close();
+        assertTrue(ps2.isClosed());
+        ps3.close();
+        assertTrue(ps3.isClosed());
+        assertEquals(0,interceptor.getCacheSize().get());
+    }
+
+    public void testCallableStatementCache() throws Exception {
+    }
+
+    public void testMaxCacheSize() throws Exception {
+        init();
+        config(true,false,100);
+        Connection con1 = datasource.getConnection();
+        Connection con2 = datasource.getConnection();
+        for (int i=0; i<120; i++) {
+            Connection con = (i%2==0)?con1:con2;
+            PreparedStatement ps = con.prepareStatement("select "+i);
+            ps.close();
+        }
+        assertEquals(100,interceptor.getCacheSize().get());
+    }
+
+    
+    public static class TestStatementCacheInterceptor extends StatementCache {
+        public TestStatementCacheInterceptor() {
+            TestStatementCache.interceptor = this;
+        }
+    }
+
+}

Propchange: 
tomcat/trunk/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestStatementCache.java
------------------------------------------------------------------------------
    svn:eol-style = native



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to