Add in ability to build with Maven
authorfhanik <fhanik@13f79535-47bb-0310-9956-ffa450edef68>
Wed, 30 Mar 2011 21:40:59 +0000 (21:40 +0000)
committerfhanik <fhanik@13f79535-47bb-0310-9956-ffa450edef68>
Wed, 30 Mar 2011 21:40:59 +0000 (21:40 +0000)
git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1087090 13f79535-47bb-0310-9956-ffa450edef68

131 files changed:
modules/jdbc-pool/.classpath
modules/jdbc-pool/build.xml
modules/jdbc-pool/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSource.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/FairBlockingQueue.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/JdbcInterceptor.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/MultiLockFairBlockingQueue.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolConfiguration.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolUtilities.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PooledConnection.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ProxyConnection.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/Validator.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/XADataSource.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractQueryReport.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/ConnectionState.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/ResetAbandonedTimer.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmxMBean.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementFinalizer.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/mbeans-descriptors.xml [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPoolMBean.java [deleted file]
modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/mbeans-descriptors.xml [deleted file]
modules/jdbc-pool/pom.xml [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSource.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/FairBlockingQueue.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/JdbcInterceptor.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/MultiLockFairBlockingQueue.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolConfiguration.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolUtilities.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PooledConnection.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ProxyConnection.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/Validator.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/XADataSource.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractQueryReport.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ConnectionState.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ResetAbandonedTimer.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmxMBean.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementFinalizer.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/mbeans-descriptors.xml [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPoolMBean.java [new file with mode: 0644]
modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/mbeans-descriptors.xml [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestInterceptor.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/AbandonPercentageTest.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/AlternateUsernameTest.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/Async0IdleTestBug50477.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/BorrowWaitTest.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/Bug50571.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/Bug50805.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/CheckOutThreadTest.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/ConnectCountTest.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/CreateTestTable.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/DefaultProperties.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/DefaultTestCase.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/FairnessTest.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/JmxPasswordTest.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/SimplePOJOAsyncExample.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/SimplePOJOExample.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/StarvationTest.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/StatementFinalizerTest.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestAsyncQueue.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestConcurrency.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestConnectionState.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestException.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestGCClose.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestGetConnection.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestInterceptorShortName.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestSizePreservation.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestSlowQueryReport.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestStatementCache.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestSuspectTimeout.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestTimeout.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TwoDataSources.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/driver/Connection.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/driver/Driver.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/driver/ResultSet.java [new file with mode: 0644]
modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/driver/Statement.java [new file with mode: 0644]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/pool/interceptor/TestInterceptor.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/AbandonPercentageTest.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/AlternateUsernameTest.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/Async0IdleTestBug50477.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/BorrowWaitTest.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/Bug50571.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/Bug50805.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/CheckOutThreadTest.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/ConnectCountTest.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/CreateTestTable.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/DefaultProperties.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/DefaultTestCase.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/FairnessTest.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/JmxPasswordTest.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/SimplePOJOAsyncExample.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/SimplePOJOExample.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/StarvationTest.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/StatementFinalizerTest.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestAsyncQueue.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestConcurrency.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestConnectionState.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestException.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestGCClose.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestGetConnection.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestInterceptorShortName.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestSizePreservation.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestSlowQueryReport.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestStatementCache.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestSuspectTimeout.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestTimeout.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TwoDataSources.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/driver/Connection.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/driver/Driver.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/driver/ResultSet.java [deleted file]
modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/driver/Statement.java [deleted file]

index 180fbc7..1a23a7e 100644 (file)
@@ -6,6 +6,6 @@
        <classpathentry kind="var" path="TOMCAT_LIBS_BASE/tomcat7-deps/dbcp/tomcat-dbcp.jar" sourcepath="/TOMCAT_LIBS_BASE/tomcat6-deps/dbcp/src/java"/>
        <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
        <classpathentry kind="lib" path="includes/h2/bin/h2-1.2.129.jar"/>
-       <classpathentry combineaccessrules="false" kind="src" path="/tomcat-trunk"/>
+       <classpathentry combineaccessrules="false" kind="src" path="/tomcat-7.0.x"/>
        <classpathentry kind="output" path="bin"/>
 </classpath>
index 389b910..6cd65f2 100644 (file)
   <target name="javadoc" depends="prepare">
   
      <xslt basedir="${tomcat.pool}/doc"
-          destdir="${basedir}/java/org/apache/tomcat/jdbc/pool"
+          destdir="${basedir}/src/main/java/org/apache/tomcat/jdbc/pool"
           extension=".html"
           style="${basedir}/doc/package.xsl"
           excludes="build.xml"
       <param name="relative-path" expression="http://tomcat.apache.org/tomcat-6.0-doc"/>
       <param name="apache-logo" expression="/images/asf-logo.gif"/>
     </xslt>
-    <move tofile="${basedir}/java/org/apache/tomcat/jdbc/pool/package.html"
-          file="${basedir}/java/org/apache/tomcat/jdbc/pool/jdbc-pool.html"/>
-    <javadoc sourcepath="${basedir}/java" destdir="${tomcat.api}" verbose="false"
+    <move tofile="${basedir}/src/main/java/org/apache/tomcat/jdbc/pool/package.html"
+          file="${basedir}/src/main/java/org/apache/tomcat/jdbc/pool/jdbc-pool.html"/>
+    <javadoc sourcepath="${basedir}/src/main/java" destdir="${tomcat.api}" verbose="false"
              link="http://java.sun.com/javase/6/docs/api/">
       <classpath refid="tomcat.jdbc.classpath"/>
     </javadoc>
       <fileset dir="${tomcat.api}"/>
       <fileset refid="license.notice"/>
     </jar>
-    <delete file="${basedir}/java/org/apache/tomcat/jdbc/pool/package.html"/>
+    <delete file="${basedir}/src/main/java/org/apache/tomcat/jdbc/pool/package.html"/>
   </target>
   
   <target name="build" depends="prepare,download">
     <mkdir dir="${tomcat.pool}"/>
     <!-- compile org.apache.tomcat.jdbc-->
-    <javac srcdir="${basedir}/java" destdir="${tomcat.classes}"
+    <javac srcdir="${basedir}/src/main/java" destdir="${tomcat.classes}"
            debug="${compile.debug}"
            deprecation="${compile.deprecation}"
            source="${compile.source}"
       <fileset dir="${tomcat.classes}">
         <include name="org/apache/tomcat/jdbc/**" />
       </fileset>
-      <fileset dir="${basedir}/java">
+      <fileset dir="${basedir}/src/main/java">
         <include name="org/apache/tomcat/jdbc/**/*.xml" />
       </fileset>
       <fileset refid="license.notice"/>
 
     <!-- connection pool source file-->
     <jar jarfile="${tomcat-jdbc-src.jar}" update="true">
-      <fileset dir="${basedir}/java">
+      <fileset dir="${basedir}/src/main/java">
         <include name="org/apache/tomcat/jdbc/**" />
       </fileset>
       <fileset refid="license.notice"/>
   <target name="build-test" depends="prepare, build, download-test">
     <mkdir dir="${tomcat.pool}"/>
     <!-- compile org.apache.tomcat.jdbc-->
-    <javac srcdir="${basedir}/test" destdir="${tomcat.testclasses}"
+    <javac srcdir="${basedir}/src/test/java" destdir="${tomcat.testclasses}"
            debug="${compile.debug}"
            deprecation="${compile.deprecation}"
            source="${compile.source}"
       <fileset dir="${tomcat.testclasses}">
         <include name="org/apache/tomcat/jdbc/**" />
       </fileset>
-      <fileset dir="${basedir}/test">
+      <fileset dir="${basedir}/src/test/java">
         <include name="org/apache/tomcat/jdbc/**/*.xml" />
       </fileset>
       <fileset refid="license.notice"/>
     </jar>
     <jar jarfile="${tomcat-jdbc-test-src.jar}" update="true">
-      <fileset dir="${basedir}/test">
+      <fileset dir="${basedir}/src/test/java">
         <include name="org/apache/tomcat/jdbc/**" />
       </fileset>
       <fileset refid="license.notice"/>
       <classpath refid="tomcat.jdbc.classpath"/>
       <classpath refid="test.classpath"/>
       <batchtest fork="yes" todir="${tomcat.testclasses}">
-        <fileset dir="${basedir}/test">
+        <fileset dir="${basedir}/src/test/java">
           <include name="**/CreateTestTable*"/>
         </fileset>
       </batchtest>
       <classpath refid="tomcat.jdbc.classpath"/>
       <classpath refid="test.classpath"/>
       <batchtest fork="yes" todir="${tomcat.testclasses}">
-        <fileset dir="${basedir}/test">
+        <fileset dir="${basedir}/src/test/java">
           <include name="org/apache/tomcat/jdbc/test/*CheckOutThreadTest*.java"/>
           <include name="org/apache/tomcat/jdbc/test/FairnessTest*.java"/>
           <exclude name="**/CreateTestTable*"/>
       <classpath refid="tomcat.jdbc.classpath"/>
       <classpath refid="test.classpath"/>
       <batchtest fork="yes" todir="${tomcat.testclasses}">
-        <fileset dir="${basedir}/test">
+        <fileset dir="${basedir}/src/test/java">
           <include name="org/apache/tomcat/jdbc/test/*Test*.java"/>
           <exclude name="org/apache/tomcat/jdbc/test/*CheckOutThreadTest*.java"/>
           <exclude name="**/CreateTestTable*"/>
       <classpath refid="tomcat.jdbc.classpath"/>
       <classpath refid="test.classpath"/>
       <batchtest fork="yes" todir="${tomcat.testclasses}">
-        <fileset dir="${basedir}/test">
+        <fileset dir="${basedir}/src/test/java">
           <include name="org/apache/tomcat/jdbc/test/*${test}*.java"/>
           <exclude name="**/CreateTestTable*"/>
           <exclude name="**/DefaultTestCase*"/>
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java
deleted file mode 100644 (file)
index 5fd7007..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * 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.naming;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.Enumeration;
-import java.util.Hashtable;
-
-import javax.naming.Context;
-import javax.naming.Name;
-import javax.naming.RefAddr;
-import javax.naming.Reference;
-import javax.naming.spi.ObjectFactory;
-
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-/**
- * Simple way of configuring generic resources by using reflection.
- * Example usage:
- * <pre><code>
- * &lt;Resource factory=&quot;org.apache.tomcat.jdbc.naming.GenericNamingResourcesFactory&quot;
- *              name=&quot;jdbc/test&quot;
- *              type=&quot;org.apache.derby.jdbc.ClientXADataSource&quot;
- *              databaseName=&quot;sample&quot;
- *              createDatabase=&quot;create&quot;
- *              serverName=&quot;localhost&quot;
- *              port=&quot;1527&quot;/&gt;
- * </code></pre>
- * 
- */
-public class GenericNamingResourcesFactory implements ObjectFactory {
-    private static final Log log = LogFactory.getLog(GenericNamingResourcesFactory.class);
-    
-    public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
-        if ((obj == null) || !(obj instanceof Reference)) {
-            return null;
-        }
-        Reference ref = (Reference) obj;
-        Enumeration<RefAddr> refs = ref.getAll();
-        
-        String type = ref.getClassName();
-        Object o = Class.forName(type).newInstance();
-        
-        while (refs.hasMoreElements()) {
-            RefAddr addr = refs.nextElement();
-            String param = addr.getType();
-            String value = null;
-            if (addr.getContent()!=null) {
-                value = addr.getContent().toString();
-            }
-            if (setProperty(o, param, value,false)) {
-                
-            } else {
-                log.debug("Property not configured["+param+"]. No setter found on["+o+"].");
-            }
-        }
-        return o;
-    }
-
-    public static boolean setProperty(Object o, String name, String value,boolean invokeSetProperty) {
-        if (log.isDebugEnabled())
-            log.debug("IntrospectionUtils: setProperty(" +
-                    o.getClass() + " " + name + "=" + value + ")");
-
-        String setter = "set" + capitalize(name);
-
-        try {
-            Method methods[] = o.getClass().getMethods();
-            Method setPropertyMethodVoid = null;
-            Method setPropertyMethodBool = null;
-
-            // First, the ideal case - a setFoo( String ) method
-            for (int i = 0; i < methods.length; i++) {
-                Class<?> paramT[] = methods[i].getParameterTypes();
-                if (setter.equals(methods[i].getName()) && paramT.length == 1
-                        && "java.lang.String".equals(paramT[0].getName())) {
-
-                    methods[i].invoke(o, new Object[] { value });
-                    return true;
-                }
-            }
-
-            // Try a setFoo ( int ) or ( boolean )
-            for (int i = 0; i < methods.length; i++) {
-                boolean ok = true;
-                if (setter.equals(methods[i].getName())
-                        && methods[i].getParameterTypes().length == 1) {
-
-                    // match - find the type and invoke it
-                    Class<?> paramType = methods[i].getParameterTypes()[0];
-                    Object params[] = new Object[1];
-
-                    // Try a setFoo ( int )
-                    if ("java.lang.Integer".equals(paramType.getName())
-                            || "int".equals(paramType.getName())) {
-                        try {
-                            params[0] = new Integer(value);
-                        } catch (NumberFormatException ex) {
-                            ok = false;
-                        }
-                    // Try a setFoo ( long )
-                    }else if ("java.lang.Long".equals(paramType.getName())
-                                || "long".equals(paramType.getName())) {
-                            try {
-                                params[0] = new Long(value);
-                            } catch (NumberFormatException ex) {
-                                ok = false;
-                            }
-
-                        // Try a setFoo ( boolean )
-                    } else if ("java.lang.Boolean".equals(paramType.getName())
-                            || "boolean".equals(paramType.getName())) {
-                        params[0] = new Boolean(value);
-
-                        // Try a setFoo ( InetAddress )
-                    } else if ("java.net.InetAddress".equals(paramType
-                            .getName())) {
-                        try {
-                            params[0] = InetAddress.getByName(value);
-                        } catch (UnknownHostException exc) {
-                            if (log.isDebugEnabled())
-                                log.debug("IntrospectionUtils: Unable to resolve host name:" + value);
-                            ok = false;
-                        }
-
-                        // Unknown type
-                    } else {
-                        if (log.isDebugEnabled())
-                            log.debug("IntrospectionUtils: Unknown type " +
-                                    paramType.getName());
-                    }
-
-                    if (ok) {
-                        methods[i].invoke(o, params);
-                        return true;
-                    }
-                }
-
-                // save "setProperty" for later
-                if ("setProperty".equals(methods[i].getName())) {
-                    if (methods[i].getReturnType()==Boolean.TYPE){
-                        setPropertyMethodBool = methods[i];
-                    }else {
-                        setPropertyMethodVoid = methods[i];    
-                    }
-                    
-                }
-            }
-
-            // Ok, no setXXX found, try a setProperty("name", "value")
-            if (setPropertyMethodBool != null || setPropertyMethodVoid != null) {
-                Object params[] = new Object[2];
-                params[0] = name;
-                params[1] = value;
-                if (setPropertyMethodBool != null) {
-                    try {
-                        return (Boolean) setPropertyMethodBool.invoke(o, params);
-                    }catch (IllegalArgumentException biae) {
-                        //the boolean method had the wrong
-                        //parameter types. lets try the other
-                        if (setPropertyMethodVoid!=null) {
-                            setPropertyMethodVoid.invoke(o, params);
-                            return true;
-                        }else {
-                            throw biae;
-                        }
-                    }
-                } else {
-                    setPropertyMethodVoid.invoke(o, params);
-                    return true;
-                }
-            }
-
-        } catch (IllegalArgumentException ex2) {
-            log.warn("IAE " + o + " " + name + " " + value, ex2);
-        } catch (SecurityException ex1) {
-            if (log.isDebugEnabled())
-                log.debug("IntrospectionUtils: SecurityException for " +
-                        o.getClass() + " " + name + "=" + value + ")", ex1);
-        } catch (IllegalAccessException iae) {
-            if (log.isDebugEnabled())
-                log.debug("IntrospectionUtils: IllegalAccessException for " +
-                        o.getClass() + " " + name + "=" + value + ")", iae);
-        } catch (InvocationTargetException ie) {
-            if (log.isDebugEnabled())
-                log.debug("IntrospectionUtils: InvocationTargetException for " +
-                        o.getClass() + " " + name + "=" + value + ")", ie);
-        }
-        return false;
-    } 
-    
-    public static String capitalize(String name) {
-        if (name == null || name.length() == 0) {
-            return name;
-        }
-        char chars[] = name.toCharArray();
-        chars[0] = Character.toUpperCase(chars[0]);
-        return new String(chars);
-    }
-
-}
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java
deleted file mode 100644 (file)
index 0faccfe..0000000
+++ /dev/null
@@ -1,1201 +0,0 @@
-/*
- * 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.pool;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Proxy;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.util.ConcurrentModificationException;
-import java.util.Iterator;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-
-/**
- * Implementation of simple connection pool.
- * The ConnectionPool uses a {@link PoolProperties} object for storing all the meta information about the connection pool.
- * As the underlying implementation, the connection pool uses {@link java.util.concurrent.BlockingQueue} to store active and idle connections.
- * A custom implementation of a fair {@link FairBlockingQueue} blocking queue is provided with the connection pool itself. 
- * @author Filip Hanik
- * @version 1.0
- */
-
-public class ConnectionPool {
-    /**
-     * Prefix type for JMX registration
-     */
-    public static final String POOL_JMX_TYPE_PREFIX = "tomcat.jdbc:type=";
-    
-    /**
-     * Logger
-     */
-    private static final Log log = LogFactory.getLog(ConnectionPool.class);
-
-    //===============================================================================
-    //         INSTANCE/QUICK ACCESS VARIABLE
-    //===============================================================================
-    /**
-     * Carries the size of the pool, instead of relying on a queue implementation
-     * that usually iterates over to get an exact count
-     */
-    private AtomicInteger size = new AtomicInteger(0);
-
-    /**
-     * All the information about the connection pool
-     * These are the properties the pool got instantiated with
-     */
-    private PoolConfiguration poolProperties;
-
-    /**
-     * Contains all the connections that are in use
-     * TODO - this shouldn't be a blocking queue, simply a list to hold our objects
-     */
-    private BlockingQueue<PooledConnection> busy;
-
-    /**
-     * Contains all the idle connections
-     */
-    private BlockingQueue<PooledConnection> idle;
-
-    /**
-     * The thread that is responsible for checking abandoned and idle threads
-     */
-    private volatile PoolCleaner poolCleaner;
-
-    /**
-     * Pool closed flag
-     */
-    private volatile boolean closed = false;
-
-    /**
-     * Since newProxyInstance performs the same operation, over and over
-     * again, it is much more optimized if we simply store the constructor ourselves.
-     */
-    private Constructor<?> proxyClassConstructor;
-
-    /**
-     * Executor service used to cancel Futures
-     */
-    private ThreadPoolExecutor cancellator = new ThreadPoolExecutor(0,1,1000,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
-    
-    /**
-     * reference to the JMX mbean
-     */
-    protected org.apache.tomcat.jdbc.pool.jmx.ConnectionPool jmxPool = null;
-    
-    /**
-     * counter to track how many threads are waiting for a connection
-     */
-    private AtomicInteger waitcount = new AtomicInteger(0);
-    
-    //===============================================================================
-    //         PUBLIC METHODS
-    //===============================================================================
-
-    /**
-     * Instantiate a connection pool. This will create connections if initialSize is larger than 0.
-     * The {@link PoolProperties} should not be reused for another connection pool.
-     * @param prop PoolProperties - all the properties for this connection pool
-     * @throws SQLException
-     */
-    public ConnectionPool(PoolConfiguration prop) throws SQLException {
-        //setup quick access variables and pools
-        init(prop);
-    }
-
-
-    /**
-     * Retrieves a Connection future. If a connection is not available, one can block using future.get()
-     * until a connection has become available.
-     * If a connection is not retrieved, the Future must be cancelled in order for the connection to be returned
-     * to the pool.
-     * @return a Future containing a reference to the connection or the future connection
-     * @throws SQLException
-     */
-    public Future<Connection> getConnectionAsync() throws SQLException {
-        try {
-            PooledConnection pc = borrowConnection(0, null, null);
-            if (pc!=null) {
-                return new ConnectionFuture(pc);
-            } 
-        }catch (SQLException x) {
-            if (x.getMessage().indexOf("NoWait")<0) {
-                throw x;
-            }
-        }
-        //we can only retrieve a future if the underlying queue supports it.
-        if (idle instanceof FairBlockingQueue<?>) {
-            Future<PooledConnection> pcf = ((FairBlockingQueue<PooledConnection>)idle).pollAsync();
-            return new ConnectionFuture(pcf);
-        } else if (idle instanceof MultiLockFairBlockingQueue<?>) {
-                Future<PooledConnection> pcf = ((MultiLockFairBlockingQueue<PooledConnection>)idle).pollAsync();
-                return new ConnectionFuture(pcf);
-        } else {
-            throw new SQLException("Connection pool is misconfigured, doesn't support async retrieval. Set the 'fair' property to 'true'");
-        }
-    }
-    
-    /**
-     * Borrows a connection from the pool. If a connection is available (in the idle queue) or the pool has not reached 
-     * {@link PoolProperties#maxActive maxActive} connections a connection is returned immediately.
-     * If no connection is available, the pool will attempt to fetch a connection for {@link PoolProperties#maxWait maxWait} milliseconds.
-     * @return Connection - a java.sql.Connection/javax.sql.PooledConnection reflection proxy, wrapping the underlying object.
-     * @throws SQLException - if the wait times out or a failure occurs creating a connection
-     */
-    public Connection getConnection() throws SQLException {
-        //check out a connection
-        PooledConnection con = borrowConnection(-1,null,null);
-        return setupConnection(con);
-    }
-
-       
-    /**
-     * Borrows a connection from the pool. If a connection is available (in the
-     * idle queue) or the pool has not reached {@link PoolProperties#maxActive
-     * maxActive} connections a connection is returned immediately. If no
-     * connection is available, the pool will attempt to fetch a connection for
-     * {@link PoolProperties#maxWait maxWait} milliseconds.
-     * 
-     * @return Connection - a java.sql.Connection/javax.sql.PooledConnection
-     *         reflection proxy, wrapping the underlying object.
-     * @throws SQLException
-     *             - if the wait times out or a failure occurs creating a
-     *             connection
-     */
-    public Connection getConnection(String username, String password) throws SQLException {
-        // check out a connection
-        PooledConnection con = borrowConnection(-1, username, password);
-        return setupConnection(con);
-    }
-    
-    /**
-     * Returns the name of this pool
-     * @return String - the name of the pool
-     */
-    public String getName() {
-        return getPoolProperties().getPoolName();
-    }
-    
-    /**
-     * Return the number of threads waiting for a connection
-     * @return number of threads waiting for a connection
-     */
-    public int getWaitCount() {
-        return waitcount.get();
-    }
-
-    /**
-     * Returns the pool properties associated with this connection pool
-     * @return PoolProperties
-     * 
-     */
-    public PoolConfiguration getPoolProperties() {
-        return this.poolProperties;
-    }
-
-    /**
-     * Returns the total size of this pool, this includes both busy and idle connections
-     * @return int - number of established connections to the database
-     */
-    public int getSize() {
-        return size.get();
-    }
-
-    /**
-     * Returns the number of connections that are in use
-     * @return int - number of established connections that are being used by the application
-     */
-    public int getActive() {
-        return busy.size();
-    }
-
-    /**
-     * Returns the number of idle connections
-     * @return int - number of established connections not being used
-     */
-    public int getIdle() {
-        return idle.size();
-    }
-
-    /**
-     * Returns true if {@link #close close} has been called, and the connection pool is unusable
-     * @return boolean
-     */
-    public  boolean isClosed() {
-        return this.closed;
-    }
-
-    //===============================================================================
-    //         PROTECTED METHODS
-    //===============================================================================
-    
-    
-    /**
-     * configures a pooled connection as a proxy.
-     * This Proxy implements {@link java.sql.Connection} and {@link javax.sql.PooledConnection} interfaces.
-     * All calls on {@link java.sql.Connection} methods will be propagated down to the actual JDBC connection except for the 
-     * {@link java.sql.Connection#close()} method.
-     * @param con a {@link PooledConnection} to wrap in a Proxy
-     * @return a {@link java.sql.Connection} object wrapping a pooled connection.
-     * @throws SQLException if an interceptor can't be configured, if the proxy can't be instantiated
-     */
-    protected Connection setupConnection(PooledConnection con) throws SQLException {
-        //fetch previously cached interceptor proxy - one per connection
-        JdbcInterceptor handler = con.getHandler();
-        if (handler==null) {
-            //build the proxy handler
-            handler = new ProxyConnection(this,con,getPoolProperties().isUseEquals());
-            //set up the interceptor chain
-            PoolProperties.InterceptorDefinition[] proxies = getPoolProperties().getJdbcInterceptorsAsArray();
-            for (int i=proxies.length-1; i>=0; i--) {
-                try {
-                    //create a new instance
-                    JdbcInterceptor interceptor = proxies[i].getInterceptorClass().newInstance();
-                    //configure properties
-                    interceptor.setProperties(proxies[i].getProperties());
-                    //setup the chain
-                    interceptor.setNext(handler);
-                    //call reset
-                    interceptor.reset(this, con);
-                    //configure the last one to be held by the connection
-                    handler = interceptor;
-                }catch(Exception x) {
-                    SQLException sx = new SQLException("Unable to instantiate interceptor chain.");
-                    sx.initCause(x);
-                    throw sx;
-                }
-            }
-            //cache handler for the next iteration
-            con.setHandler(handler);
-        } else {
-            JdbcInterceptor next = handler;
-            //we have a cached handler, reset it
-            while (next!=null) {
-                next.reset(this, con);
-                next = next.getNext();
-            }
-        }
-
-        try {
-            getProxyConstructor(con.getXAConnection() != null);
-            //create the proxy
-            //TODO possible optimization, keep track if this connection was returned properly, and don't generate a new facade
-            Connection connection = (Connection)proxyClassConstructor.newInstance(new Object[] { handler });
-            //return the connection
-            return connection;
-        }catch (Exception x) {
-            SQLException s = new SQLException();
-            s.initCause(x);
-            throw s;
-        }
-
-    }
-    
-    /**
-     * Creates and caches a {@link java.lang.reflect.Constructor} used to instantiate the proxy object.
-     * We cache this, since the creation of a constructor is fairly slow. 
-     * @return constructor used to instantiate the wrapper object
-     * @throws NoSuchMethodException
-     */
-    public Constructor<?> getProxyConstructor(boolean xa) throws NoSuchMethodException {
-        //cache the constructor
-        if (proxyClassConstructor == null ) {
-            Class<?> proxyClass = xa ?
-                Proxy.getProxyClass(ConnectionPool.class.getClassLoader(), new Class[] {java.sql.Connection.class,javax.sql.PooledConnection.class, javax.sql.XAConnection.class}) :
-                Proxy.getProxyClass(ConnectionPool.class.getClassLoader(), new Class[] {java.sql.Connection.class,javax.sql.PooledConnection.class});
-            proxyClassConstructor = proxyClass.getConstructor(new Class[] { InvocationHandler.class });
-        }
-        return proxyClassConstructor;
-    }
-
-    /**
-     * Closes the pool and all disconnects all idle connections
-     * Active connections will be closed upon the {@link java.sql.Connection#close close} method is called
-     * on the underlying connection instead of being returned to the pool
-     * @param force - true to even close the active connections
-     */
-    protected void close(boolean force) {
-        //are we already closed
-        if (this.closed) return;
-        //prevent other threads from entering
-        this.closed = true;
-        //stop background thread
-        if (poolCleaner!=null) {
-            poolCleaner.stopRunning();
-        }
-
-        /* release all idle connections */
-        BlockingQueue<PooledConnection> pool = (idle.size()>0)?idle:(force?busy:idle);
-        while (pool.size()>0) {
-            try {
-                //retrieve the next connection
-                PooledConnection con = pool.poll(1000, TimeUnit.MILLISECONDS);
-                //close it and retrieve the next one, if one is available
-                while (con != null) {
-                    //close the connection
-                    if (pool==idle)
-                        release(con);
-                    else
-                        abandon(con);
-                    con = pool.poll(1000, TimeUnit.MILLISECONDS);
-                } //while
-            } catch (InterruptedException ex) {
-                Thread.interrupted();
-            }
-            if (pool.size()==0 && force && pool!=busy) pool = busy;
-        }
-        if (this.getPoolProperties().isJmxEnabled()) this.jmxPool = null;
-        PoolProperties.InterceptorDefinition[] proxies = getPoolProperties().getJdbcInterceptorsAsArray();
-        for (int i=0; i<proxies.length; i++) {
-            try {
-                proxies[i].getInterceptorClass().newInstance().poolClosed(this);
-            }catch (Exception x) {
-                log.debug("Unable to inform interceptor of pool closure.",x);
-            }
-        }
-    } //closePool
-
-
-    /**
-     * Initialize the connection pool - called from the constructor
-     * @param properties PoolProperties - properties used to initialize the pool with
-     * @throws SQLException if initialization fails
-     */
-    protected void init(PoolConfiguration properties) throws SQLException {
-        poolProperties = properties;
-        //make space for 10 extra in case we flow over a bit
-        busy = new ArrayBlockingQueue<PooledConnection>(properties.getMaxActive(),false);
-        //busy = new FairBlockingQueue<PooledConnection>();
-        //make space for 10 extra in case we flow over a bit
-        if (properties.isFairQueue()) {
-            idle = new FairBlockingQueue<PooledConnection>();
-            //idle = new MultiLockFairBlockingQueue<PooledConnection>();
-        } else {
-            idle = new ArrayBlockingQueue<PooledConnection>(properties.getMaxActive(),properties.isFairQueue());
-        }
-
-        //if the evictor thread is supposed to run, start it now
-        if (properties.isPoolSweeperEnabled()) {
-            poolCleaner = new PoolCleaner("[Pool-Cleaner]:" + properties.getName(), this, properties.getTimeBetweenEvictionRunsMillis());
-            poolCleaner.start();
-        } //end if
-
-        //make sure the pool is properly configured
-        if (properties.getMaxActive()<1) {
-            log.warn("maxActive is smaller than 1, setting maxActive to: "+PoolProperties.DEFAULT_MAX_ACTIVE);
-            properties.setMaxActive(PoolProperties.DEFAULT_MAX_ACTIVE);
-        }
-        if (properties.getMaxActive()<properties.getInitialSize()) {
-            log.warn("initialSize is larger than maxActive, setting initialSize to: "+properties.getMaxActive());
-            properties.setInitialSize(properties.getMaxActive());
-        }
-        if (properties.getMinIdle()>properties.getMaxActive()) {
-            log.warn("minIdle is larger than maxActive, setting minIdle to: "+properties.getMaxActive());
-            properties.setMinIdle(properties.getMaxActive());
-        }
-        if (properties.getMaxIdle()>properties.getMaxActive()) {
-            log.warn("maxIdle is larger than maxActive, setting maxIdle to: "+properties.getMaxActive());
-            properties.setMaxIdle(properties.getMaxActive());
-        }
-        if (properties.getMaxIdle()<properties.getMinIdle()) {
-            log.warn("maxIdle is smaller than minIdle, setting maxIdle to: "+properties.getMinIdle());
-            properties.setMaxIdle(properties.getMinIdle());
-        }
-        
-        //create JMX MBean
-        if (this.getPoolProperties().isJmxEnabled()) createMBean();
-        
-        //Parse and create an initial set of interceptors. Letting them know the pool has started.
-        //These interceptors will not get any connection.
-        PoolProperties.InterceptorDefinition[] proxies = getPoolProperties().getJdbcInterceptorsAsArray();
-        for (int i=0; i<proxies.length; i++) {
-            try {
-                if (log.isDebugEnabled()) {
-                    log.debug("Creating interceptor instance of class:"+proxies[i].getInterceptorClass());
-                }
-                proxies[i].getInterceptorClass().newInstance().poolStarted(this);
-            }catch (Exception x) {
-                log.error("Unable to inform interceptor of pool start.",x);
-                if (jmxPool!=null) jmxPool.notify(org.apache.tomcat.jdbc.pool.jmx.ConnectionPool.NOTIFY_INIT, getStackTrace(x));
-                close(true);
-                SQLException ex = new SQLException();
-                ex.initCause(x);
-                throw ex;
-            }
-        }
-        
-        //initialize the pool with its initial set of members
-        PooledConnection[] initialPool = new PooledConnection[poolProperties.getInitialSize()];
-        try {
-            for (int i = 0; i < initialPool.length; i++) {
-                initialPool[i] = this.borrowConnection(0, null, null); //don't wait, should be no contention
-            } //for
-
-        } catch (SQLException x) {
-            if (jmxPool!=null) jmxPool.notify(org.apache.tomcat.jdbc.pool.jmx.ConnectionPool.NOTIFY_INIT, getStackTrace(x));
-            close(true);
-            throw x;
-        } finally {
-            //return the members as idle to the pool
-            for (int i = 0; i < initialPool.length; i++) {
-                if (initialPool[i] != null) {
-                    try {this.returnConnection(initialPool[i]);}catch(Exception x){/*NOOP*/}
-                } //end if
-            } //for
-        } //catch
-        
-        closed = false;
-    }
-
-
-//===============================================================================
-//         CONNECTION POOLING IMPL LOGIC
-//===============================================================================
-
-    /**
-     * thread safe way to abandon a connection
-     * signals a connection to be abandoned.
-     * this will disconnect the connection, and log the stack trace if logAbanded=true
-     * @param con PooledConnection
-     */
-    protected void abandon(PooledConnection con) {
-        if (con == null)
-            return;
-        try {
-            con.lock();
-            String trace = con.getStackTrace();
-            if (getPoolProperties().isLogAbandoned()) {
-                log.warn("Connection has been abandoned " + con + ":" + trace);
-            }
-            if (jmxPool!=null) {
-                jmxPool.notify(org.apache.tomcat.jdbc.pool.jmx.ConnectionPool.NOTIFY_ABANDON, trace);
-            }
-            //release the connection
-            release(con);
-        } finally {
-            con.unlock();
-        }
-    }
-    
-    /**
-     * thread safe way to abandon a connection
-     * signals a connection to be abandoned.
-     * this will disconnect the connection, and log the stack trace if logAbanded=true
-     * @param con PooledConnection
-     */
-    protected void suspect(PooledConnection con) {
-        if (con == null)
-            return;
-        if (con.isSuspect())
-            return;
-        try {
-            con.lock();
-            String trace = con.getStackTrace();
-            if (getPoolProperties().isLogAbandoned()) {
-                log.warn("Connection has been marked suspect, possibly abandoned " + con + "["+(System.currentTimeMillis()-con.getTimestamp())+" ms.]:" + trace);
-            }
-            if (jmxPool!=null) {
-                jmxPool.notify(org.apache.tomcat.jdbc.pool.jmx.ConnectionPool.SUSPECT_ABANDONED_NOTIFICATION, trace);
-            }
-            con.setSuspect(true);
-        } finally {
-            con.unlock();
-        }
-    }
-
-    /**
-     * thread safe way to release a connection
-     * @param con PooledConnection
-     */
-    protected void release(PooledConnection con) {
-        if (con == null)
-            return;
-        try {
-            con.lock();
-            if (con.release()) {
-                //counter only decremented once
-                size.addAndGet(-1);
-                con.setHandler(null);
-            }
-        } finally {
-            con.unlock();
-        }
-        // we've asynchronously reduced the number of connections
-        // we could have threads stuck in idle.poll(timeout) that will never be
-        // notified
-        if (waitcount.get() > 0) {
-            idle.offer(create(true));
-        }
-    }
-
-    /**
-     * Thread safe way to retrieve a connection from the pool
-     * @param wait - time to wait, overrides the maxWait from the properties, 
-     * set to -1 if you wish to use maxWait, 0 if you wish no wait time. 
-     * @return PooledConnection
-     * @throws SQLException
-     */
-    private PooledConnection borrowConnection(int wait, String username, String password) throws SQLException {
-
-        if (isClosed()) {
-            throw new SQLException("Connection pool closed.");
-        } //end if
-
-        //get the current time stamp
-        long now = System.currentTimeMillis();
-        //see if there is one available immediately
-        PooledConnection con = idle.poll();
-
-        while (true) {
-            if (con!=null) {
-                //configure the connection and return it
-                PooledConnection result = borrowConnection(now, con, username, password);
-                //null should never be returned, but was in a previous impl.
-                if (result!=null) return result;
-            }
-            
-            //if we get here, see if we need to create one
-            //this is not 100% accurate since it doesn't use a shared
-            //atomic variable - a connection can become idle while we are creating 
-            //a new connection
-            if (size.get() < getPoolProperties().getMaxActive()) {
-                //atomic duplicate check
-                if (size.addAndGet(1) > getPoolProperties().getMaxActive()) {
-                    //if we got here, two threads passed through the first if
-                    size.decrementAndGet();
-                } else {
-                    //create a connection, we're below the limit
-                    return createConnection(now, con, username, password);
-                }
-            } //end if
-
-            //calculate wait time for this iteration
-            long maxWait = wait;
-            //if the passed in wait time is -1, means we should use the pool property value
-            if (wait==-1) {
-                maxWait = (getPoolProperties().getMaxWait()<=0)?Long.MAX_VALUE:getPoolProperties().getMaxWait();
-            }
-            
-            long timetowait = Math.max(0, maxWait - (System.currentTimeMillis() - now));
-            waitcount.incrementAndGet();
-            try {
-                //retrieve an existing connection
-                con = idle.poll(timetowait, TimeUnit.MILLISECONDS);
-            } catch (InterruptedException ex) {
-                Thread.interrupted();//clear the flag, and bail out
-                SQLException sx = new SQLException("Pool wait interrupted.");
-                sx.initCause(ex);
-                throw sx;
-            } finally {
-                waitcount.decrementAndGet();
-            }
-            if (maxWait==0 && con == null) { //no wait, return one if we have one
-                throw new SQLException("[" + Thread.currentThread().getName()+"] " +
-                        "NoWait: Pool empty. Unable to fetch a connection, none available["+busy.size()+" in use].");
-            }
-            //we didn't get a connection, lets see if we timed out
-            if (con == null) {
-                if ((System.currentTimeMillis() - now) >= maxWait) {
-                    throw new SQLException("[" + Thread.currentThread().getName()+"] " +
-                        "Timeout: Pool empty. Unable to fetch a connection in " + (maxWait / 1000) +
-                        " seconds, none available["+busy.size()+" in use].");
-                } else {
-                    //no timeout, lets try again
-                    continue;
-                }
-            }
-        } //while
-    }
-
-    /**
-     * Creates a JDBC connection and tries to connect to the database.
-     * @param now timestamp of when this was called
-     * @param notUsed Argument not used
-     * @return a PooledConnection that has been connected
-     * @throws SQLException
-     */
-    protected PooledConnection createConnection(long now, PooledConnection notUsed, String username, String password) throws SQLException {
-        //no connections where available we'll create one
-        PooledConnection con = create(false);
-        if (username!=null) con.getAttributes().put(con.PROP_USER, username);
-        if (password!=null) con.getAttributes().put(con.PROP_PASSWORD, password);
-        boolean error = false;
-        try {
-            //connect and validate the connection
-            con.lock();
-            con.connect();
-            if (con.validate(PooledConnection.VALIDATE_INIT)) {
-                //no need to lock a new one, its not contented
-                con.setTimestamp(now);
-                if (getPoolProperties().isLogAbandoned()) {
-                    con.setStackTrace(getThreadDump());
-                }
-                if (!busy.offer(con)) {
-                    log.debug("Connection doesn't fit into busy array, connection will not be traceable.");
-                }
-                return con;
-            } else {
-                //validation failed, make sure we disconnect
-                //and clean up
-                error =true;
-            } //end if
-        } catch (Exception e) {
-            error = true;
-            if (log.isDebugEnabled())
-                log.debug("Unable to create a new JDBC connection.", e);
-            if (e instanceof SQLException) {
-                throw (SQLException)e;
-            } else {
-                SQLException ex = new SQLException(e.getMessage());
-                ex.initCause(e);
-                throw ex;
-            }
-        } finally {
-            // con can never be null here
-            if (error ) {
-                release(con);
-            }
-            con.unlock();
-        }//catch
-        return null;
-    }
-
-    /**
-     * Validates and configures a previously idle connection
-     * @param now - timestamp  
-     * @param con - the connection to validate and configure
-     * @return con
-     * @throws SQLException if a validation error happens
-     */
-    protected PooledConnection borrowConnection(long now, PooledConnection con, String username, String password) throws SQLException {
-        //we have a connection, lets set it up
-        
-        //flag to see if we need to nullify
-        boolean setToNull = false;
-        try {
-            con.lock();
-            boolean usercheck = con.checkUser(username, password);
-            
-            if (con.isReleased()) {
-                return null;
-            }
-            
-            if (!con.isDiscarded() && !con.isInitialized()) {
-                //attempt to connect
-                con.connect();
-            }
-            
-            if (usercheck) {
-                if ((!con.isDiscarded()) && con.validate(PooledConnection.VALIDATE_BORROW)) {
-                    //set the timestamp
-                    con.setTimestamp(now);
-                    if (getPoolProperties().isLogAbandoned()) {
-                        //set the stack trace for this pool
-                        con.setStackTrace(getThreadDump());
-                    }
-                    if (!busy.offer(con)) {
-                        log.debug("Connection doesn't fit into busy array, connection will not be traceable.");
-                    }
-                    return con;
-                }
-            }
-            //if we reached here, that means the connection
-            //is either has another principal, is discarded or validation failed.
-            //we will make one more attempt
-            //in order to guarantee that the thread that just acquired
-            //the connection shouldn't have to poll again.
-            try {
-                con.reconnect();
-                if (con.validate(PooledConnection.VALIDATE_INIT)) {
-                    //set the timestamp
-                    con.setTimestamp(now);
-                    if (getPoolProperties().isLogAbandoned()) {
-                        //set the stack trace for this pool
-                        con.setStackTrace(getThreadDump());
-                    }
-                    if (!busy.offer(con)) {
-                        log.debug("Connection doesn't fit into busy array, connection will not be traceable.");
-                    }
-                    return con;
-                } else {
-                    //validation failed.
-                    release(con);
-                    setToNull = true;
-                    throw new SQLException("Failed to validate a newly established connection.");
-                }
-            } catch (Exception x) {
-                release(con);
-                setToNull = true;
-                if (x instanceof SQLException) {
-                    throw (SQLException)x;
-                } else {
-                    SQLException ex  = new SQLException(x.getMessage());
-                    ex.initCause(x);
-                    throw ex;
-                }
-            }
-        } finally {
-            con.unlock();
-            if (setToNull) {
-                con = null;
-            }
-        }
-    }
-
-    /**
-     * Determines if a connection should be closed upon return to the pool.
-     * @param con - the connection
-     * @param action - the validation action that should be performed
-     * @return true if the connection should be closed
-     */
-    protected boolean shouldClose(PooledConnection con, int action) {
-        if (con.isDiscarded()) return true;
-        if (isClosed()) return true;
-        if (!con.validate(action)) return true;
-        if (getPoolProperties().getMaxAge()>0 ) {
-            return (System.currentTimeMillis()-con.getLastConnected()) > getPoolProperties().getMaxAge();
-        } else {
-            return false;
-        }
-    }
-    
-    /**
-     * Returns a connection to the pool
-     * If the pool is closed, the connection will be released
-     * If the connection is not part of the busy queue, it will be released.
-     * If {@link PoolProperties#testOnReturn} is set to true it will be validated
-     * @param con PooledConnection to be returned to the pool
-     */
-    protected void returnConnection(PooledConnection con) {
-        if (isClosed()) {
-            //if the connection pool is closed
-            //close the connection instead of returning it
-            release(con);
-            return;
-        } //end if
-
-        if (con != null) {
-            try {
-                con.lock();
-
-                if (busy.remove(con)) {
-                    
-                    if (!shouldClose(con,PooledConnection.VALIDATE_RETURN)) {
-                        con.setStackTrace(null);
-                        con.setTimestamp(System.currentTimeMillis());
-                        if (((idle.size()>=poolProperties.getMaxIdle()) && !poolProperties.isPoolSweeperEnabled()) || (!idle.offer(con))) {
-                            if (log.isDebugEnabled()) {
-                                log.debug("Connection ["+con+"] will be closed and not returned to the pool, idle["+idle.size()+"]>=maxIdle["+poolProperties.getMaxIdle()+"] idle.offer failed.");
-                            }
-                            release(con);
-                        }
-                    } else {
-                        if (log.isDebugEnabled()) {
-                            log.debug("Connection ["+con+"] will be closed and not returned to the pool.");
-                        }
-                        release(con);
-                    } //end if
-                } else {
-                    if (log.isDebugEnabled()) {
-                        log.debug("Connection ["+con+"] will be closed and not returned to the pool, busy.remove failed.");
-                    }
-                    release(con);
-                }
-            } finally {
-                con.unlock();
-            }
-        } //end if
-    } //checkIn
-
-    /**
-     * Determines if a connection should be abandoned based on 
-     * {@link PoolProperties#abandonWhenPercentageFull} setting.
-     * @return true if the connection should be abandoned
-     */
-    protected boolean shouldAbandon() {
-        if (poolProperties.getAbandonWhenPercentageFull()==0) return true;
-        float used = busy.size();
-        float max  = poolProperties.getMaxActive();
-        float perc = poolProperties.getAbandonWhenPercentageFull();
-        return (used/max*100f)>=perc;
-    }
-    
-    /**
-     * Iterates through all the busy connections and checks for connections that have timed out
-     */
-    public void checkAbandoned() {
-        try {
-            if (busy.size()==0) return;
-            Iterator<PooledConnection> locked = busy.iterator();
-            int sto = getPoolProperties().getSuspectTimeout();
-            while (locked.hasNext()) {
-                PooledConnection con = locked.next();
-                boolean setToNull = false;
-                try {
-                    con.lock();
-                    //the con has been returned to the pool
-                    //ignore it
-                    if (idle.contains(con))
-                        continue;
-                    long time = con.getTimestamp();
-                    long now = System.currentTimeMillis();
-                    if (shouldAbandon() && (now - time) > con.getAbandonTimeout()) {
-                        busy.remove(con);
-                        abandon(con);
-                        setToNull = true;
-                    } else if (sto > 0 && (now - time) > (sto*1000)) {
-                        suspect(con);
-                    } else {
-                        //do nothing
-                    } //end if
-                } finally {
-                    con.unlock();
-                    if (setToNull)
-                        con = null;
-                }
-            } //while
-        } catch (ConcurrentModificationException e) {
-            log.debug("checkAbandoned failed." ,e);
-        } catch (Exception e) {
-            log.warn("checkAbandoned failed, it will be retried.",e);
-        }
-    }
-
-    /**
-     * Iterates through the idle connections and resizes the idle pool based on parameters
-     * {@link PoolProperties#maxIdle}, {@link PoolProperties#minIdle}, {@link PoolProperties#minEvictableIdleTimeMillis}
-     */
-    public void checkIdle() {
-        try {
-            if (idle.size()==0) return;
-            long now = System.currentTimeMillis();
-            Iterator<PooledConnection> unlocked = idle.iterator();
-            while ( (idle.size()>=getPoolProperties().getMinIdle()) && unlocked.hasNext()) {
-                PooledConnection con = unlocked.next();
-                boolean setToNull = false;
-                try {
-                    con.lock();
-                    //the con been taken out, we can't clean it up
-                    if (busy.contains(con))
-                        continue;
-                    long time = con.getTimestamp();
-                    if ((con.getReleaseTime()>0) && ((now - time) > con.getReleaseTime()) && (getSize()>getPoolProperties().getMinIdle())) {
-                        release(con);
-                        idle.remove(con);
-                        setToNull = true;
-                    } else {
-                        //do nothing
-                    } //end if
-                } finally {
-                    con.unlock();
-                    if (setToNull)
-                        con = null;
-                }
-            } //while
-        } catch (ConcurrentModificationException e) {
-            log.debug("checkIdle failed." ,e);
-        } catch (Exception e) {
-            log.warn("checkIdle failed, it will be retried.",e);
-        }
-
-    }
-
-    /**
-     * Forces a validation of all idle connections if {@link PoolProperties#testWhileIdle} is set.
-     */
-    public void testAllIdle() {
-        try {
-            if (idle.size()==0) return;
-            Iterator<PooledConnection> unlocked = idle.iterator();
-            while (unlocked.hasNext()) {
-                PooledConnection con = unlocked.next();
-                try {
-                    con.lock();
-                    //the con been taken out, we can't clean it up
-                    if (busy.contains(con))
-                        continue;
-                    if (!con.validate(PooledConnection.VALIDATE_IDLE)) {
-                        idle.remove(con);
-                        release(con);
-                    }
-                } finally {
-                    con.unlock();
-                }
-            } //while
-        } catch (ConcurrentModificationException e) {
-            log.debug("testAllIdle failed." ,e);
-        } catch (Exception e) {
-            log.warn("testAllIdle failed, it will be retried.",e);
-        }
-
-    }
-
-    /**
-     * Creates a stack trace representing the existing thread's current state.
-     * @return a string object representing the current state.
-     * TODO investigate if we simply should store {@link java.lang.Thread#getStackTrace()} elements
-     */
-    protected static String getThreadDump() {
-        Exception x = new Exception();
-        x.fillInStackTrace();
-        return getStackTrace(x);
-    }
-
-    /**
-     * Convert an exception into a String
-     * @param x - the throwable
-     * @return a string representing the stack trace
-     */
-    public static String getStackTrace(Throwable x) {
-        if (x == null) {
-            return null;
-        } else {
-            java.io.ByteArrayOutputStream bout = new java.io.ByteArrayOutputStream();
-            java.io.PrintStream writer = new java.io.PrintStream(bout);
-            x.printStackTrace(writer);
-            String result = bout.toString();
-            return (x.getMessage()!=null && x.getMessage().length()>0)? x.getMessage()+";"+result:result;
-        } //end if
-    }
-
-
-    /**
-     * Create a new pooled connection object. Not connected nor validated.
-     * @return a pooled connection object
-     */
-    protected PooledConnection create(boolean incrementCounter) {
-        if (incrementCounter) size.incrementAndGet();
-        PooledConnection con = new PooledConnection(getPoolProperties(), this);
-        return con;
-    }
-
-    /**
-     * Hook to perform final actions on a pooled connection object once it has been disconnected and will be discarded
-     * @param con
-     */
-    protected void finalize(PooledConnection con) {
-        JdbcInterceptor handler = con.getHandler();
-        while (handler!=null) {
-            handler.reset(null, null);
-            handler=handler.getNext();
-        }
-    }
-    
-    /**
-     * Hook to perform final actions on a pooled connection object once it has been disconnected and will be discarded
-     * @param con
-     */
-    protected void disconnectEvent(PooledConnection con, boolean finalizing) {
-        JdbcInterceptor handler = con.getHandler();
-        while (handler!=null) {
-            handler.disconnected(this, con, finalizing);
-            handler=handler.getNext();
-        }
-    }
-
-    /**
-     * Return the object that is potentially registered in JMX for notifications
-     * @return the object implementing the {@link org.apache.tomcat.jdbc.pool.jmx.ConnectionPoolMBean} interface 
-     */
-    public org.apache.tomcat.jdbc.pool.jmx.ConnectionPool getJmxPool() {
-        return jmxPool;
-    }
-
-    /**
-     * Create MBean object that can be registered.
-     */
-    protected void createMBean() {
-        try {
-            jmxPool = new org.apache.tomcat.jdbc.pool.jmx.ConnectionPool(this);
-        } catch (Exception x) {
-            log.warn("Unable to start JMX integration for connection pool. Instance["+getName()+"] can't be monitored.",x);
-        }
-    }
-
-    /**
-     * Tread safe wrapper around a future for the regular queue
-     * This one retrieves the pooled connection object
-     * and performs the initialization according to 
-     * interceptors and validation rules.
-     * This class is thread safe and is cancellable
-     * @author fhanik
-     *
-     */
-    protected class ConnectionFuture implements Future<Connection>, Runnable {
-        Future<PooledConnection> pcFuture = null;
-        AtomicBoolean configured = new AtomicBoolean(false);
-        CountDownLatch latch = new CountDownLatch(1);
-        Connection result = null;
-        SQLException cause = null;
-        AtomicBoolean cancelled = new AtomicBoolean(false);
-        volatile PooledConnection pc = null;
-        public ConnectionFuture(Future<PooledConnection> pcf) {
-            this.pcFuture = pcf;
-        }
-        
-        public ConnectionFuture(PooledConnection pc) throws SQLException {
-            this.pc = pc;
-            result = ConnectionPool.this.setupConnection(pc);
-            configured.set(true);
-        }
-        /**
-         * {@inheritDoc}
-         */
-        public boolean cancel(boolean mayInterruptIfRunning) {
-            if (pc!=null) {
-                return false;
-            } else if ((!cancelled.get()) && cancelled.compareAndSet(false, true)) {
-                //cancel by retrieving the connection and returning it to the pool
-                ConnectionPool.this.cancellator.execute(this);
-            }
-            return true;
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public Connection get() throws InterruptedException, ExecutionException {
-            try {
-                return get(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
-            }catch (TimeoutException x) {
-                throw new ExecutionException(x);
-            }
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public Connection get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
-            PooledConnection pc = this.pc!=null?this.pc:pcFuture.get(timeout,unit);
-            if (pc!=null) {
-                if (result!=null) return result;
-                if (configured.compareAndSet(false, true)) {
-                    try {
-                        pc = borrowConnection(System.currentTimeMillis(),pc, null, null);
-                        result = ConnectionPool.this.setupConnection(pc);
-                    } catch (SQLException x) {
-                        cause = x;
-                    } finally {
-                        latch.countDown();
-                    }
-                } else {
-                    //if we reach here, another thread is configuring the actual connection 
-                    latch.await(timeout,unit); //this shouldn't block for long
-                }
-                if (result==null) throw new ExecutionException(cause);
-                return result;
-            } else {
-                return null;
-            }
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public boolean isCancelled() {
-            return pc==null && (pcFuture.isCancelled() || cancelled.get());
-        }
-
-        /**
-         * {@inheritDoc}
-         */
-        public boolean isDone() {
-            return pc!=null || pcFuture.isDone();
-        }
-        
-        /**
-         * run method to be executed when cancelled by an executor
-         */
-        public void run() {
-            try {
-                Connection con = get(); //complete this future
-                con.close(); //return to the pool
-            }catch (ExecutionException ex) {
-                //we can ignore this
-            }catch (Exception x) {
-                ConnectionPool.log.error("Unable to cancel ConnectionFuture.",x);
-            }
-        }
-        
-    }
-
-    protected class PoolCleaner extends Thread {
-        protected ConnectionPool pool;
-        protected long sleepTime;
-        protected volatile boolean run = true;
-        PoolCleaner(String name, ConnectionPool pool, long sleepTime) {
-            super(name);
-            this.setDaemon(true);
-            this.pool = pool;
-            this.sleepTime = sleepTime;
-            if (sleepTime <= 0) {
-                log.warn("Database connection pool evicter thread interval is set to 0, defaulting to 30 seconds");
-                this.sleepTime = 1000 * 30;
-            } else if (sleepTime < 1000) {
-                log.warn("Database connection pool evicter thread interval is set to lower than 1 second.");
-            }
-        }
-
-        @Override
-        public void run() {
-            while (run) {
-                try {
-                    sleep(sleepTime);
-                } catch (InterruptedException e) {
-                    // ignore it
-                    Thread.interrupted();
-                    continue;
-                } //catch
-
-                if (pool.isClosed()) {
-                    if (pool.getSize() <= 0) {
-                        run = false;
-                    }
-                } else {
-                    try {
-                        if (pool.getPoolProperties().isRemoveAbandoned())
-                            pool.checkAbandoned();
-                        if (pool.getPoolProperties().getMinIdle()<pool.idle.size())
-                            pool.checkIdle();
-                        if (pool.getPoolProperties().isTestWhileIdle())
-                            pool.testAllIdle();
-                    } catch (Exception x) {
-                        log.error("", x);
-                    } //catch
-                } //end if
-            } //while
-        } //run
-
-        public void stopRunning() {
-            run = false;
-            interrupt();
-        }
-    }
-}
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSource.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSource.java
deleted file mode 100644 (file)
index de837d8..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * 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.pool;
-
-import java.lang.management.ManagementFactory;
-import java.util.Hashtable;
-
-import javax.management.InstanceNotFoundException;
-import javax.management.MBeanRegistration;
-import javax.management.MBeanServer;
-import javax.management.MalformedObjectNameException;
-import javax.management.ObjectName;
-
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-
-
-/**
- * A DataSource that can be instantiated through IoC and implements the DataSource interface
- * since the DataSourceProxy is used as a generic proxy.
- * The DataSource simply wraps a {@link ConnectionPool} in order to provide a standard interface to the user.
- * @author Filip Hanik
- * @version 1.0
- */
-public class DataSource extends DataSourceProxy implements javax.sql.DataSource,MBeanRegistration, org.apache.tomcat.jdbc.pool.jmx.ConnectionPoolMBean {
-    private static final Log log = LogFactory.getLog(DataSource.class);
-
-    /**
-     * Constructor for reflection only. A default set of pool properties will be created.
-     */
-    public DataSource() {
-        super();
-    }
-    
-    /**
-     * Constructs a DataSource object wrapping a connection
-     * @param poolProperties
-     */
-    public DataSource(PoolConfiguration poolProperties) {
-        super(poolProperties);
-    }
-
-//===============================================================================
-//  JMX Operations - Register the actual pool itself under the tomcat.jdbc domain
-//===============================================================================
-    protected volatile ObjectName oname = null;
-
-    /**
-     * Unregisters the underlying connection pool mbean.<br/>
-     * {@inheritDoc}
-     */
-    public void postDeregister() {
-        if (oname!=null) unregisterJmx();
-    }
-
-    /**
-     * no-op<br/>
-     * {@inheritDoc}
-     */
-    public void postRegister(Boolean registrationDone) {
-        // NOOP
-    }
-
-
-    /**
-     * no-op<br/>
-     * {@inheritDoc}
-     */
-    public void preDeregister() throws Exception {
-        // NOOP
-    }
-
-    /**
-     * If the connection pool MBean exists, it will be registered during this operation.<br/>
-     * {@inheritDoc}
-     */
-    public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception {
-        try {
-            this.oname = createObjectName(name);
-            if (oname!=null) registerJmx();
-        }catch (MalformedObjectNameException x) {
-            log.error("Unable to create object name for JDBC pool.",x);
-        }
-        return name;   
-    }
-    
-    /**
-     * Creates the ObjectName for the ConnectionPoolMBean object to be registered
-     * @param original the ObjectName for the DataSource
-     * @return the ObjectName for the ConnectionPoolMBean
-     * @throws MalformedObjectNameException
-     */
-    public ObjectName createObjectName(ObjectName original) throws MalformedObjectNameException {
-        String domain = "tomcat.jdbc";
-        Hashtable<String,String> properties = original.getKeyPropertyList();
-        String origDomain = original.getDomain();
-        properties.put("type", "ConnectionPool");
-        properties.put("class", this.getClass().getName());
-        if (original.getKeyProperty("path")!=null) {
-            properties.put("engine", origDomain);
-        }
-        ObjectName name = new ObjectName(domain,properties);
-        return name;
-    }
-    
-    /**
-     * Registers the ConnectionPoolMBean under a unique name based on the ObjectName for the DataSource
-     */
-    protected void registerJmx() {
-        try {
-            if (pool.getJmxPool()!=null) {
-                MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
-                mbs.registerMBean(pool.getJmxPool(), oname);
-            }
-        } catch (Exception e) {
-            log.error("Unable to register JDBC pool with JMX",e);
-        }
-    }
-    
-    /**
-     * 
-     */
-    protected void unregisterJmx() {
-        try {
-            MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
-            mbs.unregisterMBean(oname);
-        } catch (InstanceNotFoundException ignore) {
-            // NOOP
-        } catch (Exception e) {
-            log.error("Unable to unregister JDBC pool with JMX",e);
-        }
-    }
-
-
-}
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java
deleted file mode 100644 (file)
index 32e5a4e..0000000
+++ /dev/null
@@ -1,538 +0,0 @@
-/*
- * 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.pool;
-
-
-import java.io.IOException;
-import java.sql.Connection;
-import java.util.Hashtable;
-import java.util.Properties;
-
-import javax.management.ObjectName;
-import javax.naming.Context;
-import javax.naming.InitialContext;
-import javax.naming.Name;
-import javax.naming.NamingException;
-import javax.naming.RefAddr;
-import javax.naming.Reference;
-import javax.naming.spi.ObjectFactory;
-import javax.sql.DataSource;
-
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-
-/**
- * <p>JNDI object factory that creates an instance of
- * <code>BasicDataSource</code> that has been configured based on the
- * <code>RefAddr</code> values of the specified <code>Reference</code>,
- * which must match the names and data types of the
- * <code>BasicDataSource</code> bean properties.</p>
- * <br/>
- * Properties available for configuration:<br/>
- * <a href="http://commons.apache.org/dbcp/configuration.html">Commons DBCP properties</a><br/>
- *<ol>
- *  <li>initSQL - A query that gets executed once, right after the connection is established.</li>
- *  <li>testOnConnect - run validationQuery after connection has been established.</li>
- *  <li>validationInterval - avoid excess validation, only run validation at most at this frequency - time in milliseconds.</li>
- *  <li>jdbcInterceptors - a semicolon separated list of classnames extending {@link JdbcInterceptor} class.</li>
- *  <li>jmxEnabled - true of false, whether to register the pool with JMX.</li>
- *  <li>fairQueue - true of false, whether the pool should sacrifice a little bit of performance for true fairness.</li>
- *</ol>
- * @author Craig R. McClanahan
- * @author Dirk Verbeeck
- * @author Filip Hanik
- */
-public class DataSourceFactory implements ObjectFactory {
-    private static final Log log = LogFactory.getLog(DataSourceFactory.class);
-
-    protected final static String PROP_DEFAULTAUTOCOMMIT = "defaultAutoCommit";
-    protected final static String PROP_DEFAULTREADONLY = "defaultReadOnly";
-    protected final static String PROP_DEFAULTTRANSACTIONISOLATION = "defaultTransactionIsolation";
-    protected final static String PROP_DEFAULTCATALOG = "defaultCatalog";
-    
-    protected final static String PROP_DRIVERCLASSNAME = "driverClassName";
-    protected final static String PROP_PASSWORD = "password";
-    protected final static String PROP_URL = "url";
-    protected final static String PROP_USERNAME = "username";
-
-    protected final static String PROP_MAXACTIVE = "maxActive";
-    protected final static String PROP_MAXIDLE = "maxIdle";
-    protected final static String PROP_MINIDLE = "minIdle";
-    protected final static String PROP_INITIALSIZE = "initialSize";
-    protected final static String PROP_MAXWAIT = "maxWait";
-    protected final static String PROP_MAXAGE = "maxAge";
-    
-    protected final static String PROP_TESTONBORROW = "testOnBorrow";
-    protected final static String PROP_TESTONRETURN = "testOnReturn";
-    protected final static String PROP_TESTWHILEIDLE = "testWhileIdle";
-    protected final static String PROP_TESTONCONNECT = "testOnConnect";
-    protected final static String PROP_VALIDATIONQUERY = "validationQuery";
-    protected final static String PROP_VALIDATOR_CLASS_NAME = "validatorClassName";
-    
-    protected final static String PROP_TIMEBETWEENEVICTIONRUNSMILLIS = "timeBetweenEvictionRunsMillis";
-    protected final static String PROP_NUMTESTSPEREVICTIONRUN = "numTestsPerEvictionRun";
-    protected final static String PROP_MINEVICTABLEIDLETIMEMILLIS = "minEvictableIdleTimeMillis";
-    
-    protected final static String PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED = "accessToUnderlyingConnectionAllowed";
-    
-    protected final static String PROP_REMOVEABANDONED = "removeAbandoned";
-    protected final static String PROP_REMOVEABANDONEDTIMEOUT = "removeAbandonedTimeout";
-    protected final static String PROP_LOGABANDONED = "logAbandoned";
-    protected final static String PROP_ABANDONWHENPERCENTAGEFULL = "abandonWhenPercentageFull";
-    
-    protected final static String PROP_POOLPREPAREDSTATEMENTS = "poolPreparedStatements";
-    protected final static String PROP_MAXOPENPREPAREDSTATEMENTS = "maxOpenPreparedStatements";
-    protected final static String PROP_CONNECTIONPROPERTIES = "connectionProperties";
-    
-    protected final static String PROP_INITSQL = "initSQL";
-    protected final static String PROP_INTERCEPTORS = "jdbcInterceptors";
-    protected final static String PROP_VALIDATIONINTERVAL = "validationInterval";
-    protected final static String PROP_JMX_ENABLED = "jmxEnabled";
-    protected final static String PROP_FAIR_QUEUE = "fairQueue";
-    
-    protected static final String PROP_USE_EQUALS = "useEquals";
-    protected static final String PROP_USE_CON_LOCK = "useLock";
-    
-    protected static final String PROP_DATASOURCE= "dataSource";
-    protected static final String PROP_DATASOURCE_JNDI = "dataSourceJNDI";
-    
-    protected static final String PROP_SUSPECT_TIMEOUT = "suspectTimeout";
-    
-    protected static final String PROP_ALTERNATE_USERNAME_ALLOWED = "alternateUsernameAllowed";
-    
-    
-    public static final int UNKNOWN_TRANSACTIONISOLATION = -1;
-    
-    public static final String OBJECT_NAME = "object_name";
-
-
-    protected final static String[] ALL_PROPERTIES = {
-        PROP_DEFAULTAUTOCOMMIT,
-        PROP_DEFAULTREADONLY,
-        PROP_DEFAULTTRANSACTIONISOLATION,
-        PROP_DEFAULTCATALOG,
-        PROP_DRIVERCLASSNAME,
-        PROP_MAXACTIVE,
-        PROP_MAXIDLE,
-        PROP_MINIDLE,
-        PROP_INITIALSIZE,
-        PROP_MAXWAIT,
-        PROP_TESTONBORROW,
-        PROP_TESTONRETURN,
-        PROP_TIMEBETWEENEVICTIONRUNSMILLIS,
-        PROP_NUMTESTSPEREVICTIONRUN,
-        PROP_MINEVICTABLEIDLETIMEMILLIS,
-        PROP_TESTWHILEIDLE,
-        PROP_TESTONCONNECT,
-        PROP_PASSWORD,
-        PROP_URL,
-        PROP_USERNAME,
-        PROP_VALIDATIONQUERY,
-        PROP_VALIDATIONINTERVAL,
-        PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED,
-        PROP_REMOVEABANDONED,
-        PROP_REMOVEABANDONEDTIMEOUT,
-        PROP_LOGABANDONED,
-        PROP_POOLPREPAREDSTATEMENTS,
-        PROP_MAXOPENPREPAREDSTATEMENTS,
-        PROP_CONNECTIONPROPERTIES,
-        PROP_INITSQL,
-        PROP_INTERCEPTORS,
-        PROP_JMX_ENABLED,
-        PROP_FAIR_QUEUE,
-        PROP_USE_EQUALS,
-        OBJECT_NAME,
-        PROP_ABANDONWHENPERCENTAGEFULL,
-        PROP_MAXAGE,
-        PROP_USE_CON_LOCK,
-        PROP_DATASOURCE,
-        PROP_DATASOURCE_JNDI,
-        PROP_ALTERNATE_USERNAME_ALLOWED
-    };
-
-    // -------------------------------------------------- ObjectFactory Methods
-
-    /**
-     * <p>Create and return a new <code>BasicDataSource</code> instance.  If no
-     * instance can be created, return <code>null</code> instead.</p>
-     *
-     * @param obj The possibly null object containing location or
-     *  reference information that can be used in creating an object
-     * @param name The name of this object relative to <code>nameCtx</code>
-     * @param nameCtx The context relative to which the <code>name</code>
-     *  parameter is specified, or <code>null</code> if <code>name</code>
-     *  is relative to the default initial context
-     * @param environment The possibly null environment that is used in
-     *  creating this object
-     *
-     * @exception Exception if an exception occurs creating the instance
-     */
-    public Object getObjectInstance(Object obj, Name name, Context nameCtx,
-                                    Hashtable<?,?> environment) throws Exception {
-
-        // We only know how to deal with <code>javax.naming.Reference</code>s
-        // that specify a class name of "javax.sql.DataSource"
-        if ((obj == null) || !(obj instanceof Reference)) {
-            return null;
-        }
-        Reference ref = (Reference) obj;
-        boolean XA = false;
-        boolean ok = false;
-        if ("javax.sql.DataSource".equals(ref.getClassName())) {
-            ok = true;
-        }
-        if ("javax.sql.XADataSource".equals(ref.getClassName())) {
-            ok = true;
-            XA = true;
-        }
-        if (org.apache.tomcat.jdbc.pool.DataSource.class.getName().equals(ref.getClassName())) {
-            ok = true;
-        }
-        
-        if (!ok) {
-            log.warn(ref.getClassName()+" is not a valid class name/type for this JNDI factory.");
-            return null;
-        }
-        
-
-        Properties properties = new Properties();
-        for (int i = 0; i < ALL_PROPERTIES.length; i++) {
-            String propertyName = ALL_PROPERTIES[i];
-            RefAddr ra = ref.get(propertyName);
-            if (ra != null) {
-                String propertyValue = ra.getContent().toString();
-                properties.setProperty(propertyName, propertyValue);
-            }
-        }
-
-        return createDataSource(properties,nameCtx,XA);
-    }
-    
-    public static PoolConfiguration parsePoolProperties(Properties properties) throws IOException{
-        PoolConfiguration poolProperties = new PoolProperties();
-        String value = null;
-
-        value = properties.getProperty(PROP_DEFAULTAUTOCOMMIT);
-        if (value != null) {
-            poolProperties.setDefaultAutoCommit(Boolean.valueOf(value));
-        }
-
-        value = properties.getProperty(PROP_DEFAULTREADONLY);
-        if (value != null) {
-            poolProperties.setDefaultReadOnly(Boolean.valueOf(value));
-        }
-
-        value = properties.getProperty(PROP_DEFAULTTRANSACTIONISOLATION);
-        if (value != null) {
-            int level = UNKNOWN_TRANSACTIONISOLATION;
-            if ("NONE".equalsIgnoreCase(value)) {
-                level = Connection.TRANSACTION_NONE;
-            } else if ("READ_COMMITTED".equalsIgnoreCase(value)) {
-                level = Connection.TRANSACTION_READ_COMMITTED;
-            } else if ("READ_UNCOMMITTED".equalsIgnoreCase(value)) {
-                level = Connection.TRANSACTION_READ_UNCOMMITTED;
-            } else if ("REPEATABLE_READ".equalsIgnoreCase(value)) {
-                level = Connection.TRANSACTION_REPEATABLE_READ;
-            } else if ("SERIALIZABLE".equalsIgnoreCase(value)) {
-                level = Connection.TRANSACTION_SERIALIZABLE;
-            } else {
-                try {
-                    level = Integer.parseInt(value);
-                } catch (NumberFormatException e) {
-                    System.err.println("Could not parse defaultTransactionIsolation: " + value);
-                    System.err.println("WARNING: defaultTransactionIsolation not set");
-                    System.err.println("using default value of database driver");
-                    level = UNKNOWN_TRANSACTIONISOLATION;
-                }
-            }
-            poolProperties.setDefaultTransactionIsolation(level);
-        }
-
-        value = properties.getProperty(PROP_DEFAULTCATALOG);
-        if (value != null) {
-            poolProperties.setDefaultCatalog(value);
-        }
-
-        value = properties.getProperty(PROP_DRIVERCLASSNAME);
-        if (value != null) {
-            poolProperties.setDriverClassName(value);
-        }
-
-        value = properties.getProperty(PROP_MAXACTIVE);
-        if (value != null) {
-            poolProperties.setMaxActive(Integer.parseInt(value));
-        }
-
-        value = properties.getProperty(PROP_MAXIDLE);
-        if (value != null) {
-            poolProperties.setMaxIdle(Integer.parseInt(value));
-        }
-
-        value = properties.getProperty(PROP_MINIDLE);
-        if (value != null) {
-            poolProperties.setMinIdle(Integer.parseInt(value));
-        }
-
-        value = properties.getProperty(PROP_INITIALSIZE);
-        if (value != null) {
-            poolProperties.setInitialSize(Integer.parseInt(value));
-        }
-
-        value = properties.getProperty(PROP_MAXWAIT);
-        if (value != null) {
-            poolProperties.setMaxWait(Integer.parseInt(value));
-        }
-
-        value = properties.getProperty(PROP_TESTONBORROW);
-        if (value != null) {
-            poolProperties.setTestOnBorrow(Boolean.valueOf(value).booleanValue());
-        }
-
-        value = properties.getProperty(PROP_TESTONRETURN);
-        if (value != null) {
-            poolProperties.setTestOnReturn(Boolean.valueOf(value).booleanValue());
-        }
-
-        value = properties.getProperty(PROP_TESTONCONNECT);
-        if (value != null) {
-            poolProperties.setTestOnConnect(Boolean.valueOf(value).booleanValue());
-        }
-
-        value = properties.getProperty(PROP_TIMEBETWEENEVICTIONRUNSMILLIS);
-        if (value != null) {
-            poolProperties.setTimeBetweenEvictionRunsMillis(Integer.parseInt(value));
-        }
-
-        value = properties.getProperty(PROP_NUMTESTSPEREVICTIONRUN);
-        if (value != null) {
-            poolProperties.setNumTestsPerEvictionRun(Integer.parseInt(value));
-        }
-
-        value = properties.getProperty(PROP_MINEVICTABLEIDLETIMEMILLIS);
-        if (value != null) {
-            poolProperties.setMinEvictableIdleTimeMillis(Integer.parseInt(value));
-        }
-
-        value = properties.getProperty(PROP_TESTWHILEIDLE);
-        if (value != null) {
-            poolProperties.setTestWhileIdle(Boolean.valueOf(value).booleanValue());
-        }
-
-        value = properties.getProperty(PROP_PASSWORD);
-        if (value != null) {
-            poolProperties.setPassword(value);
-        }
-
-        value = properties.getProperty(PROP_URL);
-        if (value != null) {
-            poolProperties.setUrl(value);
-        }
-
-        value = properties.getProperty(PROP_USERNAME);
-        if (value != null) {
-            poolProperties.setUsername(value);
-        }
-
-        value = properties.getProperty(PROP_VALIDATIONQUERY);
-        if (value != null) {
-            poolProperties.setValidationQuery(value);
-        }
-        
-        value = properties.getProperty(PROP_VALIDATOR_CLASS_NAME);
-        if (value != null) {
-            poolProperties.setValidatorClassName(value);
-        }
-
-        value = properties.getProperty(PROP_VALIDATIONINTERVAL);
-        if (value != null) {
-            poolProperties.setValidationInterval(Long.parseLong(value));
-        }
-
-        value = properties.getProperty(PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED);
-        if (value != null) {
-            poolProperties.setAccessToUnderlyingConnectionAllowed(Boolean.valueOf(value).booleanValue());
-        }
-
-        value = properties.getProperty(PROP_REMOVEABANDONED);
-        if (value != null) {
-            poolProperties.setRemoveAbandoned(Boolean.valueOf(value).booleanValue());
-        }
-
-        value = properties.getProperty(PROP_REMOVEABANDONEDTIMEOUT);
-        if (value != null) {
-            poolProperties.setRemoveAbandonedTimeout(Integer.parseInt(value));
-        }
-
-        value = properties.getProperty(PROP_LOGABANDONED);
-        if (value != null) {
-            poolProperties.setLogAbandoned(Boolean.valueOf(value).booleanValue());
-        }
-
-        value = properties.getProperty(PROP_POOLPREPAREDSTATEMENTS);
-        if (value != null) {
-            log.warn(PROP_POOLPREPAREDSTATEMENTS + " is not a valid setting, it will have no effect.");
-        }
-
-        value = properties.getProperty(PROP_MAXOPENPREPAREDSTATEMENTS);
-        if (value != null) {
-            log.warn(PROP_MAXOPENPREPAREDSTATEMENTS + " is not a valid setting, it will have no effect.");
-        }
-
-        value = properties.getProperty(PROP_CONNECTIONPROPERTIES);
-        if (value != null) {
-            Properties p = getProperties(value);
-            poolProperties.setDbProperties(p);
-        } else {
-            poolProperties.setDbProperties(new Properties());
-        }
-
-        if (poolProperties.getUsername()!=null) {
-            poolProperties.getDbProperties().setProperty("user",poolProperties.getUsername());
-        }
-        if (poolProperties.getPassword()!=null) {
-            poolProperties.getDbProperties().setProperty("password",poolProperties.getPassword());
-        }
-
-        value = properties.getProperty(PROP_INITSQL);
-        if (value != null) {
-            poolProperties.setInitSQL(value);
-        }
-
-        value = properties.getProperty(PROP_INTERCEPTORS);
-        if (value != null) {
-            poolProperties.setJdbcInterceptors(value);
-        }
-
-        value = properties.getProperty(PROP_JMX_ENABLED);
-        if (value != null) {
-            poolProperties.setJmxEnabled(Boolean.parseBoolean(value));
-        }
-        
-        value = properties.getProperty(PROP_FAIR_QUEUE);
-        if (value != null) {
-            poolProperties.setFairQueue(Boolean.parseBoolean(value));
-        }
-        
-        value = properties.getProperty(PROP_USE_EQUALS);
-        if (value != null) {
-            poolProperties.setUseEquals(Boolean.parseBoolean(value));
-        }
-
-        value = properties.getProperty(OBJECT_NAME);
-        if (value != null) {
-            poolProperties.setName(ObjectName.quote(value));
-        }
-        
-        value = properties.getProperty(PROP_ABANDONWHENPERCENTAGEFULL);
-        if (value != null) {
-            poolProperties.setAbandonWhenPercentageFull(Integer.parseInt(value));
-        }
-        
-        value = properties.getProperty(PROP_MAXAGE);
-        if (value != null) {
-            poolProperties.setMaxAge(Long.parseLong(value));
-        }
-        
-        value = properties.getProperty(PROP_USE_CON_LOCK);
-        if (value != null) {
-            poolProperties.setUseLock(Boolean.parseBoolean(value));
-        }
-        
-        value = properties.getProperty(PROP_DATASOURCE);
-        if (value != null) {
-            //this should never happen
-            throw new IllegalArgumentException("Can't set dataSource property as a string, this must be a javax.sql.DataSource object.");
-            
-        }
-        
-        value = properties.getProperty(PROP_DATASOURCE_JNDI);
-        if (value != null) {
-            poolProperties.setDataSourceJNDI(value);
-        }
-
-        value = properties.getProperty(PROP_SUSPECT_TIMEOUT);
-        if (value != null) {
-            poolProperties.setSuspectTimeout(Integer.parseInt(value));
-        }
-        
-        value = properties.getProperty(PROP_ALTERNATE_USERNAME_ALLOWED);
-        if (value != null) {
-            poolProperties.setAlternateUsernameAllowed(Boolean.parseBoolean(value));
-        }
-        
-        return poolProperties;
-    }
-
-    /**
-     * Creates and configures a {@link DataSource} instance based on the
-     * given properties.
-     *
-     * @param properties the datasource configuration properties
-     * @throws Exception if an error occurs creating the data source
-     */
-    public DataSource createDataSource(Properties properties) throws Exception {
-        return createDataSource(properties,null,false);
-    }
-    public DataSource createDataSource(Properties properties,Context context, boolean XA) throws Exception {
-        PoolConfiguration poolProperties = DataSourceFactory.parsePoolProperties(properties);
-        if (poolProperties.getDataSourceJNDI()!=null && poolProperties.getDataSource()==null) {
-            performJNDILookup(context, poolProperties);
-        }
-        org.apache.tomcat.jdbc.pool.DataSource dataSource = XA?
-                new org.apache.tomcat.jdbc.pool.XADataSource(poolProperties) :
-                new org.apache.tomcat.jdbc.pool.DataSource(poolProperties);
-        //initialise the pool itself
-        dataSource.createPool();
-        // Return the configured DataSource instance
-        return dataSource;
-    }
-
-    public void performJNDILookup(Context context, PoolConfiguration poolProperties) {
-        Object jndiDS = null;
-        try {
-            if (context!=null) {
-                jndiDS = context.lookup(poolProperties.getDataSourceJNDI());
-            } else {
-                log.warn("dataSourceJNDI property is configued, but local JNDI context is null.");
-            }
-        } catch (NamingException e) {
-            log.debug("The name \""+poolProperties.getDataSourceJNDI()+"\" can not be found in the local context.");
-        }
-        if (jndiDS==null) {
-            try {
-                context = (Context) (new InitialContext());
-                jndiDS = context.lookup(poolProperties.getDataSourceJNDI());
-            } catch (NamingException e) {
-                log.warn("The name \""+poolProperties.getDataSourceJNDI()+"\" can not be found in the InitialContext.");
-            }
-        }
-        if (jndiDS!=null) {
-            poolProperties.setDataSource(jndiDS);
-        }
-    }
-    
-    /**
-     * <p>Parse properties from the string. Format of the string must be [propertyName=property;]*<p>
-     * @param propText
-     * @return Properties
-     * @throws Exception
-     */
-    static protected Properties getProperties(String propText) throws IOException {
-        return PoolProperties.getProperties(propText,null);
-    }
-
-}
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java
deleted file mode 100644 (file)
index e839991..0000000
+++ /dev/null
@@ -1,1084 +0,0 @@
-/*
- * 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.pool;
-
-import java.io.PrintWriter;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.util.Iterator;
-import java.util.Properties;
-import java.util.concurrent.Future;
-
-import javax.sql.XAConnection;
-
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorDefinition;
-
-/**
- *
- * The DataSource proxy lets us implements methods that don't exist in the current 
- * compiler JDK but might be methods that are part of a future JDK DataSource interface.
- * <br/>
- * It's a trick to work around compiler issues when implementing interfaces. For example, 
- * I could put in Java 6 methods of javax.sql.DataSource here, and compile it with JDK 1.5
- * and still be able to run under Java 6 without getting NoSuchMethodException.
- *
- * @author Filip Hanik
- * @version 1.0
- */
-
-public class DataSourceProxy implements PoolConfiguration {
-    private static final Log log = LogFactory.getLog(DataSourceProxy.class);
-    
-    protected volatile ConnectionPool pool = null;
-    
-    protected PoolConfiguration poolProperties = null;
-
-    public DataSourceProxy() {
-        this(new PoolProperties());
-    }
-    
-    public DataSourceProxy(PoolConfiguration poolProperties) {
-        if (poolProperties == null) throw new NullPointerException("PoolConfiguration can not be null.");
-        this.poolProperties = poolProperties;
-    }
-
-
-    public boolean isWrapperFor(Class<?> iface) throws SQLException {
-        // we are not a wrapper of anything
-        return false;
-    }
-
-
-    public <T> T unwrap(Class<T> iface) throws SQLException {
-        //we can't unwrap anything
-        return null;
-    }
-
-    /**
-     * {@link javax.sql.DataSource#getConnection()}
-     */
-    public Connection getConnection(String username, String password) throws SQLException {
-        if (this.getPoolProperties().isAlternateUsernameAllowed()) {
-            if (pool == null)
-                return createPool().getConnection(username,password);
-            return pool.getConnection(username,password);
-        } else {
-            return getConnection();
-        }
-    }
-
-    public PoolConfiguration getPoolProperties() {
-        return poolProperties;
-    }
-
-    /**
-     * Sets up the connection pool, by creating a pooling driver.
-     * @return Driver
-     * @throws SQLException
-     */
-    public synchronized ConnectionPool createPool() throws SQLException {
-        if (pool != null) {
-            return pool;
-        } else {
-            pool = new ConnectionPool(poolProperties);
-            return pool;
-        }
-    }
-
-    /**
-     * {@link javax.sql.DataSource#getConnection()}
-     */
-
-    public Connection getConnection() throws SQLException {
-        if (pool == null)
-            return createPool().getConnection();
-        return pool.getConnection();
-    }
-    
-    /**
-     * Invokes an sync operation to retrieve the connection.
-     * @return a Future containing a reference to the connection when it becomes available 
-     * @throws SQLException
-     */
-    public Future<Connection> getConnectionAsync() throws SQLException {
-        if (pool == null)
-            return createPool().getConnectionAsync();
-        return pool.getConnectionAsync();
-    }
-    
-    /**
-     * {@link javax.sql.XADataSource#getXAConnection()} 
-     */
-    public XAConnection getXAConnection() throws SQLException {
-        Connection con = getConnection();
-        if (con instanceof XAConnection) {
-            return (XAConnection)con;
-        } else {
-            try {con.close();} catch (Exception ignore){}
-            throw new SQLException("Connection from pool does not implement javax.sql.XAConnection");
-        }
-    }
-    
-    /**
-     * {@link javax.sql.XADataSource#getXAConnection(String, String)} 
-     */
-    public XAConnection getXAConnection(String username, String password) throws SQLException {
-        Connection con = getConnection(username, password);
-        if (con instanceof XAConnection) {
-            return (XAConnection)con;
-        } else {
-            try {con.close();} catch (Exception ignore){}
-            throw new SQLException("Connection from pool does not implement javax.sql.XAConnection");
-        }
-    }
-
-
-    /**
-     * {@link javax.sql.DataSource#getConnection()}
-     */
-    public PooledConnection getPooledConnection() throws SQLException {
-        return (PooledConnection) getConnection();
-    }
-
-    /**
-     * {@link javax.sql.DataSource#getConnection()}
-     */
-    public PooledConnection getPooledConnection(String username,
-                                                String password) throws SQLException {
-        return (PooledConnection) getConnection();
-    }
-    
-    public ConnectionPool getPool() {
-        return pool;
-    }
-
-    
-    public void close() {
-        close(false);
-    }
-    public void close(boolean all) {
-        try {
-            if (pool != null) {
-                final ConnectionPool p = pool;
-                pool = null;
-                if (p!=null) {
-                    p.close(all);
-                }
-            }
-        }catch (Exception x) {
-            log.warn("Error duing connection pool closure.", x);
-        }
-    }
-
-    public int getPoolSize() throws SQLException{
-        final ConnectionPool p = pool;
-        if (p == null) return 0;
-        else return p.getSize();
-    }
-
-    
-    public String toString() {
-        return super.toString()+"{"+getPoolProperties()+"}";
-    }
-
-
-/*-----------------------------------------------------------------------*/
-//      PROPERTIES WHEN NOT USED WITH FACTORY
-/*------------------------------------------------------------------------*/
-   
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public String getPoolName() {
-        return pool.getName();
-    }
-   
-   
-    public void setPoolProperties(PoolConfiguration poolProperties) {
-        this.poolProperties = poolProperties;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setDriverClassName(String driverClassName) {
-        this.poolProperties.setDriverClassName(driverClassName);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setInitialSize(int initialSize) {
-        this.poolProperties.setInitialSize(initialSize);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setInitSQL(String initSQL) {
-        this.poolProperties.setInitSQL(initSQL);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setLogAbandoned(boolean logAbandoned) {
-        this.poolProperties.setLogAbandoned(logAbandoned);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setMaxActive(int maxActive) {
-        this.poolProperties.setMaxActive(maxActive);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setMaxIdle(int maxIdle) {
-        this.poolProperties.setMaxIdle(maxIdle);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setMaxWait(int maxWait) {
-        this.poolProperties.setMaxWait(maxWait);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) {
-        this.poolProperties.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setMinIdle(int minIdle) {
-        this.poolProperties.setMinIdle(minIdle);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
-        this.poolProperties.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setPassword(String password) {
-        this.poolProperties.setPassword(password);
-        this.poolProperties.getDbProperties().setProperty("password",this.poolProperties.getPassword());
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setRemoveAbandoned(boolean removeAbandoned) {
-        this.poolProperties.setRemoveAbandoned(removeAbandoned);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) {
-        this.poolProperties.setRemoveAbandonedTimeout(removeAbandonedTimeout);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setTestOnBorrow(boolean testOnBorrow) {
-        this.poolProperties.setTestOnBorrow(testOnBorrow);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setTestOnConnect(boolean testOnConnect) {
-        this.poolProperties.setTestOnConnect(testOnConnect);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setTestOnReturn(boolean testOnReturn) {
-        this.poolProperties.setTestOnReturn(testOnReturn);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setTestWhileIdle(boolean testWhileIdle) {
-        this.poolProperties.setTestWhileIdle(testWhileIdle);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setTimeBetweenEvictionRunsMillis(int timeBetweenEvictionRunsMillis) {
-        this.poolProperties.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setUrl(String url) {
-        this.poolProperties.setUrl(url);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setUsername(String username) {
-        this.poolProperties.setUsername(username);
-        this.poolProperties.getDbProperties().setProperty("user",getPoolProperties().getUsername());
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setValidationInterval(long validationInterval) {
-        this.poolProperties.setValidationInterval(validationInterval);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setValidationQuery(String validationQuery) {
-        this.poolProperties.setValidationQuery(validationQuery);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    
-    public void setValidatorClassName(String className) {
-        this.poolProperties.setValidatorClassName(className);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setJdbcInterceptors(String interceptors) {
-        this.getPoolProperties().setJdbcInterceptors(interceptors);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setJmxEnabled(boolean enabled) {
-        this.getPoolProperties().setJmxEnabled(enabled);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setFairQueue(boolean fairQueue) {
-        this.getPoolProperties().setFairQueue(fairQueue);
-    }
-    
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setUseLock(boolean useLock) {
-        this.getPoolProperties().setUseLock(useLock);
-    }
-    
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setDefaultCatalog(String catalog) {
-        this.getPoolProperties().setDefaultCatalog(catalog);
-    }
-    
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setDefaultAutoCommit(Boolean autocommit) {
-        this.getPoolProperties().setDefaultAutoCommit(autocommit);
-    }
-    
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setDefaultTransactionIsolation(int defaultTransactionIsolation) {
-        this.getPoolProperties().setDefaultTransactionIsolation(defaultTransactionIsolation);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setConnectionProperties(String properties) {
-        try {
-            java.util.Properties prop = DataSourceFactory
-                    .getProperties(properties);
-            Iterator<?> i = prop.keySet().iterator();
-            while (i.hasNext()) {
-                String key = (String) i.next();
-                String value = prop.getProperty(key);
-                getPoolProperties().getDbProperties().setProperty(key, value);
-            }
-
-        } catch (Exception x) {
-            log.error("Unable to parse connection properties.", x);
-            throw new RuntimeException(x);
-        }
-    }
-    
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setUseEquals(boolean useEquals) {
-        this.getPoolProperties().setUseEquals(useEquals);
-    }
-
-    /**
-     * no-op
-     * {@link javax.sql.DataSource#getLogWriter}
-     */
-    public PrintWriter getLogWriter() throws SQLException {
-        return null;
-    }
-
-
-    /**
-     * no-op
-     * {@link javax.sql.DataSource#setLogWriter(PrintWriter)}
-     */
-    public void setLogWriter(PrintWriter out) throws SQLException {
-        // NOOP
-    }
-
-    /**
-     * no-op
-     * {@link javax.sql.DataSource#getLoginTimeout}
-     */
-    public int getLoginTimeout() {
-        if (poolProperties == null) {
-            return 0;
-        } else {
-            return poolProperties.getMaxWait() / 1000;
-        }
-    }
-
-    /**
-     * {@link javax.sql.DataSource#setLoginTimeout(int)}
-     */
-    public void setLoginTimeout(int i) {
-        if (poolProperties == null) {
-            return;
-        } else {
-            poolProperties.setMaxWait(1000 * i);
-        }
-
-    }    
-    
-    
-    /**
-     * {@inheritDoc}
-     */
-    
-    public int getSuspectTimeout() {
-        return getPoolProperties().getSuspectTimeout(); 
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    
-    public void setSuspectTimeout(int seconds) {
-        getPoolProperties().setSuspectTimeout(seconds);
-    }
-    
-  //===============================================================================
-//  Expose JMX attributes through Tomcat's dynamic reflection
-//===============================================================================
-    /**
-     * If the pool has not been created, it will be created during this call.
-     * @return the number of established but idle connections
-     */
-    public int getIdle() {
-        try {
-            return createPool().getIdle();
-        }catch (SQLException x) {
-            throw new RuntimeException(x);
-        }
-    }
-
-    /**
-     * {@link #getIdle()}
-     */
-    public int getNumIdle() {
-        return getIdle();
-    }
-
-    /**
-     * Forces an abandon check on the connection pool.
-     * If connections that have been abandoned exists, they will be closed during this run
-     */
-    public void checkAbandoned() {
-        try {
-            createPool().checkAbandoned();
-        }catch (SQLException x) {
-            throw new RuntimeException(x);
-        }
-    }
-
-    /**
-     * Forces a check for resizing of the idle connections
-     */
-    public void checkIdle() {
-        try {
-            createPool().checkIdle();
-        }catch (SQLException x) {
-            throw new RuntimeException(x);
-        }
-    }
-
-    /**
-     * @return number of connections in use by the application
-     */
-    public int getActive() {
-        try {
-            return createPool().getActive();
-        }catch (SQLException x) {
-            throw new RuntimeException(x);
-        }
-    }
-    
-    /**
-     * @return number of connections in use by the application
-     * {@link DataSource#getActive()}
-     */
-    public int getNumActive() {
-        return getActive();
-    }
-
-    /**
-     * @return number of threads waiting for a connection
-     */
-    public int getWaitCount() {
-        try {
-            return createPool().getWaitCount();
-        }catch (SQLException x) {
-            throw new RuntimeException(x);
-        }
-    }
-
-    /**
-     * @return the current size of the pool
-     */
-    public int getSize() {
-        try {
-            return createPool().getSize();
-        }catch (SQLException x) {
-            throw new RuntimeException(x);
-        }
-    }
-
-    /**
-     * Performs a validation on idle connections
-     */
-    public void testIdle() {
-        try {
-            createPool().testAllIdle();
-        }catch (SQLException x) {
-            throw new RuntimeException(x);
-        }
-    }    
-    //=========================================================
-    //  PROPERTIES / CONFIGURATION
-    //=========================================================    
-    
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public String getConnectionProperties() {
-        return getPoolProperties().getConnectionProperties();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public Properties getDbProperties() {
-        return getPoolProperties().getDbProperties();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public String getDefaultCatalog() {
-        return getPoolProperties().getDefaultCatalog();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public int getDefaultTransactionIsolation() {
-        return getPoolProperties().getDefaultTransactionIsolation();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public String getDriverClassName() {
-        return getPoolProperties().getDriverClassName();
-    }
-
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public int getInitialSize() {
-        return getPoolProperties().getInitialSize();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public String getInitSQL() {
-        return getPoolProperties().getInitSQL();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public String getJdbcInterceptors() {
-        return getPoolProperties().getJdbcInterceptors();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public int getMaxActive() {
-        return getPoolProperties().getMaxActive();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public int getMaxIdle() {
-        return getPoolProperties().getMaxIdle();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public int getMaxWait() {
-        return getPoolProperties().getMaxWait();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public int getMinEvictableIdleTimeMillis() {
-        return getPoolProperties().getMinEvictableIdleTimeMillis();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public int getMinIdle() {
-        return getPoolProperties().getMinIdle();
-    }
-    
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public long getMaxAge() {
-        return getPoolProperties().getMaxAge();
-    }    
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public String getName() {
-        return getPoolProperties().getName();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public int getNumTestsPerEvictionRun() {
-        return getPoolProperties().getNumTestsPerEvictionRun();
-    }
-
-    /**
-     * @return DOES NOT RETURN THE PASSWORD, IT WOULD SHOW UP IN JMX
-     */
-    public String getPassword() {
-        return "Password not available as DataSource/JMX operation.";
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public int getRemoveAbandonedTimeout() {
-        return getPoolProperties().getRemoveAbandonedTimeout();
-    }
-
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public int getTimeBetweenEvictionRunsMillis() {
-        return getPoolProperties().getTimeBetweenEvictionRunsMillis();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public String getUrl() {
-        return getPoolProperties().getUrl();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public String getUsername() {
-        return getPoolProperties().getUsername();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public long getValidationInterval() {
-        return getPoolProperties().getValidationInterval();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public String getValidationQuery() {
-        return getPoolProperties().getValidationQuery();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    
-    public String getValidatorClassName() {
-        return getPoolProperties().getValidatorClassName();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    
-    public Validator getValidator() {
-        return getPoolProperties().getValidator();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public boolean isAccessToUnderlyingConnectionAllowed() {
-        return getPoolProperties().isAccessToUnderlyingConnectionAllowed();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public Boolean isDefaultAutoCommit() {
-        return getPoolProperties().isDefaultAutoCommit();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public Boolean isDefaultReadOnly() {
-        return getPoolProperties().isDefaultReadOnly();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public boolean isLogAbandoned() {
-        return getPoolProperties().isLogAbandoned();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public boolean isPoolSweeperEnabled() {
-        return getPoolProperties().isPoolSweeperEnabled();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public boolean isRemoveAbandoned() {
-        return getPoolProperties().isRemoveAbandoned();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public int getAbandonWhenPercentageFull() {
-        return getPoolProperties().getAbandonWhenPercentageFull();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public boolean isTestOnBorrow() {
-        return getPoolProperties().isTestOnBorrow();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public boolean isTestOnConnect() {
-        return getPoolProperties().isTestOnConnect();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public boolean isTestOnReturn() {
-        return getPoolProperties().isTestOnReturn();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public boolean isTestWhileIdle() {
-        return getPoolProperties().isTestWhileIdle();
-    }
-
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public Boolean getDefaultAutoCommit() {
-        return getPoolProperties().getDefaultAutoCommit();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public Boolean getDefaultReadOnly() {
-        return getPoolProperties().getDefaultReadOnly();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public InterceptorDefinition[] getJdbcInterceptorsAsArray() {
-        return getPoolProperties().getJdbcInterceptorsAsArray();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public boolean getUseLock() {
-        return getPoolProperties().getUseLock();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public boolean isFairQueue() {
-        return getPoolProperties().isFairQueue();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public boolean isJmxEnabled() {
-        return getPoolProperties().isJmxEnabled();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public boolean isUseEquals() {
-        return getPoolProperties().isUseEquals();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setAbandonWhenPercentageFull(int percentage) {
-        getPoolProperties().setAbandonWhenPercentageFull(percentage);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setAccessToUnderlyingConnectionAllowed(boolean accessToUnderlyingConnectionAllowed) {
-        getPoolProperties().setAccessToUnderlyingConnectionAllowed(accessToUnderlyingConnectionAllowed);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setDbProperties(Properties dbProperties) {
-        getPoolProperties().setDbProperties(dbProperties);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setDefaultReadOnly(Boolean defaultReadOnly) {
-        getPoolProperties().setDefaultReadOnly(defaultReadOnly);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setMaxAge(long maxAge) {
-        getPoolProperties().setMaxAge(maxAge);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setName(String name) {
-        getPoolProperties().setName(name);
-    }
-    
-    /** 
-     * {@inheritDoc}
-     */
-    public void setDataSource(Object ds) {
-        getPoolProperties().setDataSource(ds);
-    }
-    
-    /** 
-     * {@inheritDoc}
-     */
-    public Object getDataSource() {
-        return getPoolProperties().getDataSource();
-    }
-    
-    
-    /** 
-     * {@inheritDoc}
-     */
-    public void setDataSourceJNDI(String jndiDS) {
-        getPoolProperties().setDataSourceJNDI(jndiDS);
-    }
-    
-    /** 
-     * {@inheritDoc}
-     */
-    public String getDataSourceJNDI() {
-        return getPoolProperties().getDataSourceJNDI();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    public boolean isAlternateUsernameAllowed() {
-        return getPoolProperties().isAlternateUsernameAllowed();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    public void setAlternateUsernameAllowed(boolean alternateUsernameAllowed) {
-        getPoolProperties().setAlternateUsernameAllowed(alternateUsernameAllowed);
-    }
-    
-}
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/FairBlockingQueue.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/FairBlockingQueue.java
deleted file mode 100644 (file)
index ea56e86..0000000
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
- * 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.pool;
-
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.NoSuchElementException;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- *
- * A simple implementation of a blocking queue with fairness waiting.
- * invocations to method poll(...) will get handed out in the order they were received.
- * Locking is fine grained, a shared lock is only used during the first level of contention, waiting is done in a 
- * lock per thread basis so that order is guaranteed once the thread goes into a suspended monitor state.
- * <br/>
- * Not all of the methods of the {@link java.util.concurrent.BlockingQueue} are implemented.
- * @author Filip Hanik
- *
- */
-
-public class FairBlockingQueue<E> implements BlockingQueue<E> {
-    
-    /**
-     * This little sucker is used to reorder the way to do 
-     * {@link java.util.concurrent.locks.Lock#lock()},
-     * {@link java.util.concurrent.locks.Lock#unlock()}
-     * and 
-     * {@link java.util.concurrent.CountDownLatch#countDown()}
-     * during the {@link #poll(long, TimeUnit)} operation.
-     * On Linux, it performs much better if we count down while we hold the global
-     * lock, on Solaris its the other way around.
-     * Until we have tested other platforms we only check for Linux.
-     */
-    final static boolean isLinux = "Linux".equals(System.getProperty("os.name")) &&
-                                   (!Boolean.getBoolean(FairBlockingQueue.class.getName()+".ignoreOS"));
-    
-    /**
-     * Phase one entry lock in order to give out 
-     * per-thread-locks for the waiting phase we have 
-     * a phase one lock during the contention period.
-     */
-    final ReentrantLock lock = new ReentrantLock(false);
-
-    /**
-     * All the objects in the pool are stored in a simple linked list
-     */
-    final LinkedList<E> items;
-
-    /**
-     * All threads waiting for an object are stored in a linked list
-     */
-    final LinkedList<ExchangeCountDownLatch<E>> waiters;
-    
-    /**
-     * Creates a new fair blocking queue.
-     */
-    public FairBlockingQueue() {
-        items = new LinkedList<E>();
-        waiters = new LinkedList<ExchangeCountDownLatch<E>>();
-    }
-
-    //------------------------------------------------------------------
-    // USED BY CONPOOL IMPLEMENTATION
-    //------------------------------------------------------------------
-    /**
-     * Will always return true, queue is unbounded.
-     * {@inheritDoc}
-     */
-    public boolean offer(E e) {
-        //during the offer, we will grab the main lock
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        ExchangeCountDownLatch<E> c = null;
-        try {
-            //check to see if threads are waiting for an object
-            if (waiters.size() > 0) {
-                //if threads are waiting grab the latch for that thread
-                c = waiters.poll();
-                //give the object to the thread instead of adding it to the pool
-                c.setItem(e);
-                if (isLinux) c.countDown();
-            } else {
-                //we always add first, so that the most recently used object will be given out
-                items.addFirst(e);
-            }
-        } finally {
-            lock.unlock();
-        }
-        //if we exchanged an object with another thread, wake it up.
-        if (!isLinux && c!=null) c.countDown();
-        //we have an unbounded queue, so always return true
-        return true;
-    }
-
-    /**
-     * Will never timeout, as it invokes the {@link #offer(Object)} method.
-     * Once a lock has been acquired, the  
-     * {@inheritDoc}
-     */
-    public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException {
-        return offer(e);
-    }
-
-    /**
-     * Fair retrieval of an object in the queue.
-     * Objects are returned in the order the threads requested them.
-     * {@inheritDoc}
-     */
-    public E poll(long timeout, TimeUnit unit) throws InterruptedException {
-        E result = null;
-        final ReentrantLock lock = this.lock;
-        boolean error = true;
-        //acquire the global lock until we know what to do
-        lock.lock();
-        try {
-            //check to see if we have objects
-            result = items.poll();
-            if (result==null && timeout>0) {
-                //the queue is empty we will wait for an object
-                ExchangeCountDownLatch<E> c = new ExchangeCountDownLatch<E>(1);
-                //add to the bottom of the wait list
-                waiters.addLast(c);
-                //unlock the global lock
-                lock.unlock();
-                //wait for the specified timeout
-                if (!c.await(timeout, unit)) {
-                    //if we timed out, remove ourselves from the waitlist
-                    lock.lock();
-                    waiters.remove(c);
-                    lock.unlock();
-                }
-                //return the item we received, can be null if we timed out
-                result = c.getItem();
-            } else {
-                //we have an object, release
-                lock.unlock();
-            }
-            error = false;
-        } finally {
-            if (error && lock.isHeldByCurrentThread()) {
-                lock.unlock();
-            }
-        }
-        return result;
-    }
-    
-    /**
-     * Request an item from the queue asynchronously
-     * @return - a future pending the result from the queue poll request
-     */
-    public Future<E> pollAsync() {
-        Future<E> result = null;
-        final ReentrantLock lock = this.lock;
-        boolean error = true;
-        //grab the global lock
-        lock.lock();
-        try {
-            //check to see if we have objects in the queue
-            E item = items.poll();
-            if (item==null) {
-                //queue is empty, add ourselves as waiters
-                ExchangeCountDownLatch<E> c = new ExchangeCountDownLatch<E>(1);
-                waiters.addLast(c);
-                lock.unlock();
-                //return a future that will wait for the object
-                result = new ItemFuture<E>(c);
-            } else {
-                lock.unlock();
-                //return a future with the item
-                result = new ItemFuture<E>(item);
-            }
-            error = false;
-        } finally {
-            if (error && lock.isHeldByCurrentThread()) {
-                lock.unlock();
-            }
-        }
-        return result;
-    }
-    
-    /**
-     * {@inheritDoc}
-     */
-    public boolean remove(Object e) {
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
-            return items.remove(e);
-        } finally {
-            lock.unlock();
-        }
-    }
-    
-    /**
-     * {@inheritDoc}
-     */
-    public int size() {
-        return items.size();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Iterator<E> iterator() {
-        return new FairIterator();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public E poll() {
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
-            return items.poll();
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean contains(Object e) {
-        final ReentrantLock lock = this.lock;
-        lock.lock();
-        try {
-            return items.contains(e);
-        } finally {
-            lock.unlock();
-        }
-    }
-
-
-    //------------------------------------------------------------------
-    // NOT USED BY CONPOOL IMPLEMENTATION
-    //------------------------------------------------------------------
-    /**
-     * {@inheritDoc}
-     */
-    public boolean add(E e) {
-        return offer(e);
-    }
-
-    /**
-     * {@inheritDoc}
-     * @throws UnsupportedOperationException - this operation is not supported
-     */
-    public int drainTo(Collection<? super E> c, int maxElements) {
-        throw new UnsupportedOperationException("int drainTo(Collection<? super E> c, int maxElements)");
-    }
-
-    /**
-     * {@inheritDoc}
-     * @throws UnsupportedOperationException - this operation is not supported
-     */
-    
-    public int drainTo(Collection<? super E> c) {
-        return drainTo(c,Integer.MAX_VALUE);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void put(E e) throws InterruptedException {
-        offer(e);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int remainingCapacity() {
-        return Integer.MAX_VALUE - size();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public E take() throws InterruptedException {
-        return this.poll(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean addAll(Collection<? extends E> c) {
-        Iterator<? extends E> i = c.iterator();
-        while (i.hasNext()) {
-            E e = i.next();
-            offer(e);
-        }
-        return true;
-    }
-
-    /**
-     * {@inheritDoc}
-     * @throws UnsupportedOperationException - this operation is not supported
-     */
-    public void clear() {
-        throw new UnsupportedOperationException("void clear()");
-
-    }
-
-    /**
-     * {@inheritDoc}
-     * @throws UnsupportedOperationException - this operation is not supported
-     */
-    public boolean containsAll(Collection<?> c) {
-        throw new UnsupportedOperationException("boolean containsAll(Collection<?> c)");
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isEmpty() {
-        return size() == 0;
-    }
-
-    /**
-     * {@inheritDoc}
-     * @throws UnsupportedOperationException - this operation is not supported
-     */
-    public boolean removeAll(Collection<?> c) {
-        throw new UnsupportedOperationException("boolean removeAll(Collection<?> c)");
-    }
-
-    /**
-     * {@inheritDoc}
-     * @throws UnsupportedOperationException - this operation is not supported
-     */
-    public boolean retainAll(Collection<?> c) {
-        throw new UnsupportedOperationException("boolean retainAll(Collection<?> c)");
-    }
-
-    /**
-     * {@inheritDoc}
-     * @throws UnsupportedOperationException - this operation is not supported
-     */
-    public Object[] toArray() {
-        throw new UnsupportedOperationException("Object[] toArray()");
-    }
-
-    /**
-     * {@inheritDoc}
-     * @throws UnsupportedOperationException - this operation is not supported
-     */
-    public <T> T[] toArray(T[] a) {
-        throw new UnsupportedOperationException("<T> T[] toArray(T[] a)");
-    }
-
-    /**
-     * {@inheritDoc}
-     * @throws UnsupportedOperationException - this operation is not supported
-     */
-    public E element() {
-        throw new UnsupportedOperationException("E element()");
-    }
-
-    /**
-     * {@inheritDoc}
-     * @throws UnsupportedOperationException - this operation is not supported
-     */
-    public E peek() {
-        throw new UnsupportedOperationException("E peek()");
-    }
-
-    /**
-     * {@inheritDoc}
-     * @throws UnsupportedOperationException - this operation is not supported
-     */
-    public E remove() {
-        throw new UnsupportedOperationException("E remove()");
-    }
-
-
-
-    //------------------------------------------------------------------
-    // Non cancellable Future used to check and see if a connection has been made available
-    //------------------------------------------------------------------
-    protected class ItemFuture<T> implements Future<T> {
-        protected volatile T item = null;
-        protected volatile ExchangeCountDownLatch<T> latch = null;
-        protected volatile boolean canceled = false;
-        
-        public ItemFuture(T item) {
-            this.item = item;
-        }
-        
-        public ItemFuture(ExchangeCountDownLatch<T> latch) {
-            this.latch = latch;
-        }
-        
-        public boolean cancel(boolean mayInterruptIfRunning) {
-            return false; //don't allow cancel for now
-        }
-
-        public T get() throws InterruptedException, ExecutionException {
-            if (item!=null) {
-                return item;
-            } else if (latch!=null) {
-                latch.await();
-                return latch.getItem();
-            } else {
-                throw new ExecutionException("ItemFuture incorrectly instantiated. Bug in the code?", new Exception());
-            }
-        }
-
-        public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
-            if (item!=null) {
-                return item;
-            } else if (latch!=null) {
-                boolean timedout = !latch.await(timeout, unit);
-                if (timedout) throw new TimeoutException();
-                else return latch.getItem();
-            } else {
-                throw new ExecutionException("ItemFuture incorrectly instantiated. Bug in the code?", new Exception());
-            }
-        }
-
-        public boolean isCancelled() {
-            return false;
-        }
-
-        public boolean isDone() {
-            return (item!=null || latch.getItem()!=null);
-        }
-        
-    }
-
-    //------------------------------------------------------------------
-    // Count down latch that can be used to exchange information
-    //------------------------------------------------------------------
-    protected class ExchangeCountDownLatch<T> extends CountDownLatch {
-        protected volatile T item;
-        public ExchangeCountDownLatch(int i) {
-            super(i);
-        }
-        public T getItem() {
-            return item;
-        }
-        public void setItem(T item) {
-            this.item = item;
-        }
-    }
-
-    //------------------------------------------------------------------
-    // Iterator safe from concurrent modification exceptions
-    //------------------------------------------------------------------
-    protected class FairIterator implements Iterator<E> {
-        E[] elements = null;
-        int index;
-        E element = null;
-
-        public FairIterator() {
-            final ReentrantLock lock = FairBlockingQueue.this.lock;
-            lock.lock();
-            try {
-                elements = (E[]) new Object[FairBlockingQueue.this.items.size()];
-                FairBlockingQueue.this.items.toArray(elements);
-                index = 0;
-            } finally {
-                lock.unlock();
-            }
-        }
-        public boolean hasNext() {
-            return index<elements.length;
-        }
-
-        public E next() {
-            if (!hasNext()) {
-                throw new NoSuchElementException();
-            }
-            element = elements[index++];
-            return element;
-        }
-
-        public void remove() {
-            final ReentrantLock lock = FairBlockingQueue.this.lock;
-            lock.lock();
-            try {
-                if (element!=null) {
-                    FairBlockingQueue.this.items.remove(element);
-                }
-            } finally {
-                lock.unlock();
-            }
-        }
-
-    }
-}
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/JdbcInterceptor.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/JdbcInterceptor.java
deleted file mode 100644 (file)
index 8d8096c..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * 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.pool;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.util.Map;
-
-import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty;
-
-/**
- * Abstract class that is to be extended for implementations of interceptors.
- * Everytime an operation is called on the {@link java.sql.Connection} object the 
- * {@link #invoke(Object, Method, Object[])} method on the interceptor will be called.
- * Interceptors are useful to change or improve behavior of the connection pool.<br/>
- * Interceptors can receive a set of properties. Each sub class is responsible for parsing the properties during runtime when they 
- * are needed or simply override the {@link #setProperties(Map)} method. 
- * Properties arrive in a key-value pair of Strings as they were received through the configuration.
- * This method is called once per cached connection object when the object is first configured.
- * 
- * @author Filip Hanik
- * @version 1.0
- */
-public abstract class JdbcInterceptor implements InvocationHandler {
-    /**
-     * {@link java.sql.Connection#close()} method name
-     */
-    public static final String CLOSE_VAL = "close";
-    /**
-     * {@link Object#toString()} method name
-     */
-    public static final String TOSTRING_VAL = "toString";
-    /**
-     * {@link java.sql.Connection#isClosed()} method name
-     */
-    public static final String ISCLOSED_VAL = "isClosed";
-    /**
-     * {@link javax.sql.PooledConnection#getConnection()} method name
-     */
-    public static final String GETCONNECTION_VAL = "getConnection";
-    /**
-     * {@link java.sql.Wrapper#unwrap(Class)} method name
-     */
-    public static final String UNWRAP_VAL = "unwrap";
-    /**
-     * {@link java.sql.Wrapper#isWrapperFor(Class)} method name
-     */
-    public static final String ISWRAPPERFOR_VAL = "isWrapperFor";
-
-    
-    /**
-     * Properties for this interceptor.
-     */
-    protected Map<String,InterceptorProperty> properties = null; 
-    
-    /**
-     * The next interceptor in the chain
-     */
-    private JdbcInterceptor next = null;
-    /**
-     * Property that decides how we do string comparison, default is to use
-     * {@link String#equals(Object)}. If set to <code>false</code> then the
-     * equality operator (==) is used.
-     */
-    private boolean useEquals = true;
-
-    /**
-     * Public constructor for instantation through reflection
-     */
-    public JdbcInterceptor() {
-        // NOOP
-    }
-
-    /**
-     * Gets invoked each time an operation on {@link java.sql.Connection} is invoked.
-     * {@inheritDoc}
-     */
-    
-    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-        if (getNext()!=null) return getNext().invoke(this,method,args);
-        else throw new NullPointerException();
-    }
-
-    /**
-     * Returns the next interceptor in the chain
-     * @return the next interceptor in the chain
-     */
-    public JdbcInterceptor getNext() {
-        return next;
-    }
-
-    /**
-     * configures the next interceptor in the chain
-     * @param next
-     */
-    public void setNext(JdbcInterceptor next) {
-        this.next = next;
-    }
-    
-    /**
-     * Performs a string comparison, using references unless the useEquals property is set to true.
-     * @param name1
-     * @param name2
-     * @return true if name1 is equal to name2 based on {@link #useEquals}
-     */
-    public boolean compare(String name1, String name2) {
-        if (isUseEquals()) {
-            return name1.equals(name2);
-        } else {
-            return name1==name2;
-        }
-    }
-    
-    /**
-     * Compares a method name (String) to a method (Method)
-     * {@link #compare(String,String)}
-     * Uses reference comparison unless the useEquals property is set to true
-     * @param methodName
-     * @param method
-     * @return true if the name matches
-     */
-    public boolean compare(String methodName, Method method) {
-        return compare(methodName, method.getName());
-    }
-    
-    /**
-     * Gets called each time the connection is borrowed from the pool
-     * This means that if an interceptor holds a reference to the connection
-     * the interceptor can be reused for another connection.
-     * <br/>
-     * This method may be called with null as both arguments when we are closing down the connection.
-     * @param parent - the connection pool owning the connection
-     * @param con - the pooled connection
-     */
-    public abstract void reset(ConnectionPool parent, PooledConnection con);
-    
-    /**
-     * Called when {@link java.sql.Connection#close()} is called on the underlying connection.
-     * This is to notify the interceptors, that the physical connection has been released.
-     * Implementation of this method should be thought through with care, as no actions should trigger an exception.
-     * @param parent - the connection pool that this connection belongs to
-     * @param con    - the pooled connection that holds this connection
-     * @param finalizing - if this connection is finalizing. True means that the pooled connection will not reconnect the underlying connection
-     */
-    public void disconnected(ConnectionPool parent, PooledConnection con, boolean finalizing) {
-    }
-        
-    
-    /**
-     * Returns the properties configured for this interceptor
-     * @return the configured properties for this interceptor
-     */
-    public Map<String,InterceptorProperty> getProperties() {
-        return properties;
-    }
-
-    /**
-     * Called during the creation of an interceptor
-     * The properties can be set during the configuration of an interceptor
-     * Override this method to perform type casts between string values and object properties
-     * @param properties
-     */
-    public void setProperties(Map<String,InterceptorProperty> properties) {
-        this.properties = properties;
-        final String useEquals = "useEquals";
-        InterceptorProperty p = properties.get(useEquals);
-        if (p!=null) {
-            setUseEquals(Boolean.parseBoolean(p.getValue()));
-        }
-    }
-    
-    /**
-     * @return true if the compare method uses the Object.equals(Object) method
-     *         false if comparison is done on a reference level
-     */
-    public boolean isUseEquals() {
-        return useEquals;
-    }
-    
-    /**
-     * Set to true if string comparisons (for the {@link #compare(String, Method)} and {@link #compare(String, String)} methods) should use the Object.equals(Object) method
-     * The default is false
-     * @param useEquals
-     */
-    public void setUseEquals(boolean useEquals) {
-        this.useEquals = useEquals;
-    }
-    
-    /**
-     * This method is invoked by a connection pool when the pool is closed.
-     * Interceptor classes can override this method if they keep static
-     * variables or other tracking means around.
-     * <b>This method is only invoked on a single instance of the interceptor, and not on every instance created.</b>
-     * @param pool - the pool that is being closed.
-     */
-    public void poolClosed(ConnectionPool pool) {
-        // NOOP
-    }
-
-    /**
-     * This method is invoked by a connection pool when the pool is first started up, usually when the first connection is requested.
-     * Interceptor classes can override this method if they keep static
-     * variables or other tracking means around.
-     * <b>This method is only invoked on a single instance of the interceptor, and not on every instance created.</b>
-     * @param pool - the pool that is being closed.
-     */
-    public void poolStarted(ConnectionPool pool) {
-        // NOOP
-    }
-
-}
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/MultiLockFairBlockingQueue.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/MultiLockFairBlockingQueue.java
deleted file mode 100644 (file)
index f5fd28e..0000000
+++ /dev/null
@@ -1,537 +0,0 @@
-/*
- * 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.pool;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.NoSuchElementException;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * <b>EXPERIMENTAL AND NOT YET COMPLETE!</b>
- *
- *
- * An implementation of a blocking queue with fairness waiting and lock dispersal to avoid contention.
- * invocations to method poll(...) will get handed out in the order they were received.
- * Locking is fine grained, a shared lock is only used during the first level of contention, waiting is done in a 
- * lock per thread basis so that order is guaranteed once the thread goes into a suspended monitor state.
- * <br/>
- * Not all of the methods of the {@link java.util.concurrent.BlockingQueue} are implemented.
- * @author Filip Hanik
- *
- */
-
-public class MultiLockFairBlockingQueue<E> implements BlockingQueue<E> {
-    
-    final int LOCK_COUNT = Runtime.getRuntime().availableProcessors();
-    
-    final AtomicInteger putQueue = new AtomicInteger(0);
-    final AtomicInteger pollQueue = new AtomicInteger(0);
-    
-    public int getNextPut() {
-        int idx = Math.abs(putQueue.incrementAndGet()) % LOCK_COUNT;
-        return idx;
-    }
-    
-    public int getNextPoll() {
-        int idx = Math.abs(pollQueue.incrementAndGet()) % LOCK_COUNT;
-        return idx;
-    }
-    /**
-     * Phase one entry lock in order to give out 
-     * per-thread-locks for the waiting phase we have 
-     * a phase one lock during the contention period.
-     */
-    private final ReentrantLock[] locks = new ReentrantLock[LOCK_COUNT];
-
-    /**
-     * All the objects in the pool are stored in a simple linked list
-     */
-    final LinkedList<E>[] items;
-
-    /**
-     * All threads waiting for an object are stored in a linked list
-     */
-    final LinkedList<ExchangeCountDownLatch<E>>[] waiters;
-    
-    /**
-     * Creates a new fair blocking queue.
-     */
-    public MultiLockFairBlockingQueue() {
-        items = new LinkedList[LOCK_COUNT];
-        waiters = new LinkedList[LOCK_COUNT];
-        for (int i=0; i<LOCK_COUNT; i++) {
-            items[i] = new LinkedList<E>();
-            waiters[i] = new LinkedList<ExchangeCountDownLatch<E>>();
-            locks[i] = new ReentrantLock(false);
-        }
-    }
-
-    //------------------------------------------------------------------
-    // USED BY CONPOOL IMPLEMENTATION
-    //------------------------------------------------------------------
-    /**
-     * Will always return true, queue is unbounded.
-     * {@inheritDoc}
-     */
-    public boolean offer(E e) {
-        int idx = getNextPut();
-        //during the offer, we will grab the main lock
-        final ReentrantLock lock = this.locks[idx];
-        lock.lock();
-        ExchangeCountDownLatch<E> c = null;
-        try {
-            //check to see if threads are waiting for an object
-            if (waiters[idx].size() > 0) {
-                //if threads are waiting grab the latch for that thread
-                c = waiters[idx].poll();
-                //give the object to the thread instead of adding it to the pool
-                c.setItem(e);
-            } else {
-                //we always add first, so that the most recently used object will be given out
-                items[idx].addFirst(e);
-            }
-        } finally {
-            lock.unlock();
-        }
-        //if we exchanged an object with another thread, wake it up.
-        if (c!=null) c.countDown();
-        //we have an unbounded queue, so always return true
-        return true;
-    }
-
-    /**
-     * Will never timeout, as it invokes the {@link #offer(Object)} method.
-     * Once a lock has been acquired, the  
-     * {@inheritDoc}
-     */
-    public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException {
-        return offer(e);
-    }
-
-    /**
-     * Fair retrieval of an object in the queue.
-     * Objects are returned in the order the threads requested them.
-     * {@inheritDoc}
-     */
-    public E poll(long timeout, TimeUnit unit) throws InterruptedException {
-        int idx = getNextPoll();
-        E result = null;
-        final ReentrantLock lock = this.locks[idx];
-        boolean error = true;
-        //acquire the global lock until we know what to do
-        lock.lock();
-        try {
-            //check to see if we have objects
-            result = items[idx].poll();
-            if (result==null && timeout>0) {
-                //the queue is empty we will wait for an object
-                ExchangeCountDownLatch<E> c = new ExchangeCountDownLatch<E>(1);
-                //add to the bottom of the wait list
-                waiters[idx].addLast(c);
-                //unlock the global lock
-                lock.unlock();
-                //wait for the specified timeout
-                if (!c.await(timeout, unit)) {
-                    //if we timed out, remove ourselves from the waitlist
-                    lock.lock();
-                    waiters[idx].remove(c);
-                    lock.unlock();
-                }
-                //return the item we received, can be null if we timed out
-                result = c.getItem();
-            } else {
-                //we have an object, release
-                lock.unlock();
-            }
-            error = false;
-        } finally {
-            if (error && lock.isHeldByCurrentThread()) {
-                lock.unlock();
-            }
-        }
-        return result;
-    }
-    
-    /**
-     * Request an item from the queue asynchronously
-     * @return - a future pending the result from the queue poll request
-     */
-    public Future<E> pollAsync() {
-        int idx = getNextPoll();
-        Future<E> result = null;
-        final ReentrantLock lock = this.locks[idx];
-        boolean error = true;
-        //grab the global lock
-        lock.lock();
-        try {
-            //check to see if we have objects in the queue
-            E item = items[idx].poll();
-            if (item==null) {
-                //queue is empty, add ourselves as waiters
-                ExchangeCountDownLatch<E> c = new ExchangeCountDownLatch<E>(1);
-                waiters[idx].addLast(c);
-                lock.unlock();
-                //return a future that will wait for the object
-                result = new ItemFuture<E>(c);
-            } else {
-                lock.unlock();
-                //return a future with the item
-                result = new ItemFuture<E>(item);
-            }
-            error = false;
-        } finally {
-            if (error && lock.isHeldByCurrentThread()) {
-                lock.unlock();
-            }
-        }
-        return result;
-    }
-    
-    /**
-     * {@inheritDoc}
-     */
-    public boolean remove(Object e) {
-        for (int idx=0; idx<LOCK_COUNT; idx++) {
-            final ReentrantLock lock = this.locks[idx];
-            lock.lock();
-            try {
-                boolean result = items[idx].remove(e);
-                if (result) return result;
-            } finally {
-                lock.unlock();
-            }
-        }
-        return false;
-    }
-    
-    /**
-     * {@inheritDoc}
-     */
-    public int size() {
-        int size = 0;
-        for (int idx=0; idx<LOCK_COUNT; idx++) {
-            size += items[idx].size();
-        }
-        return size;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Iterator<E> iterator() {
-        return new FairIterator();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public E poll() {
-        int idx = getNextPoll();
-        final ReentrantLock lock = this.locks[idx];
-        lock.lock();
-        try {
-            return items[idx].poll();
-        } finally {
-            lock.unlock();
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean contains(Object e) {
-        for (int idx=0; idx<LOCK_COUNT; idx++) {
-            boolean result = items[idx].contains(e);
-            if (result) return result;
-        }
-        return false;
-    }
-
-
-    //------------------------------------------------------------------
-    // NOT USED BY CONPOOL IMPLEMENTATION
-    //------------------------------------------------------------------
-    /**
-     * {@inheritDoc}
-     */
-    public boolean add(E e) {
-        return offer(e);
-    }
-
-    /**
-     * {@inheritDoc}
-     * @throws UnsupportedOperationException - this operation is not supported
-     */
-    public int drainTo(Collection<? super E> c, int maxElements) {
-        throw new UnsupportedOperationException("int drainTo(Collection<? super E> c, int maxElements)");
-    }
-
-    /**
-     * {@inheritDoc}
-     * @throws UnsupportedOperationException - this operation is not supported
-     */
-    public int drainTo(Collection<? super E> c) {
-        return drainTo(c,Integer.MAX_VALUE);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void put(E e) throws InterruptedException {
-        offer(e);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public int remainingCapacity() {
-        return Integer.MAX_VALUE - size();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public E take() throws InterruptedException {
-        return this.poll(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean addAll(Collection<? extends E> c) {
-        Iterator<? extends E> i = c.iterator();
-        while (i.hasNext()) {
-            E e = i.next();
-            offer(e);
-        }
-        return true;
-    }
-
-    /**
-     * {@inheritDoc}
-     * @throws UnsupportedOperationException - this operation is not supported
-     */
-    public void clear() {
-        throw new UnsupportedOperationException("void clear()");
-
-    }
-
-    /**
-     * {@inheritDoc}
-     * @throws UnsupportedOperationException - this operation is not supported
-     */
-    public boolean containsAll(Collection<?> c) {
-        throw new UnsupportedOperationException("boolean containsAll(Collection<?> c)");
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isEmpty() {
-        return size() == 0;
-    }
-
-    /**
-     * {@inheritDoc}
-     * @throws UnsupportedOperationException - this operation is not supported
-     */
-    public boolean removeAll(Collection<?> c) {
-        throw new UnsupportedOperationException("boolean removeAll(Collection<?> c)");
-    }
-
-    /**
-     * {@inheritDoc}
-     * @throws UnsupportedOperationException - this operation is not supported
-     */
-    public boolean retainAll(Collection<?> c) {
-        throw new UnsupportedOperationException("boolean retainAll(Collection<?> c)");
-    }
-
-    /**
-     * {@inheritDoc}
-     * @throws UnsupportedOperationException - this operation is not supported
-     */
-    public Object[] toArray() {
-        throw new UnsupportedOperationException("Object[] toArray()");
-    }
-
-    /**
-     * {@inheritDoc}
-     * @throws UnsupportedOperationException - this operation is not supported
-     */
-    public <T> T[] toArray(T[] a) {
-        throw new UnsupportedOperationException("<T> T[] toArray(T[] a)");
-    }
-
-    /**
-     * {@inheritDoc}
-     * @throws UnsupportedOperationException - this operation is not supported
-     */
-    public E element() {
-        throw new UnsupportedOperationException("E element()");
-    }
-
-    /**
-     * {@inheritDoc}
-     * @throws UnsupportedOperationException - this operation is not supported
-     */
-    public E peek() {
-        throw new UnsupportedOperationException("E peek()");
-    }
-
-    /**
-     * {@inheritDoc}
-     * @throws UnsupportedOperationException - this operation is not supported
-     */
-    public E remove() {
-        throw new UnsupportedOperationException("E remove()");
-    }
-
-
-
-    //------------------------------------------------------------------
-    // Non cancellable Future used to check and see if a connection has been made available
-    //------------------------------------------------------------------
-    protected class ItemFuture<T> implements Future<T> {
-        protected volatile T item = null;
-        protected volatile ExchangeCountDownLatch<T> latch = null;
-        protected volatile boolean canceled = false;
-        
-        public ItemFuture(T item) {
-            this.item = item;
-        }
-        
-        public ItemFuture(ExchangeCountDownLatch<T> latch) {
-            this.latch = latch;
-        }
-        
-        public boolean cancel(boolean mayInterruptIfRunning) {
-            return false; //don't allow cancel for now
-        }
-
-        public T get() throws InterruptedException, ExecutionException {
-            if (item!=null) {
-                return item;
-            } else if (latch!=null) {
-                latch.await();
-                return latch.getItem();
-            } else {
-                throw new ExecutionException("ItemFuture incorrectly instantiated. Bug in the code?", new Exception());
-            }
-        }
-
-        public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
-            if (item!=null) {
-                return item;
-            } else if (latch!=null) {
-                boolean timedout = !latch.await(timeout, unit);
-                if (timedout) throw new TimeoutException();
-                else return latch.getItem();
-            } else {
-                throw new ExecutionException("ItemFuture incorrectly instantiated. Bug in the code?", new Exception());
-            }
-        }
-
-        public boolean isCancelled() {
-            return false;
-        }
-
-        public boolean isDone() {
-            return (item!=null || latch.getItem()!=null);
-        }
-        
-    }
-
-    //------------------------------------------------------------------
-    // Count down latch that can be used to exchange information
-    //------------------------------------------------------------------
-    protected class ExchangeCountDownLatch<T> extends CountDownLatch {
-        protected volatile T item;
-        public ExchangeCountDownLatch(int i) {
-            super(i);
-        }
-        public T getItem() {
-            return item;
-        }
-        public void setItem(T item) {
-            this.item = item;
-        }
-    }
-
-    //------------------------------------------------------------------
-    // Iterator safe from concurrent modification exceptions
-    //------------------------------------------------------------------
-    protected class FairIterator implements Iterator<E> {
-        E[] elements = null;
-        int index;
-        E element = null;
-
-        public FairIterator() {
-            ArrayList<E> list = new ArrayList<E>(MultiLockFairBlockingQueue.this.size());
-            for (int idx=0; idx<LOCK_COUNT; idx++) {
-                final ReentrantLock lock = MultiLockFairBlockingQueue.this.locks[idx];
-                lock.lock();
-                try {
-                    elements = (E[]) new Object[MultiLockFairBlockingQueue.this.items[idx].size()];
-                    MultiLockFairBlockingQueue.this.items[idx].toArray(elements);
-                    
-                } finally {
-                    lock.unlock();
-                }
-            }
-            index = 0;
-            elements = (E[]) new Object[list.size()];
-            list.toArray(elements);
-        }
-        public boolean hasNext() {
-            return index<elements.length;
-        }
-
-        public E next() {
-            if (!hasNext()) {
-                throw new NoSuchElementException();
-            }
-            element = elements[index++];
-            return element;
-        }
-
-        public void remove() {
-            for (int idx=0; idx<LOCK_COUNT; idx++) {
-                final ReentrantLock lock = MultiLockFairBlockingQueue.this.locks[idx];
-                lock.lock();
-                try {
-                    boolean result = MultiLockFairBlockingQueue.this.items[idx].remove(elements[index]);
-                    if (result) break;
-                } finally {
-                    lock.unlock();
-                }
-            }
-            
-        }
-
-    }
-}
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolConfiguration.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolConfiguration.java
deleted file mode 100644 (file)
index b8d2515..0000000
+++ /dev/null
@@ -1,791 +0,0 @@
-/*
- * 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.pool;
-
-import java.util.Properties;
-
-import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorDefinition;
-
-/**
- * A list of properties that are configurable for a connection pool.
- * The {@link DataSource} object also implements this interface so that it can be easily configured through
- * an IoC container without having to specify a secondary object with a setter method.
- * @author fhanik
- *
- */
-
-public interface PoolConfiguration {
-
-    /**
-     * JMX prefix for interceptors that register themselves with JMX
-     */
-    public static final String PKG_PREFIX = "org.apache.tomcat.jdbc.pool.interceptor.";
-
-    /**
-     * Connections that have been abandoned (timed out) wont get closed and reported up unless the number of connections in use are 
-     * above the percentage defined by abandonWhenPercentageFull. 
-     * The value should be between 0-100. 
-     * The default value is 0, which implies that connections are eligible for 
-     * closure as soon as removeAbandonedTimeout has been reached.
-     * @param percentage a value between 0 and 100 to indicate when connections that have been abandoned/timed out are considered abandoned
-     */
-    public void setAbandonWhenPercentageFull(int percentage);
-
-    /**
-     * Connections that have been abandoned (timed out) wont get closed and reported up unless the number of connections in use are 
-     * above the percentage defined by abandonWhenPercentageFull. 
-     * The value should be between 0-100. 
-     * The default value is 0, which implies that connections are eligible for 
-     * closure as soon as removeAbandonedTimeout has been reached.
-     * @return percentage - a value between 0 and 100 to indicate when connections that have been abandoned/timed out are considered abandoned
-     */
-    public int getAbandonWhenPercentageFull();
-
-    /**
-     * Returns true if a fair queue is being used by the connection pool
-     * @return true if a fair waiting queue is being used
-     */
-    public boolean isFairQueue();
-
-    /**
-     * Set to true if you wish that calls to getConnection 
-     * should be treated fairly in a true FIFO fashion. 
-     * This uses the {@link FairBlockingQueue} implementation for the list of the idle connections. 
-     * The default value is true. 
-     * This flag is required when you want to use asynchronous connection retrieval.
-     * @param fairQueue
-     */
-    public void setFairQueue(boolean fairQueue);
-    
-    /**
-     * Property not used. Access is always allowed.
-     * Access can be achieved by calling unwrap on the pooled connection. see {@link javax.sql.DataSource} interface 
-     * or call getConnection through reflection or cast the object as {@link javax.sql.PooledConnection}
-     * @return true
-     */
-    public boolean isAccessToUnderlyingConnectionAllowed();
-
-    /**
-     * No-op
-     * @param accessToUnderlyingConnectionAllowed parameter ignored
-     */
-    public void setAccessToUnderlyingConnectionAllowed(boolean accessToUnderlyingConnectionAllowed);
-    
-    /**
-     * The connection properties that will be sent to the JDBC driver when establishing new connections. 
-     * Format of the string is [propertyName=property;] <br/>
-     * NOTE - The "user" and "password" properties will be passed explicitly, so they do not need to be included here. 
-     * The default value is null.
-     */
-    public String getConnectionProperties();
-
-    /**
-     * The properties that will be passed into {@link java.sql.Driver#connect(String, Properties)} method.
-     * Username and password do not need to be stored here, they will be passed into the properties right before the connection is established.
-     * @param connectionProperties properties - Format of the string is [propertyName=property;]* 
-     * Example: prop1=value1;prop2=value2
-     */
-    public void setConnectionProperties(String connectionProperties);
-    
-    /**
-     * Returns the database properties that are passed into the {@link java.sql.Driver#connect(String, Properties)} method.
-     * @return database properties that are passed into the {@link java.sql.Driver#connect(String, Properties)} method.
-     */
-    public Properties getDbProperties();
-
-    /**
-     * Overrides the database properties passed into the  {@link java.sql.Driver#connect(String, Properties)} method.
-     * @param dbProperties
-     */
-    public void setDbProperties(Properties dbProperties);
-    
-    /**
-     * The default auto-commit state of connections created by this pool. 
-     * If not set (null), default is JDBC driver default (If set to null then the {@link java.sql.Connection#setAutoCommit(boolean)} method will not be called.)
-     * @return the default auto commit setting, null is Driver default.
-     */
-    public Boolean isDefaultAutoCommit();
-    
-    /**
-     * The default auto-commit state of connections created by this pool. 
-     * If not set (null), default is JDBC driver default (If set to null then the {@link java.sql.Connection#setAutoCommit(boolean)} method will not be called.)
-     * @return the default auto commit setting, null is Driver default.
-     */
-    public Boolean getDefaultAutoCommit();
-    
-    /**
-     * The default auto-commit state of connections created by this pool. 
-     * If not set (null), default is JDBC driver default (If set to null then the {@link java.sql.Connection#setAutoCommit(boolean)} method will not be called.)
-     * @param defaultAutoCommit default auto commit setting, null is Driver default.
-     */
-    public void setDefaultAutoCommit(Boolean defaultAutoCommit);
-
-    /**
-     * If non null, during connection creation the method {@link java.sql.Connection#setCatalog(String)} will be called with the set value.
-     * @return the default catalog, null if not set and accepting the driver default.
-     */
-    public String getDefaultCatalog();
-    
-    /**
-     * If non null, during connection creation the method {@link java.sql.Connection#setCatalog(String)} will be called with the set value.
-     * @param defaultCatalog null if not set and accepting the driver default.
-     */
-    public void setDefaultCatalog(String defaultCatalog);
-    
-    /**
-     * If non null, during connection creation the method {@link java.sql.Connection#setReadOnly(boolean)} will be called with the set value.
-     * @return null if not set and accepting the driver default otherwise the read only value
-     */
-    public Boolean isDefaultReadOnly();
-
-    /**
-     * If non null, during connection creation the method {@link java.sql.Connection#setReadOnly(boolean)} will be called with the set value.
-     * @return null if not set and accepting the driver default otherwise the read only value
-     */
-    public Boolean getDefaultReadOnly();
-
-    /**
-     * If non null, during connection creation the method {@link java.sql.Connection#setReadOnly(boolean)} will be called with the set value.
-     * @param defaultReadOnly null if not set and accepting the driver default.
-     */
-    public void setDefaultReadOnly(Boolean defaultReadOnly);
-
-    
-    /**
-     * Returns the default transaction isolation level. If set to {@link DataSourceFactory#UNKNOWN_TRANSACTIONISOLATION} the method
-     * {@link java.sql.Connection#setTransactionIsolation(int)} will not be called during connection creation.
-     * @return driver transaction isolation level, or -1 {@link DataSourceFactory#UNKNOWN_TRANSACTIONISOLATION} if not set.
-     */
-    public int getDefaultTransactionIsolation();
-    
-    /**
-     * If set to {@link DataSourceFactory#UNKNOWN_TRANSACTIONISOLATION} the method
-     * {@link java.sql.Connection#setTransactionIsolation(int)} will not be called during connection creation. Otherwise the method 
-     * will be called with the isolation level set by this property.
-     * @param defaultTransactionIsolation a value of {@link java.sql.Connection#TRANSACTION_NONE}, {@link java.sql.Connection#TRANSACTION_READ_COMMITTED},
-     * {@link java.sql.Connection#TRANSACTION_READ_UNCOMMITTED}, {@link java.sql.Connection#TRANSACTION_REPEATABLE_READ}, 
-     * {@link java.sql.Connection#TRANSACTION_SERIALIZABLE} or {@link DataSourceFactory#UNKNOWN_TRANSACTIONISOLATION}
-     * The last value will not be set on the connection.
-     */
-    public void setDefaultTransactionIsolation(int defaultTransactionIsolation);
-
-    /**
-     * The fully qualified Java class name of the JDBC driver to be used. The driver has to be accessible from the same classloader as tomcat-jdbc.jar
-     * @return fully qualified JDBC driver name. 
-     */
-    public String getDriverClassName();
-    
-    /**
-     * The fully qualified Java class name of the JDBC driver to be used. The driver has to be accessible from the same classloader as tomcat-jdbc.jar
-     * @param driverClassName a fully qualified Java class name of a {@link java.sql.Driver} implementation.
-     */
-    public void setDriverClassName(String driverClassName);
-    
-    /**
-     * Returns the number of connections that will be established when the connection pool is started.
-     * Default value is 10 
-     * @return number of connections to be started when pool is started
-     */
-    public int getInitialSize();
-    
-    /**
-     * Set the number of connections that will be established when the connection pool is started.
-     * Default value is 10.
-     * If this value exceeds {@link #setMaxActive(int)} it will automatically be lowered. 
-     * @param initialSize the number of connections to be established.
-     * 
-     */
-    public void setInitialSize(int initialSize);
-
-    /**
-     * boolean flag to set if stack traces should be logged for application code which abandoned a Connection. 
-     * Logging of abandoned Connections adds overhead for every Connection borrow because a stack trace has to be generated. 
-     * The default value is false.
-     * @return true if the connection pool logs stack traces when connections are borrowed from the pool.
-     */
-    public boolean isLogAbandoned();
-    
-    /**
-     * boolean flag to set if stack traces should be logged for application code which abandoned a Connection. 
-     * Logging of abandoned Connections adds overhead for every Connection borrow because a stack trace has to be generated. 
-     * The default value is false.
-     * @param logAbandoned set to true if stack traces should be recorded when {@link DataSource#getConnection()} is called.
-     */
-    public void setLogAbandoned(boolean logAbandoned);
-
-    /**
-     * The maximum number of active connections that can be allocated from this pool at the same time. The default value is 100
-     * @return the maximum number of connections used by this pool
-     */
-    public int getMaxActive();
-    
-    /**
-     * The maximum number of active connections that can be allocated from this pool at the same time. The default value is 100
-     * @param maxActive hard limit for number of managed connections by this pool
-     */
-    public void setMaxActive(int maxActive);
-
-    
-    /**
-     * The maximum number of connections that should be kept in the idle pool if {@link #isPoolSweeperEnabled()} returns false.
-     * If the If {@link #isPoolSweeperEnabled()} returns true, then the idle pool can grow up to {@link #getMaxActive}
-     * and will be shrunk according to {@link #getMinEvictableIdleTimeMillis()} setting.
-     * Default value is maxActive:100  
-     * @return the maximum number of idle connections.
-     */
-    public int getMaxIdle();
-    
-    /**
-     * The maximum number of connections that should be kept in the idle pool if {@link #isPoolSweeperEnabled()} returns false.
-     * If the If {@link #isPoolSweeperEnabled()} returns true, then the idle pool can grow up to {@link #getMaxActive}
-     * and will be shrunk according to {@link #getMinEvictableIdleTimeMillis()} setting.
-     * Default value is maxActive:100  
-     * @param maxIdle the maximum size of the idle pool
-     */
-    public void setMaxIdle(int maxIdle);
-
-    /**
-     * The maximum number of milliseconds that the pool will wait (when there are no available connections and the 
-     * {@link #getMaxActive} has been reached) for a connection to be returned 
-     * before throwing an exception. Default value is 30000 (30 seconds)
-     * @return the number of milliseconds to wait for a connection to become available if the pool is maxed out.
-     */
-    public int getMaxWait();
-
-    /**
-     * The maximum number of milliseconds that the pool will wait (when there are no available connections and the 
-     * {@link #getMaxActive} has been reached) for a connection to be returned 
-     * before throwing an exception. Default value is 30000 (30 seconds)
-     * @param maxWait the maximum number of milliseconds to wait.
-     */
-    public void setMaxWait(int maxWait);
-
-    /**
-     * The minimum amount of time an object must sit idle in the pool before it is eligible for eviction. 
-     * The default value is 60000 (60 seconds).
-     * @return the minimum amount of idle time in milliseconds before a connection is considered idle and eligible for eviction. 
-     */
-    public int getMinEvictableIdleTimeMillis();
-    
-    /**
-     * The minimum amount of time an object must sit idle in the pool before it is eligible for eviction. 
-     * The default value is 60000 (60 seconds).
-     * @param minEvictableIdleTimeMillis the number of milliseconds a connection must be idle to be eligible for eviction.
-     */
-    public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis);
-
-    /**
-     * The minimum number of established connections that should be kept in the pool at all times. 
-     * The connection pool can shrink below this number if validation queries fail and connections get closed. 
-     * Default value is derived from {@link #getInitialSize()} (also see {@link #setTestWhileIdle(boolean)}
-     * The idle pool will not shrink below this value during an eviction run, hence the number of actual connections
-     * can be between {@link #getMinIdle()} and somewhere between {@link #getMaxIdle()} and {@link #getMaxActive()}
-     * @return the minimum number of idle or established connections
-     */
-    public int getMinIdle();
-    
-    /**
-     * The minimum number of established connections that should be kept in the pool at all times. 
-     * The connection pool can shrink below this number if validation queries fail and connections get closed. 
-     * Default value is derived from {@link #getInitialSize()} (also see {@link #setTestWhileIdle(boolean)}
-     * The idle pool will not shrink below this value during an eviction run, hence the number of actual connections
-     * can be between {@link #getMinIdle()} and somewhere between {@link #getMaxIdle()} and {@link #getMaxActive()}
-     * 
-     * @param minIdle the minimum number of idle or established connections
-     */
-    public void setMinIdle(int minIdle);
-
-    /**
-     * Returns the name of the connection pool. By default a JVM unique random name is assigned.
-     * @return the name of the pool, should be unique in a JVM
-     */
-    public String getName();
-    
-    /**
-     * Sets the name of the connection pool 
-     * @param name the name of the pool, should be unique in a runtime JVM
-     */
-    public void setName(String name);
-
-    /**
-     * Property not used
-     * @return unknown value
-     */
-    public int getNumTestsPerEvictionRun();
-    
-    /**
-     * Property not used
-     * @param numTestsPerEvictionRun parameter ignored.
-     */
-    public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun);
-
-    /**
-     * Returns the password used when establishing connections to the database.
-     * @return the password in string format
-     */
-    public String getPassword();
-    
-    /**
-     * Sets the password to establish the connection with.
-     * The password will be included as a database property with the name 'password'.
-     * @param password 
-     * @see #getDbProperties()
-     */
-    public void setPassword(String password);
-
-    /**
-     * @see #getName()
-     * @return name
-     */
-    public String getPoolName();
-    
-    /**
-     * Returns the username used to establish the connection with
-     * @return the username used to establish the connection with
-     */
-    public String getUsername();
-
-    /**
-     * Sets the username used to establish the connection with
-     * It will also be a property called 'user' in the database properties.
-     * @param username
-     * @see #getDbProperties()
-     */
-    public void setUsername(String username);
-
-
-    /**
-     * boolean flag to remove abandoned connections if they exceed the removeAbandonedTimout. 
-     * If set to true a connection is considered abandoned and eligible for removal if it has 
-     * been in use longer than the {@link #getRemoveAbandonedTimeout()} and the condition for 
-     * {@link #getAbandonWhenPercentageFull()} is met.
-     * Setting this to true can recover db connections from applications that fail to close a connection. 
-     * See also {@link #isLogAbandoned()} The default value is false.
-     * @return true if abandoned connections can be closed and expelled out of the pool
-     */
-    public boolean isRemoveAbandoned();
-    
-    /**
-     * boolean flag to remove abandoned connections if they exceed the removeAbandonedTimout. 
-     * If set to true a connection is considered abandoned and eligible for removal if it has 
-     * been in use longer than the {@link #getRemoveAbandonedTimeout()} and the condition for 
-     * {@link #getAbandonWhenPercentageFull()} is met.
-     * Setting this to true can recover db connections from applications that fail to close a connection. 
-     * See also {@link #isLogAbandoned()} The default value is false.
-     * @param removeAbandoned set to true if abandoned connections can be closed and expelled out of the pool
-     */
-    public void setRemoveAbandoned(boolean removeAbandoned);
-
-    /**
-     * The time in seconds before a connection can be considered abandoned.
-     * The timer can be reset upon queries using an interceptor.
-     * @param removeAbandonedTimeout the time in seconds before a used connection can be considered abandoned
-     * @see org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer
-     */
-    public void setRemoveAbandonedTimeout(int removeAbandonedTimeout);
-
-    /**
-     * The time in seconds before a connection can be considered abandoned.
-     * The timer can be reset upon queries using an interceptor.
-     * @see org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer
-     * @return the time in seconds before a used connection can be considered abandoned
-     */ 
-    public int getRemoveAbandonedTimeout();
-
-    /**
-     * The indication of whether objects will be validated before being borrowed from the pool. 
-     * If the object fails to validate, it will be dropped from the pool, and we will attempt to borrow another. 
-     * NOTE - for a true value to have any effect, the validationQuery parameter must be set to a non-null string. 
-     * Default value is false
-     * In order to have a more efficient validation, see {@link #setValidationInterval(long)}
-     * @return true if the connection is to be validated upon borrowing a connection from the pool
-     * @see #getValidationInterval()
-     */
-    public boolean isTestOnBorrow();
-    
-    /**
-     * The indication of whether objects will be validated before being borrowed from the pool. 
-     * If the object fails to validate, it will be dropped from the pool, and we will attempt to borrow another. 
-     * NOTE - for a true value to have any effect, the validationQuery parameter must be set to a non-null string. 
-     * Default value is false
-     * In order to have a more efficient validation, see {@link #setValidationInterval(long)}
-     * @param testOnBorrow set to true if validation should take place before a connection is handed out to the application
-     * @see #getValidationInterval()
-     */
-    public void setTestOnBorrow(boolean testOnBorrow);
-    
-    /**
-     * The indication of whether objects will be validated after being returned to the pool. 
-     * If the object fails to validate, it will be dropped from the pool. 
-     * NOTE - for a true value to have any effect, the validationQuery parameter must be set to a non-null string. 
-     * Default value is false
-     * In order to have a more efficient validation, see {@link #setValidationInterval(long)}
-     * @return true if validation should take place after a connection is returned to the pool
-     * @see #getValidationInterval()
-     */
-    public boolean isTestOnReturn();
-
-    /**
-     * The indication of whether objects will be validated after being returned to the pool. 
-     * If the object fails to validate, it will be dropped from the pool. 
-     * NOTE - for a true value to have any effect, the validationQuery parameter must be set to a non-null string. 
-     * Default value is false
-     * In order to have a more efficient validation, see {@link #setValidationInterval(long)}
-     * @param testOnReturn true if validation should take place after a connection is returned to the pool
-     * @see #getValidationInterval()
-     */
-    public void setTestOnReturn(boolean testOnReturn);
-    
-    
-    /**
-     * Set to true if query validation should take place while the connection is idle.
-     * @return true if validation should take place during idle checks
-     * @see #setTimeBetweenEvictionRunsMillis(int)
-     */
-    public boolean isTestWhileIdle();
-    
-    /**
-     * Set to true if query validation should take place while the connection is idle.
-     * @param testWhileIdle true if validation should take place during idle checks
-     * @see #setTimeBetweenEvictionRunsMillis(int)
-     */
-    public void setTestWhileIdle(boolean testWhileIdle);
-    
-    /**
-     * The number of milliseconds to sleep between runs of the idle connection validation, abandoned cleaner 
-     * and idle pool resizing. This value should not be set under 1 second. 
-     * It dictates how often we check for idle, abandoned connections, and how often we validate idle connection and resize the idle pool.
-     * The default value is 5000 (5 seconds)
-     * @return the sleep time in between validations in milliseconds
-     */
-    public int getTimeBetweenEvictionRunsMillis();
-    
-    /**
-     * The number of milliseconds to sleep between runs of the idle connection validation, abandoned cleaner 
-     * and idle pool resizing. This value should not be set under 1 second. 
-     * It dictates how often we check for idle, abandoned connections, and how often we validate idle connection and resize the idle pool.
-     * The default value is 5000 (5 seconds)
-     * @param timeBetweenEvictionRunsMillis the sleep time in between validations in milliseconds
-     */
-    public void setTimeBetweenEvictionRunsMillis(int timeBetweenEvictionRunsMillis);
-    
-    /**
-     * The URL used to connect to the database
-     * @return the configured URL for this connection pool
-     * @see java.sql.Driver#connect(String, Properties)
-     */
-    public String getUrl();
-    
-    /**
-     * Sets the URL used to connect to the database
-     * @param url the configured URL for this connection pool
-     * @see java.sql.Driver#connect(String, Properties)
-     */
-    public void setUrl(String url);
-    
-    /**
-     * The SQL query that will be used to validate connections from this 
-     * pool before returning them to the caller or pool. 
-     * If specified, this query does not have to return any data, 
-     * it just can't throw a SQLException. 
-     * The default value is null. 
-     * Example values are SELECT 1(mysql), 
-     * select 1 from dual(oracle), 
-     * SELECT 1(MS Sql Server)
-     * @return the query used for validation or null if no validation is performed
-     */
-    public String getValidationQuery();
-    
-    /**
-     * The SQL query that will be used to validate connections from this 
-     * pool before returning them to the caller or pool. 
-     * If specified, this query does not have to return any data, 
-     * it just can't throw a SQLException. 
-     * The default value is null. 
-     * Example values are SELECT 1(mysql), 
-     * select 1 from dual(oracle), 
-     * SELECT 1(MS Sql Server)
-     * @param validationQuery the query used for validation or null if no validation is performed
-     */
-    public void setValidationQuery(String validationQuery);
-    
-    /**
-     * Return the name of the optional validator class - may be null.
-     *  
-     * @return the name of the optional validator class - may be null
-     */
-    public String getValidatorClassName();
-    
-    /**
-     * Set the name for an optional validator class which will be used in place of test queries. If set to
-     * null, standard validation will be used.
-     * 
-     * @param className the name of the optional validator class
-     */
-    public void setValidatorClassName(String className);
-    
-    /**
-     * @return the optional validator object - may be null
-     */
-    public Validator getValidator();
-
-    /**
-     * avoid excess validation, only run validation at most at this frequency - time in milliseconds. 
-     * If a connection is due for validation, but has been validated previously 
-     * within this interval, it will not be validated again. 
-     * The default value is 30000 (30 seconds).
-     * @return the validation interval in milliseconds
-     */
-    public long getValidationInterval();
-    
-    /**
-     * avoid excess validation, only run validation at most at this frequency - time in milliseconds. 
-     * If a connection is due for validation, but has been validated previously 
-     * within this interval, it will not be validated again. 
-     * The default value is 30000 (30 seconds).
-     * @param validationInterval the validation interval in milliseconds
-     */
-    public void setValidationInterval(long validationInterval);
-    
-    /**
-     * A custom query to be run when a connection is first created. The default value is null.
-     * This query only runs once per connection, and that is when a new connection is established to the database.
-     * If this value is non null, it will replace the validation query during connection creation. 
-     * @return the init SQL used to run against the DB or null if not set 
-     */
-    public String getInitSQL();
-    
-    /**
-     * A custom query to be run when a connection is first created. The default value is null.
-     * This query only runs once per connection, and that is when a new connection is established to the database.
-     * If this value is non null, it will replace the validation query during connection creation. 
-     * @param initSQL the init SQL used to run against the DB or null if no query should be executed 
-     */
-    public void setInitSQL(String initSQL);
-
-    /**
-     * Returns true if we should run the validation query when connecting to the database for the first time on a connection.
-     * Normally this is always set to false, unless one wants to use the validationQuery as an init query.
-     * @return true if we should run the validation query upon connect
-     */
-    public boolean isTestOnConnect();
-
-    /**
-     * Set to true if we should run the validation query when connecting to the database for the first time on a connection.
-     * Normally this is always set to false, unless one wants to use the validationQuery as an init query.
-     * Setting an {@link #setInitSQL(String)} will override this setting, as the init SQL will be used instead of the validation query
-     * @param testOnConnect set to true if we should run the validation query upon connect
-     */
-    public void setTestOnConnect(boolean testOnConnect);
-    
-    /**
-     * A semicolon separated list of classnames extending {@link org.apache.tomcat.jdbc.pool.JdbcInterceptor} class. 
-     * These interceptors will be inserted as an interceptor into the chain of operations on a java.sql.Connection object.
-     * Example interceptors are {@link org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer StatementFinalizer} to close all 
-     * used statements during the session.
-     * {@link org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer ResetAbandonedTimer} resets the timer upon every operation
-     * on the connection or a statement.
-     * {@link org.apache.tomcat.jdbc.pool.interceptor.ConnectionState ConnectionState} caches the auto commit, read only and catalog settings to avoid round trips to the DB.
-     * The default value is null.
-     * @return the interceptors that are used for connections.
-     * Example format: 'ConnectionState(useEquals=true,fast=yes);ResetAbandonedTimer'
-     */
-    public String getJdbcInterceptors();
-    
-    /**
-     * A semicolon separated list of classnames extending {@link org.apache.tomcat.jdbc.pool.JdbcInterceptor} class. 
-     * These interceptors will be inserted as an interceptor into the chain of operations on a java.sql.Connection object.
-     * Example interceptors are {@link org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer StatementFinalizer} to close all 
-     * used statements during the session.
-     * {@link org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer ResetAbandonedTimer} resets the timer upon every operation
-     * on the connection or a statement.
-     * {@link org.apache.tomcat.jdbc.pool.interceptor.ConnectionState ConnectionState} caches the auto commit, read only and catalog settings to avoid round trips to the DB.
-     * The default value is null.
-     * @param jdbcInterceptors the interceptors that are used for connections.
-     * Example format: 'ConnectionState(useEquals=true,fast=yes);ResetAbandonedTimer'
-     */
-    public void setJdbcInterceptors(String jdbcInterceptors);
-
-    /**
-     * Returns the {@link #getJdbcInterceptors()} as an array of objects with properties and the classes.
-     * @return an array of interceptors that have been configured
-     */
-    public InterceptorDefinition[] getJdbcInterceptorsAsArray();
-
-    
-    /**
-     * If set to true, the connection pool creates a {@link org.apache.tomcat.jdbc.pool.jmx.ConnectionPoolMBean} object 
-     * that can be registered with JMX to receive notifications and state about the pool.
-     * The ConnectionPool object doesn't register itself, as there is no way to keep a static non changing ObjectName across JVM restarts.
-     * @return true if the mbean object will be created upon startup.
-     */
-    public boolean isJmxEnabled();
-
-    /**
-     * If set to true, the connection pool creates a {@link org.apache.tomcat.jdbc.pool.jmx.ConnectionPoolMBean} object 
-     * that can be registered with JMX to receive notifications and state about the pool.
-     * The ConnectionPool object doesn't register itself, as there is no way to keep a static non changing ObjectName across JVM restarts.
-     * @param jmxEnabled set to to if the mbean object should be created upon startup.
-     */
-    public void setJmxEnabled(boolean jmxEnabled);
-
-    /**
-     * Returns true if the pool sweeper is enabled for the connection pool.
-     * The pool sweeper is enabled if any settings that require async intervention in the pool are turned on
-     * <source>
-        boolean result = getTimeBetweenEvictionRunsMillis()>0;
-        result = result && (isRemoveAbandoned() && getRemoveAbandonedTimeout()>0);
-        result = result || (isTestWhileIdle() && getValidationQuery()!=null);
-        return result;
-       </source> 
-     *
-     * @return true if a background thread is or will be enabled for this pool
-     */
-    public boolean isPoolSweeperEnabled();
-
-    /**
-     * Set to true if you wish the <code>ProxyConnection</code> class to use <code>String.equals</code> instead of 
-     * <code>==</code> when comparing method names. 
-     * This property does not apply to added interceptors as those are configured individually.
-     * The default value is <code>false</code>.
-     * @return true if pool uses {@link String#equals(Object)} instead of == when comparing method names on {@link java.sql.Connection} methods
-     */
-    public boolean isUseEquals();
-
-    /**
-     * Set to true if you wish the <code>ProxyConnection</code> class to use <code>String.equals</code> instead of 
-     * <code>==</code> when comparing method names. 
-     * This property does not apply to added interceptors as those are configured individually.
-     * The default value is <code>false</code>.
-     * @param useEquals set to true if the pool should use {@link String#equals(Object)} instead of ==
-     * when comparing method names on {@link java.sql.Connection} methods
-     */
-    public void setUseEquals(boolean useEquals);
-
-    /**
-     * Time in milliseconds to keep this connection alive even when used. 
-     * When a connection is returned to the pool, the pool will check to see if the 
-     * ((now - time-when-connected) > maxAge) has been reached, and if so, 
-     * it closes the connection rather than returning it to the pool. 
-     * The default value is 0, which implies that connections will be left open and no 
-     * age check will be done upon returning the connection to the pool.
-     * This is a useful setting for database sessions that leak memory as it ensures that the session
-     * will have a finite life span.
-     * @return the time in milliseconds a connection will be open for when used
-     */
-    public long getMaxAge();
-
-    /**
-     * Time in milliseconds to keep this connection alive even when used. 
-     * When a connection is returned to the pool, the pool will check to see if the 
-     * ((now - time-when-connected) > maxAge) has been reached, and if so, 
-     * it closes the connection rather than returning it to the pool. 
-     * The default value is 0, which implies that connections will be left open and no 
-     * age check will be done upon returning the connection to the pool.
-     * This is a useful setting for database sessions that leak memory as it ensures that the session
-     * will have a finite life span.
-     * @param maxAge the time in milliseconds a connection will be open for when used
-     */
-    public void setMaxAge(long maxAge);
-
-    /**
-     * Return true if a lock should be used when operations are performed on the connection object.
-     * Should be set to false unless you plan to have a background thread of your own doing idle and abandon checking
-     * such as JMX clients. If the pool sweeper is enabled, then the lock will automatically be used regardless of this setting.
-     * @return true if a lock is used.
-     */
-    public boolean getUseLock();
-
-    /**
-     * Set to true if a lock should be used when operations are performed on the connection object.
-     * Should be set to false unless you plan to have a background thread of your own doing idle and abandon checking
-     * such as JMX clients. If the pool sweeper is enabled, then the lock will automatically be used regardless of this setting.
-     * @param useLock set to true if a lock should be used on connection operations
-     */
-    public void setUseLock(boolean useLock);
-    
-    /**
-     * Similar to {@link #setRemoveAbandonedTimeout(int)} but instead of treating the connection
-     * as abandoned, and potentially closing the connection, this simply logs the warning if 
-     * {@link #isLogAbandoned()} returns true. If this value is equal or less than 0, no suspect 
-     * checking will be performed. Suspect checking only takes place if the timeout value is larger than 0 and
-     * the connection was not abandoned or if abandon check is disabled. If a connection is suspect a WARN message gets
-     * logged and a JMX notification gets sent once. 
-     * @param seconds - the amount of time in seconds that has to pass before a connection is marked suspect. 
-     */
-    public void setSuspectTimeout(int seconds);
-    
-    /**
-     * Returns the time in seconds to pass before a connection is marked an abanoned suspect.
-     * Any value lesser than or equal to 0 means the check is disabled. 
-     * @return Returns the time in seconds to pass before a connection is marked an abanoned suspect.
-     */
-    public int getSuspectTimeout();
-    
-    /**
-     * Injects a datasource that will be used to retrieve/create connections.
-     * If a data source is set, the {@link PoolConfiguration#getUrl()} and {@link PoolConfiguration#getDriverClassName()} methods are ignored
-     * and not used by the pool. If the {@link PoolConfiguration#getUsername()} and {@link PoolConfiguration#getPassword()}
-     * values are set, the method {@link javax.sql.DataSource#getConnection(String, String)} method will be called instead of the
-     * {@link javax.sql.DataSource#getConnection()} method.
-     * If the data source implements {@link javax.sql.XADataSource} the methods 
-     * {@link javax.sql.XADataSource#getXAConnection()} and {@link javax.sql.XADataSource#getXAConnection(String,String)}
-     * will be invoked.  
-     * @param ds the {@link javax.sql.DataSource} to be used for creating connections to be pooled.
-     */
-    public void setDataSource(Object ds);
-    
-    /**
-     * Returns a datasource, if one exists that is being used to create connections.
-     * This method will return null if the pool is using a {@link java.sql.Driver}
-     * @return the {@link javax.sql.DataSource} to be used for creating connections to be pooled or null if a Driver is used.
-     */
-    public Object getDataSource();
-    
-    /**
-     * Configure the connection pool to use a DataSource according to {@link PoolConfiguration#setDataSource(Object)}
-     * But instead of injecting the object, specify the JNDI location.
-     * After a successful JNDI look, the {@link PoolConfiguration#getDataSource()} will not return null. 
-     * @param jndiDS -the JNDI string @TODO specify the rules here.
-     */
-    public void setDataSourceJNDI(String jndiDS);
-    
-    /**
-     * Returns the JNDI string configured for data source usage.
-     * @return the JNDI string or null if not set
-     */
-    public String getDataSourceJNDI();
-    
-    /**
-     * Returns true if the call {@link DataSource#getConnection(String, String) getConnection(username,password)} is 
-     * allowed. This is used for when the pool is used by an application accessing multiple schemas.
-     * There is a performance impact turning this option on.
-     * @return true if {@link DataSource#getConnection(String, String) getConnection(username,password)} is honored, false if it is ignored.
-     */
-    public boolean isAlternateUsernameAllowed();
-    
-    /**
-     * Set to true if the call {@link DataSource#getConnection(String, String) getConnection(username,password)} is 
-     * allowed and honored.. This is used for when the pool is used by an application accessing multiple schemas.
-     * There is a performance impact turning this option on, even when not used due to username checks.
-     * @param alternateUsernameAllowed - set true if {@link DataSource#getConnection(String, String) getConnection(username,password)} is honored, 
-     * false if it is to be ignored.
-     */
-    public void setAlternateUsernameAllowed(boolean alternateUsernameAllowed);
-    
-
-}
\ No newline at end of file
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolProperties.java
deleted file mode 100644 (file)
index 6fd20d4..0000000
+++ /dev/null
@@ -1,1053 +0,0 @@
-/*
- * 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.pool;
-
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-import java.util.concurrent.atomic.AtomicInteger;
-
-
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-
-/**
- * @author Filip Hanik
- *
- */
-public class PoolProperties implements PoolConfiguration {
-    private static final Log log = LogFactory.getLog(PoolProperties.class);
-    
-    public static final int DEFAULT_MAX_ACTIVE = 100;
-    
-    protected static AtomicInteger poolCounter = new AtomicInteger(0);
-    protected Properties dbProperties = new Properties();
-    protected String url = null;
-    protected String driverClassName = null;
-    protected Boolean defaultAutoCommit = null;
-    protected Boolean defaultReadOnly = null;
-    protected int defaultTransactionIsolation = DataSourceFactory.UNKNOWN_TRANSACTIONISOLATION;
-    protected String defaultCatalog = null;
-    protected String connectionProperties;
-    protected int initialSize = 10;
-    protected int maxActive = DEFAULT_MAX_ACTIVE;
-    protected int maxIdle = maxActive;
-    protected int minIdle = initialSize;
-    protected int maxWait = 30000;
-    protected String validationQuery;
-    protected String validatorClassName;
-    protected Validator validator;
-    protected boolean testOnBorrow = false;
-    protected boolean testOnReturn = false;
-    protected boolean testWhileIdle = false;
-    protected int timeBetweenEvictionRunsMillis = 5000;
-    protected int numTestsPerEvictionRun;
-    protected int minEvictableIdleTimeMillis = 60000;
-    protected final boolean accessToUnderlyingConnectionAllowed = true;
-    protected boolean removeAbandoned = false;
-    protected int removeAbandonedTimeout = 60;
-    protected boolean logAbandoned = false;
-    protected String name = "Tomcat Connection Pool["+(poolCounter.addAndGet(1))+"-"+System.identityHashCode(PoolProperties.class)+"]";
-    protected String password;
-    protected String username;
-    protected long validationInterval = 30000;
-    protected boolean jmxEnabled = true;
-    protected String initSQL;
-    protected boolean testOnConnect =false;
-    protected String jdbcInterceptors=null;
-    protected boolean fairQueue = true;
-    protected boolean useEquals = true;
-    protected int abandonWhenPercentageFull = 0;
-    protected long maxAge = 0;
-    protected boolean useLock = false;
-    protected InterceptorDefinition[] interceptors = null;
-    protected int suspectTimeout = 0;
-    protected Object dataSource = null;
-    protected String dataSourceJNDI = null;
-    protected boolean alternateUsernameAllowed = false;
-    
-    
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setAbandonWhenPercentageFull(int percentage) {
-        if (percentage<0) abandonWhenPercentageFull = 0;
-        else if (percentage>100) abandonWhenPercentageFull = 100;
-        else abandonWhenPercentageFull = percentage;
-    }
-    
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public int getAbandonWhenPercentageFull() {
-        return abandonWhenPercentageFull;
-    }
-    
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public boolean isFairQueue() {
-        return fairQueue;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setFairQueue(boolean fairQueue) {
-        this.fairQueue = fairQueue;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public boolean isAccessToUnderlyingConnectionAllowed() {
-        return accessToUnderlyingConnectionAllowed;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public String getConnectionProperties() {
-        return connectionProperties;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public Properties getDbProperties() {
-        return dbProperties;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public Boolean isDefaultAutoCommit() {
-        return defaultAutoCommit;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public String getDefaultCatalog() {
-        return defaultCatalog;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public Boolean isDefaultReadOnly() {
-        return defaultReadOnly;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public int getDefaultTransactionIsolation() {
-        return defaultTransactionIsolation;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public String getDriverClassName() {
-        return driverClassName;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public int getInitialSize() {
-        return initialSize;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public boolean isLogAbandoned() {
-        return logAbandoned;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public int getMaxActive() {
-        return maxActive;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public int getMaxIdle() {
-        return maxIdle;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public int getMaxWait() {
-        return maxWait;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public int getMinEvictableIdleTimeMillis() {
-        return minEvictableIdleTimeMillis;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public int getMinIdle() {
-        return minIdle;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public String getName() {
-        return name;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public int getNumTestsPerEvictionRun() {
-        return numTestsPerEvictionRun;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public String getPassword() {
-        return password;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public String getPoolName() {
-        return getName();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public boolean isRemoveAbandoned() {
-        return removeAbandoned;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public int getRemoveAbandonedTimeout() {
-        return removeAbandonedTimeout;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public boolean isTestOnBorrow() {
-        return testOnBorrow;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public boolean isTestOnReturn() {
-        return testOnReturn;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public boolean isTestWhileIdle() {
-        return testWhileIdle;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public int getTimeBetweenEvictionRunsMillis() {
-        return timeBetweenEvictionRunsMillis;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public String getUrl() {
-        return url;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public String getUsername() {
-        return username;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public String getValidationQuery() {
-        return validationQuery;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    
-    public String getValidatorClassName() {
-        return validatorClassName;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    
-    public Validator getValidator() {
-        return validator;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public long getValidationInterval() {
-        return validationInterval;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public String getInitSQL() {
-        return initSQL;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public boolean isTestOnConnect() {
-        return testOnConnect;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public String getJdbcInterceptors() {
-        return jdbcInterceptors;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public InterceptorDefinition[] getJdbcInterceptorsAsArray() {
-        if (interceptors == null) {
-            if (jdbcInterceptors==null) {
-                interceptors = new InterceptorDefinition[0];
-            } else {
-                String[] interceptorValues = jdbcInterceptors.split(";");
-                InterceptorDefinition[] definitions = new InterceptorDefinition[interceptorValues.length];
-                for (int i=0; i<interceptorValues.length; i++) {
-                    int propIndex = interceptorValues[i].indexOf("(");
-                    int endIndex = interceptorValues[i].indexOf(")");
-                    if (propIndex<0 || endIndex<0 || endIndex <= propIndex) {
-                        definitions[i] = new InterceptorDefinition(interceptorValues[i].trim());
-                    } else {
-                        String name = interceptorValues[i].substring(0,propIndex).trim();
-                        definitions[i] = new InterceptorDefinition(name);
-                        String propsAsString = interceptorValues[i].substring(propIndex+1, interceptorValues[i].length()-1);
-                        String[] props = propsAsString.split(",");
-                        for (int j=0; j<props.length; j++) {
-                            int pidx = props[j].indexOf("=");
-                            String propName = props[j].substring(0,pidx).trim();
-                            String propValue = props[j].substring(pidx+1).trim();
-                            definitions[i].addProperty(new InterceptorProperty(propName,propValue));
-                        }
-                    }
-                }
-                interceptors = definitions;
-            }
-        }
-        return interceptors;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setAccessToUnderlyingConnectionAllowed(boolean accessToUnderlyingConnectionAllowed) {
-        // NOOP
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setConnectionProperties(String connectionProperties) {
-        this.connectionProperties = connectionProperties;
-        getProperties(connectionProperties, getDbProperties());
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setDbProperties(Properties dbProperties) {
-        this.dbProperties = dbProperties;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setDefaultAutoCommit(Boolean defaultAutoCommit) {
-        this.defaultAutoCommit = defaultAutoCommit;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setDefaultCatalog(String defaultCatalog) {
-        this.defaultCatalog = defaultCatalog;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setDefaultReadOnly(Boolean defaultReadOnly) {
-        this.defaultReadOnly = defaultReadOnly;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setDefaultTransactionIsolation(int defaultTransactionIsolation) {
-        this.defaultTransactionIsolation = defaultTransactionIsolation;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setDriverClassName(String driverClassName) {
-        this.driverClassName = driverClassName;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setInitialSize(int initialSize) {
-        this.initialSize = initialSize;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setLogAbandoned(boolean logAbandoned) {
-        this.logAbandoned = logAbandoned;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setMaxActive(int maxActive) {
-        this.maxActive = maxActive;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setMaxIdle(int maxIdle) {
-        this.maxIdle = maxIdle;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setMaxWait(int maxWait) {
-        this.maxWait = maxWait;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) {
-        this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setMinIdle(int minIdle) {
-        this.minIdle = minIdle;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
-        this.numTestsPerEvictionRun = numTestsPerEvictionRun;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setPassword(String password) {
-        this.password = password;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setRemoveAbandoned(boolean removeAbandoned) {
-        this.removeAbandoned = removeAbandoned;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) {
-        this.removeAbandonedTimeout = removeAbandonedTimeout;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setTestOnBorrow(boolean testOnBorrow) {
-        this.testOnBorrow = testOnBorrow;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setTestWhileIdle(boolean testWhileIdle) {
-        this.testWhileIdle = testWhileIdle;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setTestOnReturn(boolean testOnReturn) {
-        this.testOnReturn = testOnReturn;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setTimeBetweenEvictionRunsMillis(int
-                                                 timeBetweenEvictionRunsMillis) {
-        this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setUrl(String url) {
-        this.url = url;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setUsername(String username) {
-        this.username = username;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setValidationInterval(long validationInterval) {
-        this.validationInterval = validationInterval;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setValidationQuery(String validationQuery) {
-        this.validationQuery = validationQuery;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    
-    public void setValidatorClassName(String className) {
-        this.validatorClassName = className;
-        
-        validator = null;
-        
-        if (className == null) {
-            return;
-        }
-        
-        try {
-            Class<Validator> validatorClass = (Class<Validator>)Class.forName(className);
-            validator = validatorClass.newInstance();
-        } catch (ClassNotFoundException e) {
-            log.warn("The class "+className+" cannot be found.", e);
-        } catch (ClassCastException e) {
-            log.warn("The class "+className+" does not implement the Validator interface.", e);
-        } catch (InstantiationException e) {
-            log.warn("An object of class "+className+" cannot be instantiated. Make sure that "+
-                     "it includes an implicit or explicit no-arg constructor.", e);
-        } catch (IllegalAccessException e) {
-            log.warn("The class "+className+" or its no-arg constructor are inaccessible.", e);
-        }
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setInitSQL(String initSQL) {
-        this.initSQL = initSQL;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setTestOnConnect(boolean testOnConnect) {
-        this.testOnConnect = testOnConnect;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setJdbcInterceptors(String jdbcInterceptors) {
-        this.jdbcInterceptors = jdbcInterceptors;
-        this.interceptors = null;
-    }
-
-    
-    public String toString() {
-        StringBuilder buf = new StringBuilder("ConnectionPool[");
-        try {
-            String[] fields = DataSourceFactory.ALL_PROPERTIES;
-            for (int i=0; i<fields.length; i++) {
-                final String[] prefix = new String[] {"get","is"};
-                for (int j=0; j<prefix.length; j++) {
-
-                    String name = prefix[j] + fields[i].substring(0, 1).toUpperCase() +
-                                  fields[i].substring(1);
-                    Method m = null;
-                    try {
-                        m = getClass().getMethod(name);
-                    }catch (NoSuchMethodException nm) {
-                        continue;
-                    }
-                    buf.append(fields[i]);
-                    buf.append("=");
-                    buf.append(m.invoke(this, new Object[0]));
-                    buf.append("; ");
-                    break;
-                }
-            }
-        }catch (Exception x) {
-            //shouldn;t happen
-            x.printStackTrace();
-        }
-        return buf.toString();
-    }
-
-    public static int getPoolCounter() {
-        return poolCounter.get();
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public boolean isJmxEnabled() {
-        return jmxEnabled;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setJmxEnabled(boolean jmxEnabled) {
-        this.jmxEnabled = jmxEnabled;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public Boolean getDefaultAutoCommit() {
-        return defaultAutoCommit;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public Boolean getDefaultReadOnly() {
-        return defaultReadOnly;
-    }
-    
-    
-    /**
-     * {@inheritDoc}
-     */
-    
-    public int getSuspectTimeout() {
-        return this.suspectTimeout;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    
-    public void setSuspectTimeout(int seconds) {
-        this.suspectTimeout = seconds;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public boolean isPoolSweeperEnabled() {
-        boolean timer = getTimeBetweenEvictionRunsMillis()>0;
-        boolean result = timer && (isRemoveAbandoned() && getRemoveAbandonedTimeout()>0);
-        result = result || (timer && getSuspectTimeout()>0); 
-        result = result || (timer && isTestWhileIdle() && getValidationQuery()!=null);
-        result = result || (timer && getMinEvictableIdleTimeMillis()>0); 
-        return result;
-    }
-
-
-    public static class InterceptorDefinition {
-        protected String className;
-        protected Map<String,InterceptorProperty> properties = new HashMap<String,InterceptorProperty>();
-        protected volatile Class<?> clazz = null;
-        public InterceptorDefinition(String className) {
-            this.className = className;
-        }
-
-        public String getClassName() {
-            return className;
-        }
-        public void addProperty(String name, String value) {
-            InterceptorProperty p = new InterceptorProperty(name,value);
-            addProperty(p);
-        }
-        
-        public void addProperty(InterceptorProperty p) {
-            properties.put(p.getName(), p);
-        }
-        
-        public Map<String,InterceptorProperty> getProperties() {
-            return properties;
-        }
-        
-        public Class<? extends JdbcInterceptor> getInterceptorClass() throws ClassNotFoundException {
-            if (clazz==null) {
-                if (getClassName().indexOf(".")<0) {
-                    if (log.isDebugEnabled()) {
-                        log.debug("Loading interceptor class:"+PoolConfiguration.PKG_PREFIX+getClassName());
-                    }
-                    clazz = Class.forName(PoolConfiguration.PKG_PREFIX+getClassName(), true, this.getClass().getClassLoader());
-                } else {
-                    if (log.isDebugEnabled()) {
-                        log.debug("Loading interceptor class:"+getClassName());
-                    }
-                    clazz = Class.forName(getClassName(), true, this.getClass().getClassLoader());
-                }
-            }
-            return (Class<? extends JdbcInterceptor>)clazz;
-        }
-    } 
-    
-    public static class InterceptorProperty {
-        String name;
-        String value;
-        public InterceptorProperty(String name, String value) {
-            assert(name!=null);
-            this.name = name;
-            this.value = value;
-        }
-        public String getName() {
-            return name;
-        }
-        public String getValue() {
-            return value;
-        }
-        
-        public boolean getValueAsBoolean(boolean def) {
-            if (value==null) return def;
-            if ("true".equals(value)) return true;
-            if ("false".equals(value)) return false;
-            return def;
-        }
-        
-        public int getValueAsInt(int def) {
-            if (value==null) return def;
-            try {
-                int v = Integer.parseInt(value);
-                return v;
-            }catch (NumberFormatException nfe) {
-                return def;
-            }
-        }
-        
-        public long getValueAsLong(long def) {
-            if (value==null) return def;
-            try {
-                return Long.parseLong(value);
-            }catch (NumberFormatException nfe) {
-                return def;
-            }
-        }
-
-        public byte getValueAsByte(byte def) {
-            if (value==null) return def;
-            try {
-                return Byte.parseByte(value);
-            }catch (NumberFormatException nfe) {
-                return def;
-            }
-        }
-        
-        public short getValueAsShort(short def) {
-            if (value==null) return def;
-            try {
-                return Short.parseShort(value);
-            }catch (NumberFormatException nfe) {
-                return def;
-            }
-        }
-
-        public float getValueAsFloat(float def) {
-            if (value==null) return def;
-            try {
-                return Float.parseFloat(value);
-            }catch (NumberFormatException nfe) {
-                return def;
-            }
-        }
-
-        public double getValueAsDouble(double def) {
-            if (value==null) return def;
-            try {
-                return Double.parseDouble(value);
-            }catch (NumberFormatException nfe) {
-                return def;
-            }
-        }
-        public char getValueAschar(char def) {
-            if (value==null) return def;
-            try {
-                return value.charAt(0);
-            }catch (StringIndexOutOfBoundsException nfe) {
-                return def;
-            }
-        }
-        
-        public int hashCode() {
-            return name.hashCode();
-        }
-        
-        public boolean equals(Object o) {
-            if (o==this) return true;
-            if (o instanceof InterceptorProperty) {
-                InterceptorProperty other = (InterceptorProperty)o;
-                return other.name.equals(this.name);
-            }
-            return false;
-        }
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public boolean isUseEquals() {
-        return useEquals;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setUseEquals(boolean useEquals) {
-        this.useEquals = useEquals;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public long getMaxAge() {
-        return maxAge;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setMaxAge(long maxAge) {
-        this.maxAge = maxAge;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public boolean getUseLock() {
-        return useLock;
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    
-    public void setUseLock(boolean useLock) {
-        this.useLock = useLock;
-    }
-    
-    
-    /** 
-     * {@inheritDoc}
-     */
-    public void setDataSource(Object ds) {
-        this.dataSource = ds;
-    }
-    
-    /** 
-     * {@inheritDoc}
-     */
-    public Object getDataSource() {
-        return dataSource;
-    }
-    
-    
-    /** 
-     * {@inheritDoc}
-     */
-    public void setDataSourceJNDI(String jndiDS) {
-        this.dataSourceJNDI = jndiDS;
-    }
-    
-    /** 
-     * {@inheritDoc}
-     */
-    public String getDataSourceJNDI() {
-        return this.dataSourceJNDI;
-    }
-    
-        
-    public static Properties getProperties(String propText, Properties props) {
-        if (props==null) props = new Properties();
-        if (propText != null) {
-            try {
-                props.load(new ByteArrayInputStream(propText.replace(';', '\n').getBytes()));
-            }catch (IOException x) {
-                throw new RuntimeException(x);
-            }
-        }
-        return props;
-    }
-    
-    /** 
-     * {@inheritDoc}
-     */
-    public boolean isAlternateUsernameAllowed() {
-        return alternateUsernameAllowed;
-    }
-    
-    /** 
-     * {@inheritDoc}
-     */
-    public void setAlternateUsernameAllowed(boolean alternateUsernameAllowed) {
-        this.alternateUsernameAllowed = alternateUsernameAllowed;
-    }
-    
-}
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolUtilities.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PoolUtilities.java
deleted file mode 100644 (file)
index 0b2a5ed..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.pool;
-
-import java.util.Properties;
-
-/**
- * 
- * @author fhanik
- *
- */
-public class PoolUtilities {
-    
-    public static final String PROP_USER = "user";
-    
-    public static final String PROP_PASSWORD = "password";
-    
-    public static Properties clone(Properties p) {
-        Properties c = new Properties();
-        c.putAll(p);
-        return c;
-    }
-    
-    public static Properties cloneWithoutPassword(Properties p) {
-        Properties result = clone(p);
-        result.remove(PROP_PASSWORD);
-        return result;
-    }
-}
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PooledConnection.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/PooledConnection.java
deleted file mode 100644 (file)
index e4108b8..0000000
+++ /dev/null
@@ -1,670 +0,0 @@
-/*
- * 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.pool;
-
-
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.HashMap;
-import java.util.Properties;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;
-
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * Represents a pooled connection
- * and holds a reference to the {@link java.sql.Connection} object
- * @author Filip Hanik
- * @version 1.0
- */
-public class PooledConnection {
-    /**
-     * Logger
-     */
-    private static final Log log = LogFactory.getLog(PooledConnection.class);
-
-    public static final String PROP_USER = PoolUtilities.PROP_USER;
-    
-    public static final String PROP_PASSWORD = PoolUtilities.PROP_PASSWORD;
-    
-    /**
-     * Validate when connection is borrowed flag
-     */
-    public static final int VALIDATE_BORROW = 1;
-    /**
-     * Validate when connection is returned flag
-     */
-    public static final int VALIDATE_RETURN = 2;
-    /**
-     * Validate when connection is idle flag
-     */
-    public static final int VALIDATE_IDLE = 3;
-    /**
-     * Validate when connection is initialized flag
-     */
-    public static final int VALIDATE_INIT = 4;
-    /**
-     * The properties for the connection pool
-     */
-    protected PoolConfiguration poolProperties;
-    /**
-     * The underlying database connection
-     */
-    private volatile java.sql.Connection connection;
-    
-    /**
-     * If using a XAConnection underneath.
-     */
-    protected volatile javax.sql.XAConnection xaConnection;
-    /**
-     * When we track abandon traces, this string holds the thread dump
-     */
-    private String abandonTrace = null;
-    /**
-     * Timestamp the connection was last 'touched' by the pool
-     */
-    private volatile long timestamp;
-    /**
-     * Lock for this connection only
-     */
-    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(false);
-    /**
-     * Set to true if this connection has been discarded by the pool
-     */
-    private volatile boolean discarded = false;
-    /**
-     * The Timestamp when the last time the connect() method was called successfully
-     */
-    private volatile long lastConnected = -1;
-    /**
-     * timestamp to keep track of validation intervals
-     */
-    private volatile long lastValidated = System.currentTimeMillis();
-    /**
-     * 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
-     * so that we don't create a new list of interceptors each time we borrow
-     * the connection
-     */
-    private volatile JdbcInterceptor handler = null;
-    
-    private AtomicBoolean released = new AtomicBoolean(false);
-    
-    private volatile boolean suspect = false;
-    
-    private java.sql.Driver driver = null;
-    
-    /**
-     * Constructor
-     * @param prop - pool properties
-     * @param parent - the parent connection pool
-     */
-    public PooledConnection(PoolConfiguration prop, ConnectionPool parent) {
-        poolProperties = prop;
-        this.parent = parent;
-    }
-
-    public boolean checkUser(String username, String password) {
-        if (!getPoolProperties().isAlternateUsernameAllowed()) return true;
-        
-        if (username==null) username = poolProperties.getUsername();
-        if (password==null) password = poolProperties.getPassword();
-        
-        String storedUsr = (String)getAttributes().get(PROP_USER);
-        String storedPwd = (String)getAttributes().get(PROP_PASSWORD);
-        
-        boolean result = (username==null && storedUsr==null);
-        result = (result || (username!=null && username.equals(storedUsr)));
-                
-        result = result && ((password==null && storedPwd==null) || (password!=null && password.equals(storedPwd)));
-        
-        if (username==null)  getAttributes().remove(PROP_USER); else getAttributes().put(PROP_USER, username);
-        if (password==null)  getAttributes().remove(PROP_PASSWORD); else getAttributes().put(PROP_PASSWORD, password);
-        
-        return result;
-    }
-    
-    /**
-     * Connects the underlying connection to the database.
-     * @throws SQLException if the method {@link #release()} has been called.
-     * @throws SQLException if driver instantiation fails
-     * @throws SQLException if a call to {@link java.sql.Driver#connect(String, java.util.Properties)} fails.
-     * @throws SQLException if default properties are configured and a call to 
-     * {@link java.sql.Connection#setAutoCommit(boolean)}, {@link java.sql.Connection#setCatalog(String)}, 
-     * {@link java.sql.Connection#setTransactionIsolation(int)} or {@link java.sql.Connection#setReadOnly(boolean)} fails.  
-     */
-    public void connect() throws SQLException {
-        if (released.get()) throw new SQLException("A connection once released, can't be reestablished.");
-        if (connection != null) {
-            try {
-                this.disconnect(false);
-            } catch (Exception x) {
-                log.debug("Unable to disconnect previous connection.", x);
-            } //catch
-        } //end if
-        if (poolProperties.getDataSource()==null && poolProperties.getDataSourceJNDI()!=null) {
-            //TODO lookup JNDI name
-        }
-        
-        if (poolProperties.getDataSource()!=null) {
-            connectUsingDataSource();
-        } else {
-            connectUsingDriver();
-        }
-        
-        //set up the default state, unless we expect the interceptor to do it
-        if (poolProperties.getJdbcInterceptors()==null || poolProperties.getJdbcInterceptors().indexOf(ConnectionState.class.getName())<0) {
-            if (poolProperties.getDefaultTransactionIsolation()!=DataSourceFactory.UNKNOWN_TRANSACTIONISOLATION) connection.setTransactionIsolation(poolProperties.getDefaultTransactionIsolation());
-            if (poolProperties.getDefaultReadOnly()!=null) connection.setReadOnly(poolProperties.getDefaultReadOnly().booleanValue());
-            if (poolProperties.getDefaultAutoCommit()!=null) connection.setAutoCommit(poolProperties.getDefaultAutoCommit().booleanValue());
-            if (poolProperties.getDefaultCatalog()!=null) connection.setCatalog(poolProperties.getDefaultCatalog());
-        }        
-        this.discarded = false;
-        this.lastConnected = System.currentTimeMillis();
-    }
-    
-    protected void connectUsingDataSource() throws SQLException {
-        String usr = null;
-        String pwd = null;
-        if (getAttributes().containsKey(PROP_USER)) {
-            usr = (String) getAttributes().get(PROP_USER);
-        } else {
-            usr = poolProperties.getUsername();
-            getAttributes().put(PROP_USER, usr);
-        }
-        if (getAttributes().containsKey(PROP_PASSWORD)) {
-            pwd = (String) getAttributes().get(PROP_PASSWORD);
-        } else {
-            pwd = poolProperties.getPassword();
-            getAttributes().put(PROP_PASSWORD, pwd);
-        }
-        if (poolProperties.getDataSource() instanceof javax.sql.XADataSource) {
-            javax.sql.XADataSource xds = (javax.sql.XADataSource)poolProperties.getDataSource();
-            if (usr!=null && pwd!=null) {
-                xaConnection = xds.getXAConnection(usr, pwd);
-                connection = xaConnection.getConnection();
-            } else {
-                xaConnection = xds.getXAConnection();
-                connection = xaConnection.getConnection();
-            }
-        } else if (poolProperties.getDataSource() instanceof javax.sql.DataSource){
-            javax.sql.DataSource ds = (javax.sql.DataSource)poolProperties.getDataSource();
-            if (usr!=null && pwd!=null) {
-                connection = ds.getConnection(usr, pwd);
-            } else {
-                connection = ds.getConnection();
-            }
-        } else if (poolProperties.getDataSource() instanceof javax.sql.ConnectionPoolDataSource){
-            javax.sql.ConnectionPoolDataSource ds = (javax.sql.ConnectionPoolDataSource)poolProperties.getDataSource();
-            if (usr!=null && pwd!=null) {
-                connection = ds.getPooledConnection(usr, pwd).getConnection();
-            } else {
-                connection = ds.getPooledConnection().getConnection();
-            }
-        } else {
-            throw new SQLException("DataSource is of unknown class:"+(poolProperties.getDataSource()!=null?poolProperties.getDataSource().getClass():"null"));
-        }
-    }
-    protected void connectUsingDriver() throws SQLException {
-        
-        try {
-            if (driver==null)
-                driver = (java.sql.Driver) Class.forName(poolProperties.getDriverClassName(),
-                                                         true, PooledConnection.class.getClassLoader()
-                                                         ).newInstance();
-        } catch (java.lang.Exception cn) {
-            if (log.isDebugEnabled()) {
-                log.debug("Unable to instantiate JDBC driver.", cn);
-            }
-            SQLException ex = new SQLException(cn.getMessage());
-            ex.initCause(cn);
-            throw ex;
-        }
-        String driverURL = poolProperties.getUrl();
-        String usr = null;
-        String pwd = null;
-        if (getAttributes().containsKey(PROP_USER)) {
-            usr = (String) getAttributes().get(PROP_USER);
-        } else {
-            usr = poolProperties.getUsername();
-            getAttributes().put(PROP_USER, usr);
-        }
-        if (getAttributes().containsKey(PROP_PASSWORD)) {
-            pwd = (String) getAttributes().get(PROP_PASSWORD);
-        } else {
-            pwd = poolProperties.getPassword();
-            getAttributes().put(PROP_PASSWORD, pwd);
-        }
-        Properties properties = PoolUtilities.clone(poolProperties.getDbProperties());
-        if (usr != null) properties.setProperty(PROP_USER, usr);
-        if (pwd != null) properties.setProperty(PROP_PASSWORD, pwd);
-
-        try {
-            connection = connection = driver.connect(driverURL, properties);
-        } catch (Exception x) {
-            if (log.isDebugEnabled()) {
-                log.debug("Unable to connect to database.", x);
-            }
-            if (parent.jmxPool!=null) {
-                parent.jmxPool.notify(org.apache.tomcat.jdbc.pool.jmx.ConnectionPool.NOTIFY_CONNECT,
-                        ConnectionPool.getStackTrace(x));
-            }
-            if (x instanceof SQLException) {
-                throw (SQLException)x;
-            } else {
-                SQLException ex = new SQLException(x.getMessage());
-                ex.initCause(x);
-                throw ex;
-            }
-        }
-        if (connection==null) {
-            throw new SQLException("Driver:"+driver+" returned null for URL:"+driverURL);
-        }
-    }
-    
-    /**
-     * 
-     * @return true if connect() was called successfully and disconnect has not yet been called
-     */
-    public boolean isInitialized() {
-        return connection!=null;
-    }
-
-    /**
-     * Issues a call to {@link #disconnect(boolean)} with the argument false followed by a call to 
-     * {@link #connect()}
-     * @throws SQLException if the call to {@link #connect()} fails.
-     */
-    public void reconnect() throws SQLException {
-        this.disconnect(false);
-        this.connect();
-    } //reconnect
-
-    /**
-     * Disconnects the connection. All exceptions are logged using debug level.
-     * @param finalize if set to true, a call to {@link ConnectionPool#finalize(PooledConnection)} is called.
-     */
-    private void disconnect(boolean finalize) {
-        if (isDiscarded()) {
-            return;
-        }
-        setDiscarded(true);
-        if (connection != null) {
-            try {
-                parent.disconnectEvent(this, finalize);
-                if (xaConnection == null) {
-                    connection.close();
-                } else {
-                    xaConnection.close();
-                }
-            }catch (Exception ignore) {
-                if (log.isDebugEnabled()) {
-                    log.debug("Unable to close underlying SQL connection",ignore);
-                }
-            }
-        }
-        connection = null;
-        xaConnection = null;
-        lastConnected = -1;
-        if (finalize) parent.finalize(this);
-    }
-
-
-//============================================================================
-//             
-//============================================================================
-
-    /**
-     * Returns abandon timeout in milliseconds
-     * @return abandon timeout in milliseconds
-     */
-    public long getAbandonTimeout() {
-        if (poolProperties.getRemoveAbandonedTimeout() <= 0) {
-            return Long.MAX_VALUE;
-        } else {
-            return poolProperties.getRemoveAbandonedTimeout()*1000;
-        } //end if
-    }
-
-    /**
-     * Returns true if the connection pool is configured 
-     * to do validation for a certain action.
-     * @param action
-     * @return
-     */
-    private boolean doValidate(int action) {
-        if (action == PooledConnection.VALIDATE_BORROW &&
-            poolProperties.isTestOnBorrow())
-            return true;
-        else if (action == PooledConnection.VALIDATE_RETURN &&
-                 poolProperties.isTestOnReturn())
-            return true;
-        else if (action == PooledConnection.VALIDATE_IDLE &&
-                 poolProperties.isTestWhileIdle())
-            return true;
-        else if (action == PooledConnection.VALIDATE_INIT &&
-                 poolProperties.isTestOnConnect())
-            return true;
-        else if (action == PooledConnection.VALIDATE_INIT &&
-                 poolProperties.getInitSQL()!=null)
-           return true;
-        else
-            return false;
-    }
-
-    /**Returns true if the object is still valid. if not
-     * the pool will call the getExpiredAction() and follow up with one
-     * of the four expired methods
-     */
-    public boolean validate(int validateAction) {
-        return validate(validateAction,null);
-    }
-
-    /**
-     * Validates a connection. 
-     * @param validateAction the action used. One of {@link #VALIDATE_BORROW}, {@link #VALIDATE_IDLE}, 
-     * {@link #VALIDATE_INIT} or {@link #VALIDATE_RETURN}
-     * @param sql the SQL to be used during validation. If the {@link PoolConfiguration#setInitSQL(String)} has been called with a non null 
-     * value and the action is {@link #VALIDATE_INIT} the init SQL will be used for validation.
-     *  
-     * @return true if the connection was validated successfully. It returns true even if validation was not performed, such as when 
-     * {@link PoolConfiguration#setValidationInterval(long)} has been called with a positive value. 
-     * <p>
-     * false if the validation failed. The caller should close the connection if false is returned since a session could have been left in 
-     * an unknown state during initialization.
-     */
-    public boolean validate(int validateAction,String sql) {
-        if (this.isDiscarded()) {
-            return false;
-        }
-        
-        if (!doValidate(validateAction)) {
-            //no validation required, no init sql and props not set
-            return true;
-        }
-
-        //Don't bother validating if already have recently enough
-        long now = System.currentTimeMillis();
-        if (validateAction!=VALIDATE_INIT &&
-            poolProperties.getValidationInterval() > 0 &&
-            (now - this.lastValidated) <
-            poolProperties.getValidationInterval()) {
-            return true;
-        }
-
-        if (poolProperties.getValidator() != null) {
-            if (poolProperties.getValidator().validate(connection, validateAction)) {
-                this.lastValidated = now;
-                return true;
-            } else {
-                return false;
-            }
-        }
-        
-        String query = sql;
-        
-        if (validateAction == VALIDATE_INIT && poolProperties.getInitSQL() != null) {
-            query = poolProperties.getInitSQL();
-        }
-
-        if (query == null) {
-            query = poolProperties.getValidationQuery();
-        }
-        
-        Statement stmt = null;
-        try {
-            stmt = connection.createStatement();
-            stmt.execute(query);
-            stmt.close();
-            this.lastValidated = now;
-            return true;
-        } catch (Exception ignore) {
-            if (log.isDebugEnabled())
-                log.debug("Unable to validate object:",ignore);
-            if (stmt!=null)
-                try { stmt.close();} catch (Exception ignore2){/*NOOP*/}
-        }
-        return false;
-    } //validate
-
-    /**
-     * The time limit for how long the object
-     * can remain unused before it is released
-     * @return {@link PoolConfiguration#getMinEvictableIdleTimeMillis()}
-     */
-    public long getReleaseTime() {
-        return this.poolProperties.getMinEvictableIdleTimeMillis();
-    }
-
-    /**
-     * This method is called if (Now - timeCheckedIn > getReleaseTime())
-     * This method disconnects the connection, logs an error in debug mode if it happens
-     * then sets the {@link #released} flag to false. Any attempts to connect this cached object again
-     * will fail per {@link #connect()}
-     * The connection pool uses the atomic return value to decrement the pool size counter.
-     * @return true if this is the first time this method has been called. false if this method has been called before.
-     */
-    public boolean release() {
-        try {
-            disconnect(true);
-        } catch (Exception x) {
-            if (log.isDebugEnabled()) {
-                log.debug("Unable to close SQL connection",x);
-            }
-        }
-        return released.compareAndSet(false, true);
-
-    }
-
-    /**
-     * The pool will set the stack trace when it is check out and
-     * checked in
-     * @param trace the stack trace for this connection
-     */
-
-    public void setStackTrace(String trace) {
-        abandonTrace = trace;
-    }
-
-    /**
-     * Returns the stack trace from when this connection was borrowed. Can return null if no stack trace was set.
-     * @return the stack trace or null of no trace was set
-     */
-    public String getStackTrace() {
-        return abandonTrace;
-    }
-
-    /**
-     * Sets a timestamp on this connection. A timestamp usually means that some operation
-     * performed successfully.
-     * @param timestamp the timestamp as defined by {@link System#currentTimeMillis()}
-     */
-    public void setTimestamp(long timestamp) {
-        this.timestamp = timestamp;
-        setSuspect(false);
-    }
-
-
-    public boolean isSuspect() {
-        return suspect;
-    }
-
-    public void setSuspect(boolean suspect) {
-        this.suspect = suspect;
-    }
-
-    /**
-     * An interceptor can call this method with the value true, and the connection will be closed when it is returned to the pool.
-     * @param discarded - only valid value is true
-     * @throws IllegalStateException if this method is called with the value false and the value true has already been set.
-     */
-    public void setDiscarded(boolean discarded) {
-        if (this.discarded && !discarded) throw new IllegalStateException("Unable to change the state once the connection has been discarded");
-        this.discarded = discarded;
-    }
-
-    /**
-     * Set the timestamp the connection was last validated.
-     * This flag is used to keep track when we are using a {@link PoolConfiguration#setValidationInterval(long) validation-interval}.
-     * @param lastValidated a timestamp as defined by {@link System#currentTimeMillis()} 
-     */
-    public void setLastValidated(long lastValidated) {
-        this.lastValidated = lastValidated;
-    }
-
-    /**
-     * Sets the pool configuration for this connection and connection pool.
-     * Object is shared with the {@link ConnectionPool}
-     * @param poolProperties
-     */
-    public void setPoolProperties(PoolConfiguration poolProperties) {
-        this.poolProperties = poolProperties;
-    }
-
-    /**
-     * Return the timestamps of last pool action. Timestamps are typically set when connections 
-     * are borrowed from the pool. It is used to keep track of {@link PoolConfiguration#setRemoveAbandonedTimeout(int) abandon-timeouts}.
-     * This timestamp can also be reset by the {@link org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer#invoke(Object, java.lang.reflect.Method, Object[])}   
-     * @return the timestamp of the last pool action as defined by {@link System#currentTimeMillis()}
-     */
-    public long getTimestamp() {
-        return timestamp;
-    }
-
-    /**
-     * Returns the discarded flag.
-     * @return the discarded flag. If the value is true, 
-     * either {@link #disconnect(boolean)} has been called or it will be called when the connection is returned to the pool.
-     */
-    public boolean isDiscarded() {
-        return discarded;
-    }
-
-    /**
-     * Returns the timestamp of the last successful validation query execution. 
-     * @return the timestamp of the last successful validation query execution as defined by {@link System#currentTimeMillis()}
-     */
-    public long getLastValidated() {
-        return lastValidated;
-    }
-
-    /**
-     * Returns the configuration for this connection and pool
-     * @return the configuration for this connection and pool
-     */
-    public PoolConfiguration getPoolProperties() {
-        return poolProperties;
-    }
-
-    /**
-     * Locks the connection only if either {@link PoolConfiguration#isPoolSweeperEnabled()} or 
-     * {@link PoolConfiguration#getUseLock()} return true. The per connection lock ensures thread safety is
-     * multiple threads are performing operations on the connection. 
-     * Otherwise this is a noop for performance
-     */
-    public void lock() {
-        if (poolProperties.getUseLock() || this.poolProperties.isPoolSweeperEnabled()) {
-            //optimized, only use a lock when there is concurrency
-            lock.writeLock().lock();
-        }
-    }
-
-    /**
-     * Unlocks the connection only if the sweeper is enabled
-     * Otherwise this is a noop for performance
-     */
-    public void unlock() {
-        if (poolProperties.getUseLock() || this.poolProperties.isPoolSweeperEnabled()) {
-          //optimized, only use a lock when there is concurrency
-            lock.writeLock().unlock();
-        }
-    }
-
-    /**
-     * Returns the underlying connection
-     * @return the underlying JDBC connection as it was returned from the JDBC driver
-     * @see javax.sql.PooledConnection#getConnection()
-     */
-    public java.sql.Connection getConnection() {
-        return this.connection;
-    }
-    
-    /**
-     * Returns the underlying XA connection
-     * @return the underlying XA connection as it was returned from the Datasource
-     */
-    public javax.sql.XAConnection getXAConnection() {
-        return this.xaConnection;
-    }
-    
-    
-    /**
-     * Returns the timestamp of when the connection was last connected to the database.
-     * ie, a successful call to {@link java.sql.Driver#connect(String, java.util.Properties)}.
-     * @return the timestamp when this connection was created as defined by {@link System#currentTimeMillis()}
-     */
-    public long getLastConnected() {
-        return lastConnected;
-    }
-
-    /**
-     * Returns the first handler in the interceptor chain
-     * @return the first interceptor for this connection
-     */
-    public JdbcInterceptor getHandler() {
-        return handler;
-    }
-
-    public void setHandler(JdbcInterceptor handler) {
-        if (this.handler!=null && this.handler!=handler) {
-            JdbcInterceptor interceptor = this.handler;
-            while (interceptor!=null) {
-                interceptor.reset(null, null);
-                interceptor = interceptor.getNext();
-            }//while 
-        }//end if
-        this.handler = handler;
-    }
-    
-    @Override
-    public String toString() {
-        return "PooledConnection["+(connection!=null?connection.toString():"null")+"]";
-    }
-    
-    /**
-     * Returns true if this connection has been released and wont be reused.
-     * @return true if the method {@link #release()} has been called
-     */
-    public boolean isReleased() {
-        return released.get();
-    }
-    
-    public HashMap<Object,Object> getAttributes() {
-        return attributes;
-    }
-
-}
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ProxyConnection.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/ProxyConnection.java
deleted file mode 100644 (file)
index 532cb6a..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * 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.pool;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.sql.SQLException;
-
-import javax.sql.XAConnection;
-/**
- * A ProxyConnection object is the bottom most interceptor that wraps an object of type 
- * {@link PooledConnection}. The ProxyConnection intercepts three methods:
- * <ul>
- *   <li>{@link java.sql.Connection#close()} - returns the connection to the pool. May be called multiple times.</li>
- *   <li>{@link java.lang.Object#toString()} - returns a custom string for this object</li>
- *   <li>{@link javax.sql.PooledConnection#getConnection()} - returns the underlying connection</li>
- * </ul>
- * By default method comparisons is done on a String reference level, unless the {@link PoolConfiguration#setUseEquals(boolean)} has been called
- * with a <code>true</code> argument.
- * @author Filip Hanik
- */
-public class ProxyConnection extends JdbcInterceptor {
-
-    protected PooledConnection connection = null;
-
-    protected ConnectionPool pool = null;
-
-    public PooledConnection getConnection() {
-        return connection;
-    }
-
-    public void setConnection(PooledConnection connection) {
-        this.connection = connection;
-    }
-
-    public ConnectionPool getPool() {
-        return pool;
-    }
-
-    public void setPool(ConnectionPool pool) {
-        this.pool = pool;
-    }
-
-    protected ProxyConnection(ConnectionPool parent, PooledConnection con, boolean useEquals) throws SQLException {
-        pool = parent;
-        connection = con;
-        setUseEquals(useEquals);
-    }
-
-    @Override
-    public void reset(ConnectionPool parent, PooledConnection con) {
-        this.pool = parent;
-        this.connection = con;
-    }
-
-    public boolean isWrapperFor(Class<?> iface) throws SQLException {
-        if (iface == XAConnection.class && connection.getXAConnection()!=null) {
-            return true;
-        } else {
-            return (iface.isInstance(connection.getConnection()));
-        }
-    }
-
-
-    public Object unwrap(Class<?> iface) throws SQLException {
-        if (iface == PooledConnection.class) {
-            return connection;
-        }else if (iface == XAConnection.class) {
-            return connection.getXAConnection();
-        } else if (isWrapperFor(iface)) {
-            return connection.getConnection();
-        } else {
-            throw new SQLException("Not a wrapper of "+iface.getName());
-        }
-    }
-
-    @Override
-    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-        if (compare(ISCLOSED_VAL,method)) {
-            return Boolean.valueOf(isClosed());
-        }
-        if (compare(CLOSE_VAL,method)) {
-            if (isClosed()) return null; //noop for already closed.
-            PooledConnection poolc = this.connection;
-            this.connection = null;
-            pool.returnConnection(poolc);
-            return null;
-        } else if (compare(TOSTRING_VAL,method)) {
-            return this.toString();
-        } else if (compare(GETCONNECTION_VAL,method) && connection!=null) {
-            return connection.getConnection();
-        } else if (method.getDeclaringClass().equals(XAConnection.class)) {
-            try {
-                return method.invoke(connection.getXAConnection(),args);
-            }catch (Throwable t) {
-                if (t instanceof InvocationTargetException) {
-                    InvocationTargetException it = (InvocationTargetException)t;
-                    throw it.getCause()!=null?it.getCause():it;
-                } else {
-                    throw t;
-                }
-            }
-        }
-        if (isClosed()) throw new SQLException("Connection has already been closed.");
-        if (compare(UNWRAP_VAL,method)) {
-            return unwrap((Class<?>)args[0]);
-        } else if (compare(ISWRAPPERFOR_VAL,method)) {
-            return this.isWrapperFor((Class<?>)args[0]);
-        }
-        try {
-            return method.invoke(connection.getConnection(),args);
-        }catch (Throwable t) {
-            if (t instanceof InvocationTargetException) {
-                InvocationTargetException it = (InvocationTargetException)t;
-                throw it.getCause()!=null?it.getCause():it;
-            } else {
-                throw t;
-            }
-        }
-    }
-    
-    public boolean isClosed() {
-        return connection==null || connection.isDiscarded();
-    }
-
-    public PooledConnection getDelegateConnection() {
-        return connection;
-    }
-
-    public ConnectionPool getParentPool() {
-        return pool;
-    }
-    
-    @Override
-    public String toString() {
-        return "ProxyConnection["+(connection!=null?connection.toString():"null")+"]";
-    }
-
-}
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/Validator.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/Validator.java
deleted file mode 100644 (file)
index 4f286ef..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.pool;
-
-import java.sql.Connection;
-
-/**
- * Interface to be implemented by custom validator classes.
- * 
- * @author mpassell
- */
-public interface Validator {
-    /**
-     * Validate a connection and return a boolean to indicate if it's valid.
-     * 
-     * @param connection the Connection object to test
-     * @param validateAction the action used. One of {@link PooledConnection#VALIDATE_BORROW},
-     *   {@link PooledConnection#VALIDATE_IDLE}, {@link PooledConnection#VALIDATE_INIT} or
-     *   {@link PooledConnection#VALIDATE_RETURN}
-     * @return true if the connection is valid
-     */
-    public boolean validate(Connection connection, int validateAction);
-}
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/XADataSource.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/XADataSource.java
deleted file mode 100644 (file)
index ce829d3..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.pool;
-
-public class XADataSource extends DataSource implements javax.sql.XADataSource {
-
-    /**
-     * Constructor for reflection only. A default set of pool properties will be created.
-     */
-    public XADataSource() {
-        super();
-    }
-
-    /**
-     * Constructs a DataSource object wrapping a connection
-     * @param poolProperties
-     */
-    public XADataSource(PoolConfiguration poolProperties) {
-        super(poolProperties);
-    }
-
-}
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java
deleted file mode 100644 (file)
index 19a13ed..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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.pool.interceptor;
-
-import java.lang.reflect.Method;
-
-import org.apache.tomcat.jdbc.pool.ConnectionPool;
-import org.apache.tomcat.jdbc.pool.JdbcInterceptor;
-import org.apache.tomcat.jdbc.pool.PooledConnection;
-
-/**
- * Abstraction interceptor. This component intercepts all calls to create some type of SQL statement.
- * By extending this class, one can intercept queries and update statements by overriding the {@link #createStatement(Object, Method, Object[], Object, long)}
- * method.
- * @author Filip Hanik
- * @version 1.0
- */
-public abstract class  AbstractCreateStatementInterceptor extends JdbcInterceptor {
-    protected static final String CREATE_STATEMENT      = "createStatement";
-    protected static final int    CREATE_STATEMENT_IDX  = 0;
-    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_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;
-    
-    protected static final String EXECUTE        = "execute";
-    protected static final String EXECUTE_QUERY  = "executeQuery";
-    protected static final String EXECUTE_UPDATE = "executeUpdate";
-    protected static final String EXECUTE_BATCH  = "executeBatch";
-
-    protected static final String[] EXECUTE_TYPES = {EXECUTE, EXECUTE_QUERY, EXECUTE_UPDATE, EXECUTE_BATCH};
-
-    public  AbstractCreateStatementInterceptor() {
-        super();
-    }
-    
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-        if (compare(CLOSE_VAL,method)) {
-            closeInvoked();
-            return super.invoke(proxy, method, args);
-        } else {
-            boolean process = false;
-            process = isStatement(method, process);
-            if (process) {
-                long start = System.currentTimeMillis();
-                Object statement = super.invoke(proxy,method,args);
-                long delta = System.currentTimeMillis() - start;
-                return createStatement(proxy,method,args,statement, delta);
-            } else {
-                return super.invoke(proxy,method,args);
-            }
-        }
-    }
-    
-    /**
-     * This method will be invoked after a successful statement creation. This method can choose to return a wrapper
-     * around the statement or return the statement itself.
-     * If this method returns a wrapper then it should return a wrapper object that implements one of the following interfaces.
-     * {@link java.sql.Statement}, {@link java.sql.PreparedStatement} or {@link java.sql.CallableStatement}
-     * @param proxy the actual proxy object
-     * @param method the method that was called. It will be one of the methods defined in {@link #STATEMENT_TYPES}
-     * @param args the arguments to the method
-     * @param statement the statement that the underlying connection created
-     * @return a {@link java.sql.Statement} object
-     */
-    public abstract Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time);
-    
-    /**
-     * Method invoked when the operation {@link java.sql.Connection#close()} is invoked. 
-     */
-    public abstract void closeInvoked();
-
-    /**
-     * Returns true if the method that is being invoked matches one of the statement types.
-     * 
-     * @param method the method being invoked on the proxy
-     * @param process boolean result used for recursion
-     * @return returns true if the method name matched
-     */
-    protected boolean isStatement(Method method, boolean process){
-        return process(STATEMENT_TYPES, method, process);
-    }
-
-    /**
-     * Returns true if the method that is being invoked matches one of the execute types.
-     * 
-     * @param method the method being invoked on the proxy
-     * @param process boolean result used for recursion
-     * @return returns true if the method name matched
-     */
-    protected boolean isExecute(Method method, boolean process){
-        return process(EXECUTE_TYPES, method, process);
-    }
-
-    /*
-     * Returns true if the method that is being invoked matches one of the method names passed in
-     * @param names list of method names that we want to intercept
-     * @param method the method being invoked on the proxy
-     * @param process boolean result used for recursion
-     * @return returns true if the method name matched
-     */
-    protected boolean process(String[] names, Method method, boolean process) {
-        final String name = method.getName();
-        for (int i=0; (!process) && i<names.length; i++) {
-            process = compare(names[i],name);
-        }
-        return process;
-    }
-    
-    /**
-     * no-op for this interceptor. no state is stored.
-     */
-    @Override
-    public void reset(ConnectionPool parent, PooledConnection con) {
-        // NOOP
-    }
-}
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractQueryReport.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractQueryReport.java
deleted file mode 100644 (file)
index 198cc8a..0000000
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- *  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.pool.interceptor;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.sql.CallableStatement;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-import java.sql.Statement;
-
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.jdbc.pool.JdbcInterceptor;
-/**
- * Abstract class that wraps statements and intercepts query executions.
- * @author fhanik
- *
- */
-public abstract class AbstractQueryReport extends AbstractCreateStatementInterceptor {
-    //logger
-    private static final Log log = LogFactory.getLog(AbstractQueryReport.class);
-
-    /**
-     * The threshold in milliseconds. If the query is faster than this, we don't measure it
-     */
-    protected long threshold = 1000; //don't report queries less than this
-    
-    /**
-     * the constructors that are used to create statement proxies 
-     */
-    protected static final Constructor<?>[] constructors =
-        new Constructor[AbstractCreateStatementInterceptor.STATEMENT_TYPE_COUNT];
-
-    
-    public AbstractQueryReport() {
-        super();
-    }
-    
-    /**
-     * Invoked when prepareStatement has been called and completed.
-     * @param sql - the string used to prepare the statement with
-     * @param time - the time it took to invoke prepare
-     */
-    protected abstract void prepareStatement(String sql, long time);
-    
-    /**
-     * Invoked when prepareCall has been called and completed.
-     * @param query - the string used to prepare the statement with
-     * @param time - the time it took to invoke prepare
-     */
-    protected abstract void prepareCall(String query, long time);
-
-    /**
-     * Invoked when a query execution, a call to execute/executeQuery or executeBatch failed.
-     * @param query the query that was executed and failed
-     * @param args the arguments to the execution
-     * @param name the name of the method used to execute {@link AbstractCreateStatementInterceptor#isExecute(Method, boolean)}
-     * @param start the time the query execution started
-     * @param t the exception that happened
-     * @return - the SQL that was executed or the string &quot;batch&quot; if it was a batch execution 
-     */
-    protected String reportFailedQuery(String query, Object[] args, final String name, long start, Throwable t) {
-        //extract the query string
-        String sql = (query==null && args!=null &&  args.length>0)?(String)args[0]:query;
-        //if we do batch execution, then we name the query 'batch'
-        if (sql==null && compare(EXECUTE_BATCH,name)) {
-            sql = "batch";
-        }
-        return sql;
-    }
-
-    /**
-     * Invoked when a query execution, a call to execute/executeQuery or executeBatch succeeded and was within the timing threshold
-     * @param query the query that was executed and failed
-     * @param args the arguments to the execution
-     * @param name the name of the method used to execute {@link AbstractCreateStatementInterceptor#isExecute(Method, boolean)}
-     * @param start the time the query execution started
-     * @param delta the time the execution took
-     * @return - the SQL that was executed or the string &quot;batch&quot; if it was a batch execution 
-     */
-    protected String reportQuery(String query, Object[] args, final String name, long start, long delta) {
-        //extract the query string
-        String sql = (query==null && args!=null &&  args.length>0)?(String)args[0]:query;
-        //if we do batch execution, then we name the query 'batch'
-        if (sql==null && compare(EXECUTE_BATCH,name)) {
-            sql = "batch";
-        }
-        return sql;
-    }
-
-    /**
-     * Invoked when a query execution, a call to execute/executeQuery or executeBatch succeeded and was exceeded the timing threshold
-     * @param query the query that was executed and failed
-     * @param args the arguments to the execution
-     * @param name the name of the method used to execute {@link AbstractCreateStatementInterceptor#isExecute(Method, boolean)}
-     * @param start the time the query execution started
-     * @param delta the time the execution took
-     * @return - the SQL that was executed or the string &quot;batch&quot; if it was a batch execution 
-     */
-    protected String reportSlowQuery(String query, Object[] args, final String name, long start, long delta) {
-        //extract the query string
-        String sql = (query==null && args!=null &&  args.length>0)?(String)args[0]:query;
-        //if we do batch execution, then we name the query 'batch'
-        if (sql==null && compare(EXECUTE_BATCH,name)) {
-            sql = "batch";
-        }
-        return sql;
-    }
-    
-    /**
-     * returns the query measure threshold.
-     * This value is in milliseconds. If the query is faster than this threshold than it wont be accounted for
-     * @return the threshhold in milliseconds
-     */
-    public long getThreshold() {
-        return threshold;
-    }
-
-    /**
-     * Sets the query measurement threshold. The value is in milliseconds.
-     * If the query goes faster than this threshold it will not be recorded.
-     * @param threshold set to -1 to record every query. Value is in milliseconds.
-     */
-    public void setThreshold(long threshold) {
-        this.threshold = threshold;
-    }
-
-    /**
-     * Creates a constructor for a proxy class, if one doesn't already exist
-     * @param idx - the index of the constructor
-     * @param clazz - the interface that the proxy will implement
-     * @return - returns a constructor used to create new instances
-     * @throws NoSuchMethodException
-     */
-    protected Constructor<?> getConstructor(int idx, Class<?> clazz) throws NoSuchMethodException {
-        if (constructors[idx]==null) {
-            Class<?> proxyClass = Proxy.getProxyClass(SlowQueryReport.class.getClassLoader(), new Class[] {clazz});
-            constructors[idx] = proxyClass.getConstructor(new Class[] { InvocationHandler.class });
-        }
-        return constructors[idx];
-    }
-
-    /**
-     * Creates a statement interceptor to monitor query response times
-     */
-    @Override
-    public Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time) {
-        try {
-            Object result = null;
-            String name = method.getName();
-            String sql = null;
-            Constructor<?> constructor = null;
-            if (compare(CREATE_STATEMENT,name)) {
-                //createStatement
-                constructor = getConstructor(CREATE_STATEMENT_IDX,Statement.class);
-            }else if (compare(PREPARE_STATEMENT,name)) {
-                //prepareStatement
-                sql = (String)args[0];
-                constructor = getConstructor(PREPARE_STATEMENT_IDX,PreparedStatement.class);
-                if (sql!=null) {
-                    prepareStatement(sql, time);
-                }
-            }else if (compare(PREPARE_CALL,name)) {
-                //prepareCall
-                sql = (String)args[0];
-                constructor = getConstructor(PREPARE_CALL_IDX,CallableStatement.class);
-                prepareCall(sql,time);
-            }else {
-                //do nothing, might be a future unsupported method
-                //so we better bail out and let the system continue
-                return statement;
-            }
-            result = constructor.newInstance(new Object[] { new StatementProxy(statement,sql) });
-            return result;
-        }catch (Exception x) {
-            log.warn("Unable to create statement proxy for slow query report.",x);
-        }
-        return statement;
-    }
-
-
-    /**
-     * Class to measure query execute time
-     * @author fhanik
-     *
-     */
-    protected class StatementProxy implements InvocationHandler {
-        protected boolean closed = false;
-        protected Object delegate;
-        protected final String query;
-        public StatementProxy(Object parent, String query) {
-            this.delegate = parent;
-            this.query = query;
-        }
-        
-        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.");
-            boolean process = false;
-            //check to see if we are about to execute a query
-            process = isExecute( method, process);
-            //if we are executing, get the current time
-            long start = (process)?System.currentTimeMillis():0;
-            Object result =  null;
-            try {
-                //execute the query
-                result =  method.invoke(delegate,args);
-            }catch (Throwable t) {
-                reportFailedQuery(query,args,name,start,t);
-                if (t instanceof InvocationTargetException) {
-                    InvocationTargetException it = (InvocationTargetException)t;
-                    throw it.getCause()!=null?it.getCause():it;
-                } else {
-                    throw t;
-                }
-            }
-            //measure the time
-            long delta = (process)?(System.currentTimeMillis()-start):Long.MIN_VALUE;
-            //see if we meet the requirements to measure
-            if (delta>threshold) {
-                try {
-                    //report the slow query
-                    reportSlowQuery(query, args, name, start, delta);
-                }catch (Exception t) {
-                    if (log.isWarnEnabled()) log.warn("Unable to process slow query",t);
-                }
-            } else if (process) {
-                reportQuery(query, args, name, start, delta);
-            }
-            //perform close cleanup
-            if (close) {
-                closed=true;
-                delegate = null;
-            }
-            return result;
-        }
-    }    
-
-}
\ No newline at end of file
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/ConnectionState.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/ConnectionState.java
deleted file mode 100644 (file)
index 6da8bd5..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * 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.pool.interceptor;
-
-import java.lang.reflect.Method;
-import java.sql.SQLException;
-
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.jdbc.pool.ConnectionPool;
-import org.apache.tomcat.jdbc.pool.DataSourceFactory;
-import org.apache.tomcat.jdbc.pool.JdbcInterceptor;
-import org.apache.tomcat.jdbc.pool.PoolConfiguration;
-import org.apache.tomcat.jdbc.pool.PooledConnection;
-
-/**
- * Interceptor that keep track of connection state to avoid roundtrips to the database.
- * The {@link org.apache.tomcat.jdbc.pool.ConnectionPool} is optimized to do as little work as possible.
- * The pool itself doesn't remember settings like {@link java.sql.Connection#setAutoCommit(boolean)}, 
- * {@link java.sql.Connection#setReadOnly(boolean)}, {@link java.sql.Connection#setCatalog(String)} or
- * {@link java.sql.Connection#setTransactionIsolation(int)}. It relies on the application to remember how and when 
- * these settings have been applied.
- * In the cases where the application code doesn't know or want to keep track of the state, this interceptor helps cache the 
- * state, and it also avoids roundtrips to the database asking for it.
- * @author fhanik
- *
- */
-
-public class ConnectionState extends JdbcInterceptor  {
-    private static final Log log = LogFactory.getLog(ConnectionState.class);
-    
-    protected final String[] readState = {"getAutoCommit","getTransactionIsolation","isReadOnly","getCatalog"};
-    protected final String[] writeState = {"setAutoCommit","setTransactionIsolation","setReadOnly","setCatalog"};
-
-    protected Boolean autoCommit = null;
-    protected Integer transactionIsolation = null;
-    protected Boolean readOnly = null;
-    protected String catalog = null;
-    
-    
-    @Override
-    public void reset(ConnectionPool parent, PooledConnection con) {
-        if (parent==null || con==null) {
-            //we are resetting, reset our defaults
-            autoCommit = null;
-            transactionIsolation = null;
-            readOnly = null;
-            catalog = null;
-            return;
-        }
-        PoolConfiguration poolProperties = parent.getPoolProperties();
-        if (poolProperties.getDefaultTransactionIsolation()!=DataSourceFactory.UNKNOWN_TRANSACTIONISOLATION) {
-            try {
-                if (transactionIsolation==null || transactionIsolation.intValue()!=poolProperties.getDefaultTransactionIsolation()) {
-                    con.getConnection().setTransactionIsolation(poolProperties.getDefaultTransactionIsolation());
-                    transactionIsolation = Integer.valueOf(poolProperties.getDefaultTransactionIsolation());
-                }
-            }catch (SQLException x) {
-                transactionIsolation = null;
-                log.error("Unable to reset transaction isolation state to connection.",x);
-            }
-        }
-        if (poolProperties.getDefaultReadOnly()!=null) {
-            try {
-                if (readOnly==null || readOnly.booleanValue()!=poolProperties.getDefaultReadOnly().booleanValue()) {
-                    con.getConnection().setReadOnly(poolProperties.getDefaultReadOnly().booleanValue());
-                    readOnly = poolProperties.getDefaultReadOnly();
-                }
-            }catch (SQLException x) {
-                readOnly = null;
-                log.error("Unable to reset readonly state to connection.",x);
-            }
-        }
-        if (poolProperties.getDefaultAutoCommit()!=null) {
-            try {
-                if (autoCommit==null || autoCommit.booleanValue()!=poolProperties.getDefaultAutoCommit().booleanValue()) {
-                    con.getConnection().setAutoCommit(poolProperties.getDefaultAutoCommit().booleanValue());
-                    autoCommit = poolProperties.getDefaultAutoCommit();
-                }
-            }catch (SQLException x) {
-                autoCommit = null;
-                log.error("Unable to reset autocommit state to connection.",x);
-            }
-        }
-        if (poolProperties.getDefaultCatalog()!=null) {
-            try {
-                if (catalog==null || (!catalog.equals(poolProperties.getDefaultCatalog()))) {
-                    con.getConnection().setCatalog(poolProperties.getDefaultCatalog());
-                    catalog = poolProperties.getDefaultCatalog();
-                }
-            }catch (SQLException x) {
-                catalog = null;
-                log.error("Unable to reset default catalog state to connection.",x);
-            }
-        }
-        
-    }
-
-    @Override
-    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-        String name = method.getName();
-        boolean read = false;
-        int index = -1;
-        for (int i=0; (!read) && i<readState.length; i++) {
-            read = compare(name,readState[i]);
-            if (read) index = i;
-        }
-        boolean write = false;
-        for (int i=0; (!write) && (!read) && i<writeState.length; i++) {
-            write = compare(name,writeState[i]);
-            if (write) index = i;
-        }
-        Object result = null;
-        if (read) {
-            switch (index) {
-                case 0:{result = autoCommit; break;}
-                case 1:{result = transactionIsolation; break;}
-                case 2:{result = readOnly; break;}
-                case 3:{result = catalog; break;}
-                default: result = null;
-            }
-            //return cached result, if we have it
-            if (result!=null) return result;
-        }
-
-        result = super.invoke(proxy, method, args);
-        if (read || write) {
-            switch (index) {
-                case 0:{autoCommit = (Boolean) (read?result:args[0]); break;}
-                case 1:{transactionIsolation = (Integer)(read?result:args[0]); break;}
-                case 2:{readOnly = (Boolean)(read?result:args[0]); break;}
-                case 3:{catalog = (String)(read?result:args[0]); break;}
-            }
-        }
-        return result;
-    }
-
-}
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/ResetAbandonedTimer.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/ResetAbandonedTimer.java
deleted file mode 100644 (file)
index 328d6be..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- *  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.pool.interceptor;
-
-import java.lang.reflect.Method;
-
-import org.apache.tomcat.jdbc.pool.JdbcInterceptor;
-import org.apache.tomcat.jdbc.pool.PooledConnection;
-import org.apache.tomcat.jdbc.pool.ProxyConnection;
-
-/**
- * Class that resets the abandoned timer on any activity on the 
- * Connection or any successful query executions.
- * This interceptor is useful for when you have a {@link org.apache.tomcat.jdbc.pool.PoolConfiguration#setRemoveAbandonedTimeout(int)}
- * that is fairly low, and you want to reset the abandoned time each time any operation on the connection is performed
- * This is useful for batch processing programs that use connections for extensive amount of times.
- * @author fhanik
- *
- */
-public class ResetAbandonedTimer extends AbstractQueryReport {
-
-    public ResetAbandonedTimer() {
-        // TODO Auto-generated constructor stub
-    }
-    
-    public boolean resetTimer() {
-        boolean result = false;
-        JdbcInterceptor interceptor = this.getNext();
-        while (interceptor!=null && result==false) {
-            if (interceptor instanceof ProxyConnection) {
-                PooledConnection con = ((ProxyConnection)interceptor).getConnection();
-                if (con!=null) {
-                    con.setTimestamp(System.currentTimeMillis());
-                    result = true;
-                } else {
-                    break;
-                }
-            }
-            interceptor = interceptor.getNext();
-        }
-        return result;
-    }
-
-
-    @Override
-    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-        // TODO Auto-generated method stub
-        Object result = super.invoke(proxy, method, args);
-        resetTimer();
-        return result;
-    }
-
-    @Override
-    protected void prepareCall(String query, long time) {
-        resetTimer();
-    }
-
-    @Override
-    protected void prepareStatement(String sql, long time) {
-        resetTimer();
-
-    }
-
-    @Override
-    public void closeInvoked() {
-        resetTimer();
-    }
-
-    @Override
-    protected String reportQuery(String query, Object[] args, String name,long start, long delta) {
-        resetTimer();
-        return super.reportQuery(query, args, name, start, delta);
-    }
-
-    @Override
-    protected String reportSlowQuery(String query, Object[] args, String name,long start, long delta) {
-        resetTimer();
-        return super.reportSlowQuery(query, args, name, start, delta);
-    }
-}
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java
deleted file mode 100644 (file)
index 85b0779..0000000
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * 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.pool.interceptor;
-
-import java.util.Iterator;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.jdbc.pool.ConnectionPool;
-import org.apache.tomcat.jdbc.pool.PooledConnection;
-import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty;
-
-/**
- * Slow query report interceptor. Tracks timing of query executions.
- * @author Filip Hanik
- * @version 1.0
- */
-public class SlowQueryReport extends AbstractQueryReport  {
-    //logger
-    private static final Log log = LogFactory.getLog(SlowQueryReport.class);
-
-    /**
-     * we will be keeping track of query stats on a per pool basis
-     */
-    protected static ConcurrentHashMap<String,ConcurrentHashMap<String,QueryStats>> perPoolStats = 
-        new ConcurrentHashMap<String,ConcurrentHashMap<String,QueryStats>>();
-    /**
-     * the queries that are used for this interceptor.
-     */
-    protected ConcurrentHashMap<String,QueryStats> queries = null;
-    /**
-     * Maximum number of queries we will be storing
-     */
-    protected int  maxQueries= 1000; //don't store more than this amount of queries
-    
-    /**
-     * Returns the query stats for a given pool
-     * @param poolname - the name of the pool we want to retrieve stats for
-     * @return a hash map containing statistics for 0 to maxQueries 
-     */
-    public static ConcurrentHashMap<String,QueryStats> getPoolStats(String poolname) {
-        return perPoolStats.get(poolname);
-    }
-    
-    /**
-     * Creates a slow query report interceptor
-     */
-    public SlowQueryReport() {
-        super();
-    }
-
-    public void setMaxQueries(int maxQueries) {
-        this.maxQueries = maxQueries;
-    }
-
-
-    @Override
-    protected String reportFailedQuery(String query, Object[] args, String name, long start, Throwable t) {
-        String sql = super.reportFailedQuery(query, args, name, start, t);
-        if (this.maxQueries > 0 ) {
-            long now = System.currentTimeMillis();
-            long delta = now - start;
-            QueryStats qs = this.getQueryStats(sql);
-            qs.failure(delta, now);
-        }
-        return sql;
-    }
-
-    @Override
-    protected String reportSlowQuery(String query, Object[] args, String name, long start, long delta) {
-        String sql = super.reportSlowQuery(query, args, name, start, delta);
-        if (this.maxQueries > 0 ) {
-            QueryStats qs = this.getQueryStats(sql);
-            qs.add(delta, start);
-        }
-        return sql;
-    }
-
-    /**
-     * invoked when the connection receives the close request
-     * Not used for now.
-     */
-    @Override
-    public void closeInvoked() {
-        queries = null;
-    }
-    
-    @Override
-    public void prepareStatement(String sql, long time) {
-        QueryStats qs = getQueryStats(sql);
-        qs.prepare(time, System.currentTimeMillis());
-    }
-    
-    @Override
-    public void prepareCall(String sql, long time) {
-        QueryStats qs = getQueryStats(sql);
-        qs.prepare(time, System.currentTimeMillis());
-    }
-    
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void poolStarted(ConnectionPool pool) {
-        super.poolStarted(pool);
-        //see if we already created a map for this pool
-        queries = SlowQueryReport.perPoolStats.get(pool.getName());
-        if (queries==null) {
-            //create the map to hold our stats
-            //however TODO we need to improve the eviction
-            //selection
-            queries = new ConcurrentHashMap<String,QueryStats>() {
-                
-            };
-            if (perPoolStats.putIfAbsent(pool.getName(), queries)!=null) {
-                //there already was one
-                queries = SlowQueryReport.perPoolStats.get(pool.getName());
-            }
-        }
-    }
-    
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void poolClosed(ConnectionPool pool) {
-        perPoolStats.remove(pool.getName());
-        super.poolClosed(pool);
-    }
-    
-    protected QueryStats getQueryStats(String sql) {
-        ConcurrentHashMap<String,QueryStats> queries = SlowQueryReport.this.queries;
-        if (queries==null) return null;
-        QueryStats qs = queries.get(sql);
-        if (qs == null) {
-            qs = new QueryStats(sql);
-            if (queries.putIfAbsent(sql,qs)!=null) {
-                qs = queries.get(sql);
-            } else {
-                //we added a new element, see if we need to remove the oldest
-                if (queries.size() > maxQueries) {
-                    removeOldest(queries);
-                }
-            }
-        }
-        return qs;
-    }
-    
-    /**
-     * TODO - implement a better algorithm
-     * @param queries
-     */
-    protected void removeOldest(ConcurrentHashMap<String,QueryStats> queries) {
-        Iterator<String> it = queries.keySet().iterator();
-        while (queries.size()>maxQueries && it.hasNext()) {
-            String sql = it.next();
-            it.remove();
-            if (log.isDebugEnabled()) log.debug("Removing slow query, capacity reached:"+sql);
-        } 
-    }
-
-
-    @Override
-    public void reset(ConnectionPool parent, PooledConnection con) {
-        super.reset(parent, con);
-        if (parent!=null) 
-            queries = SlowQueryReport.perPoolStats.get(parent.getName());
-    }
-
-
-    @Override
-    public void setProperties(Map<String, InterceptorProperty> properties) {
-        super.setProperties(properties);
-        final String threshold = "threshold";
-        final String maxqueries= "maxQueries";
-        InterceptorProperty p1 = properties.get(threshold);
-        InterceptorProperty p2 = properties.get(maxqueries);
-        if (p1!=null) {
-            setThreshold(Long.parseLong(p1.getValue()));
-        }
-        if (p2!=null) {
-            setMaxQueries(Integer.parseInt(p2.getValue()));
-        }
-    }
-
-
-    /**
-     * 
-     * @author fhanik
-     *
-     */
-    public static class QueryStats {
-        static final String[] FIELD_NAMES = new String[] {
-            "query",
-            "nrOfInvocations",
-            "maxInvocationTime",
-            "maxInvocationDate",
-            "minInvocationTime",
-            "minInvocationDate",
-            "totalInvocationTime",
-            "failures",
-            "prepareCount",
-            "prepareTime",
-            "lastInvocation"
-        };
-        
-        static final  String[] FIELD_DESCRIPTIONS = new String[] {
-            "The SQL query",
-            "The number of query invocations, a call to executeXXX",
-            "The longest time for this query in milliseconds",
-            "The time and date for when the longest query took place",
-            "The shortest time for this query in milliseconds",
-            "The time and date for when the shortest query took place",
-            "The total amount of milliseconds spent executing this query",
-            "The number of failures for this query",
-            "The number of times this query was prepared (prepareStatement/prepareCall)",
-            "The total number of milliseconds spent preparing this query",
-            "The date and time of the last invocation"
-        };
-        
-        static final OpenType[] FIELD_TYPES = new OpenType[] { 
-            SimpleType.STRING,
-            SimpleType.INTEGER,
-            SimpleType.LONG,
-            SimpleType.LONG,
-            SimpleType.LONG,
-            SimpleType.LONG,
-            SimpleType.LONG,
-            SimpleType.LONG,
-            SimpleType.INTEGER,
-            SimpleType.LONG,
-            SimpleType.LONG 
-        };
-
-        private final String query;
-        private int nrOfInvocations;
-        private long maxInvocationTime = Long.MIN_VALUE;
-        private long maxInvocationDate;
-        private long minInvocationTime = Long.MAX_VALUE;
-        private long minInvocationDate;
-        private long totalInvocationTime;
-        private long failures;
-        private int prepareCount;
-        private long prepareTime;
-        private volatile long lastInvocation = 0;
-        
-        public static String[] getFieldNames() {
-            return FIELD_NAMES;
-        }
-        
-        public static String[] getFieldDescriptions() {
-            return FIELD_DESCRIPTIONS;
-        }
-        
-        public static OpenType[] getFieldTypes() {
-            return FIELD_TYPES;
-        }
-        
-        @Override
-        public String toString() {
-            StringBuilder buf = new StringBuilder("QueryStats[query:");
-            buf.append(query);
-            buf.append(", nrOfInvocations:");
-            buf.append(nrOfInvocations);
-            buf.append(", maxInvocationTime:");
-            buf.append(maxInvocationTime);
-            buf.append(", maxInvocationDate:");
-            buf.append(new java.util.Date(maxInvocationDate).toGMTString());
-            buf.append(", minInvocationTime:");
-            buf.append(minInvocationTime);
-            buf.append(", minInvocationDate:");
-            buf.append(new java.util.Date(minInvocationDate).toGMTString());
-            buf.append(", totalInvocationTime:");
-            buf.append(totalInvocationTime);
-            buf.append(", averageInvocationTime:");
-            buf.append((float)totalInvocationTime / (float)nrOfInvocations);
-            buf.append(", failures:");
-            buf.append(failures);
-            buf.append(", prepareCount:");
-            buf.append(prepareCount);
-            buf.append(", prepareTime:");
-            buf.append(prepareTime);
-            buf.append("]");
-            return buf.toString();
-        }
-        
-        public CompositeDataSupport getCompositeData(final CompositeType type) throws OpenDataException{
-            Object[] values = new Object[] {
-                    query,
-                    Integer.valueOf(nrOfInvocations),
-                    Long.valueOf(maxInvocationTime),
-                    Long.valueOf(maxInvocationDate),
-                    Long.valueOf(minInvocationTime),
-                    Long.valueOf(minInvocationDate),
-                    Long.valueOf(totalInvocationTime),
-                    Long.valueOf(failures),
-                    Integer.valueOf(prepareCount),
-                    Long.valueOf(prepareTime),
-                    Long.valueOf(lastInvocation)
-            };
-            return new CompositeDataSupport(type,FIELD_NAMES,values);
-        }
-        
-        public QueryStats(String query) {
-            this.query = query;
-        }
-        
-        public void prepare(long invocationTime, long now) {
-            prepareCount++;
-            prepareTime+=invocationTime;
-            
-        }
-        
-        public void add(long invocationTime, long now) {
-            //not thread safe, but don't sacrifice performance for this kind of stuff
-            maxInvocationTime = Math.max(invocationTime, maxInvocationTime);
-            if (maxInvocationTime == invocationTime) {
-                maxInvocationDate = now;
-            }
-            minInvocationTime = Math.min(invocationTime, minInvocationTime);
-            if (minInvocationTime==invocationTime) {
-                minInvocationDate = now;
-            }
-            nrOfInvocations++;
-            totalInvocationTime+=invocationTime;
-            lastInvocation = now;
-        }
-        
-        public void failure(long invocationTime, long now) {
-            add(invocationTime,now);
-            failures++;
-            
-        }
-        
-        public String getQuery() {
-            return query;
-        }
-
-        public int getNrOfInvocations() {
-            return nrOfInvocations;
-        }
-
-        public long getMaxInvocationTime() {
-            return maxInvocationTime;
-        }
-
-        public long getMaxInvocationDate() {
-            return maxInvocationDate;
-        }
-
-        public long getMinInvocationTime() {
-            return minInvocationTime;
-        }
-
-        public long getMinInvocationDate() {
-            return minInvocationDate;
-        }
-
-        public long getTotalInvocationTime() {
-            return totalInvocationTime;
-        }
-
-        @Override
-        public int hashCode() {
-            return query.hashCode();
-        }
-        
-        @Override
-        public boolean equals(Object other) {
-            if (other instanceof QueryStats) {
-                QueryStats qs = (QueryStats)other;
-                return qs.query.equals(this.query);
-            } 
-            return false;
-        }
-        
-        public boolean isOlderThan(QueryStats other) {
-            return this.lastInvocation < other.lastInvocation;
-        }
-    }
-    
-    
-}
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java
deleted file mode 100644 (file)
index 433519c..0000000
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * 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.pool.interceptor;
-
-import java.lang.management.ManagementFactory;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicLong;
-
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.ListenerNotFoundException;
-import javax.management.MBeanException;
-import javax.management.MBeanNotificationInfo;
-import javax.management.MBeanRegistrationException;
-import javax.management.MalformedObjectNameException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.Notification;
-import javax.management.NotificationBroadcasterSupport;
-import javax.management.NotificationEmitter;
-import javax.management.NotificationFilter;
-import javax.management.NotificationListener;
-import javax.management.ObjectName;
-import javax.management.RuntimeOperationsException;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenDataException;
-
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.jdbc.pool.ConnectionPool;
-import org.apache.tomcat.jdbc.pool.PooledConnection;
-import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty;
-/**
- * Publishes data to JMX and provides notifications 
- * when failures happen.
- * @author fhanik
- *
- */
-public class SlowQueryReportJmx extends SlowQueryReport implements NotificationEmitter, SlowQueryReportJmxMBean{
-    public static final String SLOW_QUERY_NOTIFICATION = "SLOW QUERY";
-    public static final String FAILED_QUERY_NOTIFICATION = "FAILED QUERY";
-
-    protected static CompositeType SLOW_QUERY_TYPE; 
-        
-    private static final Log log = LogFactory.getLog(SlowQueryReportJmx.class);
-    
-    
-    protected static ConcurrentHashMap<String,SlowQueryReportJmxMBean> mbeans = 
-        new ConcurrentHashMap<String,SlowQueryReportJmxMBean>(); 
-    
-    
-    //==============================JMX STUFF========================
-    protected volatile NotificationBroadcasterSupport notifier = new NotificationBroadcasterSupport();
-
-    public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws IllegalArgumentException {
-        notifier.addNotificationListener(listener, filter, handback);
-    }
-
-    
-    public MBeanNotificationInfo[] getNotificationInfo() {
-        return notifier.getNotificationInfo();
-    }
-
-    public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException {
-        notifier.removeNotificationListener(listener);
-        
-    }
-
-    public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException {
-        notifier.removeNotificationListener(listener, filter, handback);
-        
-    }
-
-
-    //==============================JMX STUFF========================    
-    
-    protected String poolName = null;
-    
-    protected static AtomicLong notifySequence = new AtomicLong(0);
-    
-    protected boolean notifyPool = true;
-    
-    protected ConnectionPool pool = null;
-    
-    protected static CompositeType getCompositeType() {
-        if (SLOW_QUERY_TYPE==null) {
-            try {
-                SLOW_QUERY_TYPE = new CompositeType(
-                        SlowQueryReportJmx.class.getName(),
-                        "Composite data type for query statistics",
-                        QueryStats.getFieldNames(),
-                        QueryStats.getFieldDescriptions(),
-                        QueryStats.getFieldTypes());
-            }catch (OpenDataException x) {
-                log.warn("Unable to initialize composite data type for JMX stats and notifications.",x);
-            }
-        }
-        return SLOW_QUERY_TYPE;
-    }
-    
-    @Override
-    public void reset(ConnectionPool parent, PooledConnection con) {
-        // TODO Auto-generated method stub
-        super.reset(parent, con);
-        if (parent!=null) {
-            poolName = parent.getName();
-            pool = parent;
-            registerJmx();
-        }
-    }
-
-
-    @Override
-    public void poolClosed(ConnectionPool pool) {
-        this.poolName = pool.getName();
-        deregisterJmx();
-        super.poolClosed(pool);
-    }
-
-    @Override
-    public void poolStarted(ConnectionPool pool) {
-        this.pool = pool;
-        super.poolStarted(pool);
-        this.poolName = pool.getName();
-    }
-
-    @Override
-    protected String reportFailedQuery(String query, Object[] args, String name, long start, Throwable t) {
-        query = super.reportFailedQuery(query, args, name, start, t);
-        notifyJmx(query,FAILED_QUERY_NOTIFICATION);
-        return query;
-    }
-
-    protected void notifyJmx(String query, String type) {
-        try {
-            long sequence = notifySequence.incrementAndGet();
-            
-            if (isNotifyPool()) {
-                if (this.pool!=null && this.pool.getJmxPool()!=null) {
-                    this.pool.getJmxPool().notify(type, query);
-                }
-            } else {
-                if (notifier!=null) {
-                    Notification notification = 
-                        new Notification(type, 
-                                         this, 
-                                         sequence, 
-                                         System.currentTimeMillis(),
-                                         query);
-                    
-                    notifier.sendNotification(notification);
-                }
-            }
-        } catch (RuntimeOperationsException e) {
-            if (log.isDebugEnabled()) {
-                log.debug("Unable to send failed query notification.",e);
-            }
-        }
-    }
-
-    @Override
-    protected String reportSlowQuery(String query, Object[] args, String name, long start, long delta) {
-        query = super.reportSlowQuery(query, args, name, start, delta);
-        notifyJmx(query,SLOW_QUERY_NOTIFICATION);
-        return query;
-    }
-
-    /**
-     * JMX operation - return the names of all the pools
-     * @return - all the names of pools that we have stored data for
-     */
-    public String[] getPoolNames() {
-        Set<String> keys = perPoolStats.keySet();
-        return keys.toArray(new String[0]);
-    }
-
-    /**
-     * JMX operation - return the name of the pool
-     * @return the name of the pool, unique within the JVM
-     */
-    public String getPoolName() {
-        return poolName;
-    }
-
-
-    public boolean isNotifyPool() {
-        return notifyPool;
-    }
-
-    public void setNotifyPool(boolean notifyPool) {
-        this.notifyPool = notifyPool;
-    }
-
-    /**
-     * JMX operation - remove all stats for this connection pool
-     */
-    public void resetStats() {
-        ConcurrentHashMap<String,QueryStats> queries = perPoolStats.get(poolName);
-        if (queries!=null) {
-            Iterator<String> it = queries.keySet().iterator();
-            while (it.hasNext()) it.remove();
-        }
-    }
-    
-    /**
-     * JMX operation - returns all the queries we have collected.
-     * @return - the slow query report as composite data.
-     */
-    public CompositeData[] getSlowQueriesCD() throws OpenDataException {
-        CompositeDataSupport[] result = null;
-        ConcurrentHashMap<String,QueryStats> queries = perPoolStats.get(poolName);
-        if (queries!=null) {
-            Set<Map.Entry<String,QueryStats>> stats = queries.entrySet();
-            if (stats!=null) {
-                result = new CompositeDataSupport[stats.size()];
-                Iterator<Map.Entry<String,QueryStats>> it = stats.iterator();
-                int pos = 0;
-                while (it.hasNext()) {
-                    Map.Entry<String,QueryStats> entry = it.next();
-                    QueryStats qs = entry.getValue();
-                    result[pos++] = qs.getCompositeData(getCompositeType());
-                }
-            }
-        }
-        return result;
-    }
-    
-    protected void deregisterJmx() {
-        try {
-            if (mbeans.remove(poolName)!=null) {
-                ObjectName oname = getObjectName(getClass(),poolName);
-                ManagementFactory.getPlatformMBeanServer().unregisterMBean(oname);
-            }
-        } catch (MBeanRegistrationException e) {
-            log.debug("Jmx deregistration failed.",e);
-        } catch (InstanceNotFoundException e) {
-            log.debug("Jmx deregistration failed.",e);
-        } catch (MalformedObjectNameException e) {
-            log.warn("Jmx deregistration failed.",e);
-        } catch (RuntimeOperationsException e) {
-            log.warn("Jmx deregistration failed.",e);
-        }
-        
-    }
-
-
-    public static ObjectName getObjectName(Class<?> clazz, String poolName) throws MalformedObjectNameException {
-        ObjectName oname = new ObjectName(ConnectionPool.POOL_JMX_TYPE_PREFIX+clazz.getName()+",name=" + poolName);
-        return oname;
-    }
-    
-    protected void registerJmx() {
-        try {
-            //only if we notify the pool itself
-            if (isNotifyPool()) {
-                
-            } else if (getCompositeType()!=null) {
-                ObjectName oname = getObjectName(getClass(),poolName);
-                if (mbeans.putIfAbsent(poolName, this)==null) {
-                    ManagementFactory.getPlatformMBeanServer().registerMBean(this, oname);
-                }
-            } else {
-                log.warn(SlowQueryReport.class.getName()+ "- No JMX support, composite type was not found.");
-            }
-        } catch (MalformedObjectNameException e) {
-            log.error("Jmx registration failed, no JMX data will be exposed for the query stats.",e);
-        } catch (RuntimeOperationsException e) {
-            log.error("Jmx registration failed, no JMX data will be exposed for the query stats.",e);
-        } catch (MBeanException e) {
-            log.error("Jmx registration failed, no JMX data will be exposed for the query stats.",e);
-        } catch (InstanceAlreadyExistsException e) {
-            log.error("Jmx registration failed, no JMX data will be exposed for the query stats.",e);
-        } catch (NotCompliantMBeanException e) {
-            log.error("Jmx registration failed, no JMX data will be exposed for the query stats.",e);
-        }
-    }
-    
-    @Override
-    public void setProperties(Map<String, InterceptorProperty> properties) {
-        super.setProperties(properties);
-        final String threshold = "notifyPool";
-        InterceptorProperty p1 = properties.get(threshold);
-        if (p1!=null) {
-            this.setNotifyPool(Boolean.parseBoolean(p1.getValue()));
-        }
-    }
-
-
-}
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmxMBean.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmxMBean.java
deleted file mode 100644 (file)
index 908eb1c..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* 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.pool.interceptor;
-
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.OpenDataException;
-
-public interface SlowQueryReportJmxMBean {
-    public CompositeData[] getSlowQueriesCD() throws OpenDataException;
-}
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java
deleted file mode 100644 (file)
index 533211c..0000000
+++ /dev/null
@@ -1,261 +0,0 @@
-/* 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.pool.interceptor;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.sql.Statement;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.apache.tomcat.jdbc.pool.ConnectionPool;
-import org.apache.tomcat.jdbc.pool.PooledConnection;
-import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty;
-
-public class StatementCache extends StatementDecoratorInterceptor {
-    protected static final String[] ALL_TYPES = new String[] {PREPARE_STATEMENT,PREPARE_CALL}; 
-    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 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;
-    }
-
-    @Override
-    public void setProperties(Map<String, InterceptorProperty> properties) {
-        super.setProperties(properties);
-        InterceptorProperty p = properties.get("prepared");
-        if (p!=null) cachePrepared = p.getValueAsBoolean(cachePrepared);
-        p = properties.get("callable");
-        if (p!=null) cacheCallable = p.getValueAsBoolean(cacheCallable);
-        p = properties.get("max");
-        if (p!=null) maxCacheSize = p.getValueAsInt(maxCacheSize);
-        if (cachePrepared && cacheCallable) {
-            this.types = ALL_TYPES;
-        } else if (cachePrepared) {
-            this.types = PREPARED_TYPE;
-        } else if (cacheCallable) {
-            this.types = CALLABLE_TYPE;
-        } else {
-            this.types = NO_TYPE;
-        }
-    
-    }
-    /*end properties for the statement cache*/
-    
-    /*begin the cache size*/
-    private static ConcurrentHashMap<ConnectionPool,AtomicInteger> cacheSizeMap = 
-        new ConcurrentHashMap<ConnectionPool,AtomicInteger>();
-    
-    private AtomicInteger cacheSize;
-
-    @Override
-    public void poolStarted(ConnectionPool pool) {
-        cacheSizeMap.putIfAbsent(pool, new AtomicInteger(0));
-        super.poolStarted(pool);
-    }
-    
-    @Override
-    public void poolClosed(ConnectionPool pool) {
-        cacheSizeMap.remove(pool);
-        super.poolClosed(pool);
-    }
-    /*end the cache size*/
-    
-    /*begin the actual statement cache*/
-    @Override
-    public void reset(ConnectionPool parent, PooledConnection con) {
-        super.reset(parent, con);
-        if (parent==null) {
-            cacheSize = null;
-            this.pcon = null;
-        } else {
-            cacheSize = cacheSizeMap.get(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);
-            }
-        }
-    }
-    
-    @Override
-    public void disconnected(ConnectionPool parent, PooledConnection con, boolean finalizing) {
-        ConcurrentHashMap<String,CachedStatement> statements = 
-            (ConcurrentHashMap<String,CachedStatement>)con.getAttributes().get(STATEMENT_CACHE_ATTR);
-        
-        if (statements!=null) {
-            for (Map.Entry<String, CachedStatement> p : statements.entrySet()) {
-                closeStatement(p.getValue());
-            }
-            statements.clear();
-        }
-        
-        super.disconnected(parent, con, finalizing);
-    }
-    
-    public void closeStatement(CachedStatement st) {
-        if (st==null) return;
-        st.forceClose();
-    }
-    
-    @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);
-        }
-    }
-
-    @Override
-    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-        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 CachedStatement isCached(String sql) {
-        ConcurrentHashMap<String,CachedStatement> cache = 
-            (ConcurrentHashMap<String,CachedStatement>)pcon.getAttributes().get(STATEMENT_CACHE_ATTR);
-        return cache.get(sql);
-    }
-    
-    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())) {
-            return false;
-        } else if (cacheSize.get()>=maxCacheSize) {
-            return false;
-        } else if (cacheSize.incrementAndGet()>maxCacheSize) {
-            cacheSize.decrementAndGet();
-            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 CachedStatement extends StatementDecoratorInterceptor.StatementProxy<Statement> {
-        boolean cached = false;
-        public CachedStatement(Statement parent, String sql) {
-            super(parent, sql);
-        }
-        
-        @Override
-        public void closeInvoked() {
-            //should we cache it
-            boolean shouldClose = true;
-            if (cacheSize.get() < maxCacheSize) {
-                //cache a proxy so that we don't reuse the facade
-                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.closeInvoked();
-            }
-           
-        }
-        
-        public void forceClose() {
-            removeStatement(this);
-            super.closeInvoked();
-        }
-        
-    }
-    
-}
-
-
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java
deleted file mode 100644 (file)
index 922205e..0000000
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * 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.pool.interceptor;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.sql.CallableStatement;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-
-
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.jdbc.pool.interceptor.AbstractCreateStatementInterceptor;
-
-/**
- * Implementation of <b>JdbcInterceptor</b> that proxies resultSets and statements.
- * @author Guillermo Fernandes
- */
-public class StatementDecoratorInterceptor extends AbstractCreateStatementInterceptor {
-
-    private static final Log logger = LogFactory.getLog(StatementDecoratorInterceptor.class);
-
-    private static final String[] EXECUTE_QUERY_TYPES = { "executeQuery" };
-
-    /**
-     * the constructors that are used to create statement proxies
-     */
-    protected static final Constructor<?>[] constructors = new Constructor[AbstractCreateStatementInterceptor.STATEMENT_TYPE_COUNT];
-
-    /**
-     * the constructor to create the resultSet proxies
-     */
-    protected static Constructor<?> resultSetConstructor = null;
-
-    @Override
-    public void closeInvoked() {
-        // nothing to do
-    }
-
-    /**
-     * Creates a constructor for a proxy class, if one doesn't already exist
-     * 
-     * @param idx
-     *            - the index of the constructor
-     * @param clazz
-     *            - the interface that the proxy will implement
-     * @return - returns a constructor used to create new instances
-     * @throws NoSuchMethodException
-     */
-    protected Constructor<?> getConstructor(int idx, Class<?> clazz) throws NoSuchMethodException {
-        if (constructors[idx] == null) {
-            Class<?> proxyClass = Proxy.getProxyClass(StatementDecoratorInterceptor.class.getClassLoader(),
-                    new Class[] { clazz });
-            constructors[idx] = proxyClass.getConstructor(new Class[] { InvocationHandler.class });
-        }
-        return constructors[idx];
-    }
-
-    protected Constructor<?> getResultSetConstructor() throws NoSuchMethodException {
-        if (resultSetConstructor == null) {
-            Class<?> proxyClass = Proxy.getProxyClass(StatementDecoratorInterceptor.class.getClassLoader(),
-                    new Class[] { ResultSet.class });
-            resultSetConstructor = proxyClass.getConstructor(new Class[] { InvocationHandler.class });
-        }
-        return resultSetConstructor;
-    }
-
-    /**
-     * Creates a statement interceptor to monitor query response times
-     */
-    @Override
-    public Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time) {
-        try {
-            String name = method.getName();
-            Constructor<?> constructor = null;
-            String sql = null;
-            if (compare(CREATE_STATEMENT, name)) {
-                // createStatement
-                constructor = getConstructor(CREATE_STATEMENT_IDX, Statement.class);
-            } else if (compare(PREPARE_STATEMENT, name)) {
-                // prepareStatement
-                constructor = getConstructor(PREPARE_STATEMENT_IDX, PreparedStatement.class);
-                sql = (String)args[0];
-            } else if (compare(PREPARE_CALL, name)) {
-                // prepareCall
-                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;
-            }
-            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);
-    }
-
-    protected boolean isExecuteQuery(Method method) {
-        return isExecuteQuery(method.getName());
-    }
-
-    /**
-     * Class to measure query execute time
-     * 
-     * @author fhanik
-     * 
-     */
-    protected class StatementProxy<T extends java.sql.Statement> implements InvocationHandler {
-        
-        protected boolean closed = false;
-        protected T delegate;
-        private Object actualProxy;
-        private Object connection;
-        private String sql;
-        private Constructor constructor;
-
-        public StatementProxy(T delegate, String sql) {
-            this.delegate = delegate;
-            this.sql = sql;
-        }
-        public T getDelegate() {
-            return this.delegate;
-        }
-        
-        public String getSql() {
-            return sql;
-        }
-
-        public void setConnection(Object proxy) {
-            this.connection = proxy;            
-        }
-        public Object getConnection() {
-            return this.connection;
-        }
-
-        public void setActualProxy(Object proxy){
-            this.actualProxy = proxy;
-        }
-        public Object getActualProxy() {
-            return this.actualProxy;
-        }
-        
-        
-        public Constructor getConstructor() {
-            return constructor;
-        }
-        public void setConstructor(Constructor constructor) {
-            this.constructor = constructor;
-        }
-        public void closeInvoked() {
-            if (getDelegate()!=null) {
-                try {
-                    getDelegate().close();
-                }catch (SQLException ignore) {
-                }
-            }
-            closed = true;
-            delegate = null;
-        }
-        
-        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-            if (compare(TOSTRING_VAL,method)) {
-                return toString();
-            }
-            // was close invoked?
-            boolean close = compare(CLOSE_VAL, method);
-            // allow close to be called multiple times
-            if (close && closed)
-                return null;
-            // are we calling isClosed?
-            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 (compare(GETCONNECTION_VAL,method)){
-                return connection;
-            }
-            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 {
-                // perform close cleanup
-                if (close) {
-                    closeInvoked();
-                } 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;
-                }
-            }
-            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 {
-
-        private Object st;
-        private Object delegate;
-
-        public ResultSetProxy(Object st, Object delegate) {
-            this.st = st;
-            this.delegate = delegate;
-        }
-
-        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-            if (method.getName().equals("getStatement")) {
-                return this.st;
-            } else {
-                return method.invoke(this.delegate, args);
-            }
-        }
-    }
-}
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementFinalizer.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/StatementFinalizer.java
deleted file mode 100644 (file)
index f05efde..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.pool.interceptor;
-
-import java.lang.ref.WeakReference;
-import java.lang.reflect.Method;
-import java.sql.Statement;
-import java.util.ArrayList;
-
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.jdbc.pool.ConnectionPool;
-import org.apache.tomcat.jdbc.pool.PooledConnection;
-/**
- * Keeps track of statements associated with a connection and invokes close upon {@link java.sql.Connection#close()}
- * Useful for applications that dont close the associated statements after being done with a connection.
- * @author fhanik
- *
- */
-public class StatementFinalizer extends AbstractCreateStatementInterceptor {
-    private static final Log log = LogFactory.getLog(StatementFinalizer.class);
-    
-    protected ArrayList<WeakReference<Statement>> statements = new ArrayList<WeakReference<Statement>>();
-    
-    @Override
-    public Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time) {
-        // TODO Auto-generated method stub
-        try {
-            if (statement instanceof Statement)
-                statements.add(new WeakReference<Statement>((Statement)statement));
-        }catch (ClassCastException x) {
-            //ignore this one
-        }
-        return statement;
-    }
-    
-    @Override
-    public void closeInvoked() {
-        while (statements.size()>0) {
-            WeakReference<Statement> ws = statements.remove(0);
-            Statement st = ws.get();
-            if (st!=null) {
-                try {
-                    st.close();
-                } catch (Exception ignore) {
-                    if (log.isDebugEnabled()) {
-                        log.debug("Unable to closed statement upon connection close.",ignore);
-                    }
-                }
-            }
-        }
-    }
-
-    @Override
-    public void reset(ConnectionPool parent, PooledConnection con) {
-        statements.clear();
-        super.reset(parent, con);
-    }
-    
-    
-}
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/mbeans-descriptors.xml b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/interceptor/mbeans-descriptors.xml
deleted file mode 100644 (file)
index e312d05..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0"?>
-<!--
- 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.
--->
-<mbeans-descriptors>
-
-  <mbean description="Reports " domain="tomcat.jdbc" group="jdbc-pool" name="SlowQueryReportJmx" 
-         type="org.apache.tomcat.jdbc.pool.interceptor.SlowQueryReportJmx">
-
-    <attribute description="The name of the connection pool this Jmx bean is representing" name="poolName" type="java.lang.String" writeable="false"/>
-    <attribute description="List of all registered connections pools" name="poolNames" type="[java.lang.String;" writeable="false"/>
-    <attribute description="All the recorded query stats. " name="slowQueriesCD" type="[javax.management.openmbean.CompositeData;" writeable="false"/>
-    <operation description="Clears all the query stats" impact="ACTION" name="resetStats" returnType="void"/>
-
-    <notification description="Notification sent out by the slow query report when a query exceeds the threshhold" name="slow-query">
-      <notification-type>Slow query</notification-type>
-    </notification>
-    
-    <notification description="Notification sent out by the slow query report when a query fails execution" name="failed-query">
-      <notification-type>Failed query execution</notification-type>
-    </notification>
-  </mbean>
-</mbeans-descriptors>
\ No newline at end of file
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java
deleted file mode 100644 (file)
index 657cf0e..0000000
+++ /dev/null
@@ -1,641 +0,0 @@
-/* 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.pool.jmx;
-/**
- * @author Filip Hanik
- */
-import java.util.Properties;
-import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import javax.management.MBeanNotificationInfo;
-import javax.management.Notification;
-import javax.management.NotificationBroadcasterSupport;
-import javax.management.NotificationListener;
-
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
-import org.apache.tomcat.jdbc.pool.PoolConfiguration;
-import org.apache.tomcat.jdbc.pool.PoolUtilities;
-import org.apache.tomcat.jdbc.pool.Validator;
-import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorDefinition;
-
-public class ConnectionPool extends NotificationBroadcasterSupport implements ConnectionPoolMBean  {
-    /**
-     * logger
-     */
-    private static final Log log = LogFactory.getLog(ConnectionPool.class);
-
-    /**
-     * the connection pool
-     */
-    protected org.apache.tomcat.jdbc.pool.ConnectionPool pool = null;
-    /**
-     * sequence for JMX notifications
-     */
-    protected AtomicInteger sequence = new AtomicInteger(0);
-    
-    /**
-     * Listeners that are local and interested in our notifications, no need for JMX
-     */
-    protected ConcurrentLinkedQueue<NotificationListener> listeners = new ConcurrentLinkedQueue<NotificationListener>(); 
-
-    public ConnectionPool(org.apache.tomcat.jdbc.pool.ConnectionPool pool) {
-        super();
-        this.pool = pool;
-    }
-
-    public org.apache.tomcat.jdbc.pool.ConnectionPool getPool() {
-        return pool;
-    }
-    
-    public PoolConfiguration getPoolProperties() {
-        return pool.getPoolProperties();
-    }
-    
-    //=================================================================
-    //       NOTIFICATION INFO
-    //=================================================================
-    public static final String NOTIFY_INIT = "INIT FAILED";
-    public static final String NOTIFY_CONNECT = "CONNECTION FAILED";
-    public static final String NOTIFY_ABANDON = "CONNECTION ABANDONED";
-    public static final String SLOW_QUERY_NOTIFICATION = "SLOW QUERY";
-    public static final String FAILED_QUERY_NOTIFICATION = "FAILED QUERY";
-    public static final String SUSPECT_ABANDONED_NOTIFICATION = "SUSPECT CONNETION ABANDONED";
-
-    @Override
-    public MBeanNotificationInfo[] getNotificationInfo() { 
-        MBeanNotificationInfo[] pres = super.getNotificationInfo();
-        MBeanNotificationInfo[] loc = getDefaultNotificationInfo();
-        MBeanNotificationInfo[] aug = new MBeanNotificationInfo[pres.length + loc.length];
-        if (pres.length>0) System.arraycopy(pres, 0, aug, 0, pres.length);
-        if (loc.length >0) System.arraycopy(loc, 0, aug, pres.length, loc.length);    
-        return aug; 
-    } 
-    
-    public static MBeanNotificationInfo[] getDefaultNotificationInfo() {
-        String[] types = new String[] {NOTIFY_INIT, NOTIFY_CONNECT, NOTIFY_ABANDON, SLOW_QUERY_NOTIFICATION, FAILED_QUERY_NOTIFICATION, SUSPECT_ABANDONED_NOTIFICATION}; 
-        String name = Notification.class.getName(); 
-        String description = "A connection pool error condition was met."; 
-        MBeanNotificationInfo info = new MBeanNotificationInfo(types, name, description); 
-        return new MBeanNotificationInfo[] {info};
-    }
-    
-    /**
-     * Return true if the notification was sent successfully, false otherwise.
-     * @param type
-     * @param message
-     * @return true if the notification succeeded
-     */
-    public boolean notify(final String type, String message) {
-        try {
-            Notification n = new Notification(
-                    type,
-                    this,
-                    sequence.incrementAndGet(),
-                    System.currentTimeMillis(),
-                    "["+type+"] "+message);
-            sendNotification(n);
-            for (NotificationListener listener : listeners) {
-                listener.handleNotification(n,this);
-            }
-            return true;
-        }catch (Exception x) {
-            if (log.isDebugEnabled()) {
-                log.debug("Notify failed. Type="+type+"; Message="+message,x);
-            }
-            return false;
-        }
-        
-    }
-    
-    public void addListener(NotificationListener list) {
-        listeners.add(list);
-    }
-    
-    public boolean removeListener(NotificationListener list) {
-        return listeners.remove(list);
-    }
-    
-    //=================================================================
-    //       POOL STATS
-    //=================================================================
-
-    public int getSize() {
-        return pool.getSize();
-    }
-
-    public int getIdle() {
-        return pool.getIdle();
-    }
-
-    public int getActive() {
-        return pool.getActive();
-    }
-    
-    public int getNumIdle() {
-        return getIdle();
-    }
-    
-    public int getNumActive() {
-        return getActive();
-    }
-    
-    public int getWaitCount() {
-        return pool.getWaitCount();
-    }
-
-    //=================================================================
-    //       POOL OPERATIONS
-    //=================================================================
-    public void checkIdle() {
-        pool.checkIdle();
-    }
-
-    public void checkAbandoned() {
-        pool.checkAbandoned();
-    }
-
-    public void testIdle() {
-        pool.testAllIdle();
-    }
-    //=================================================================
-    //       POOL PROPERTIES
-    //=================================================================
-    //=========================================================
-    //  PROPERTIES / CONFIGURATION
-    //=========================================================    
-
-
-    public String getConnectionProperties() {
-        return getPoolProperties().getConnectionProperties();
-    }
-
-    public Properties getDbProperties() {
-        return PoolUtilities.cloneWithoutPassword(getPoolProperties().getDbProperties());
-    }
-
-    public String getDefaultCatalog() {
-        return getPoolProperties().getDefaultCatalog();
-    }
-
-    public int getDefaultTransactionIsolation() {
-        return getPoolProperties().getDefaultTransactionIsolation();
-    }
-
-    public String getDriverClassName() {
-        return getPoolProperties().getDriverClassName();
-    }
-
-
-    public int getInitialSize() {
-        return getPoolProperties().getInitialSize();
-    }
-
-    public String getInitSQL() {
-        return getPoolProperties().getInitSQL();
-    }
-
-    public String getJdbcInterceptors() {
-        return getPoolProperties().getJdbcInterceptors();
-    }
-
-    public int getMaxActive() {
-        return getPoolProperties().getMaxActive();
-    }
-
-    public int getMaxIdle() {
-        return getPoolProperties().getMaxIdle();
-    }
-
-    public int getMaxWait() {
-        return getPoolProperties().getMaxWait();
-    }
-
-    public int getMinEvictableIdleTimeMillis() {
-        return getPoolProperties().getMinEvictableIdleTimeMillis();
-    }
-
-    public int getMinIdle() {
-        return getPoolProperties().getMinIdle();
-    }
-    
-    public long getMaxAge() {
-        return getPoolProperties().getMaxAge();
-    }    
-
-    public String getName() {
-        return this.getPoolName();
-    }
-
-    public int getNumTestsPerEvictionRun() {
-        return getPoolProperties().getNumTestsPerEvictionRun();
-    }
-
-    /**
-     * @return DOES NOT RETURN THE PASSWORD, IT WOULD SHOW UP IN JMX
-     */
-    public String getPassword() {
-        return "Password not available as DataSource/JMX operation.";
-    }
-
-    public int getRemoveAbandonedTimeout() {
-        return getPoolProperties().getRemoveAbandonedTimeout();
-    }
-
-
-    public int getTimeBetweenEvictionRunsMillis() {
-        return getPoolProperties().getTimeBetweenEvictionRunsMillis();
-    }
-
-    public String getUrl() {
-        return getPoolProperties().getUrl();
-    }
-
-    public String getUsername() {
-        return getPoolProperties().getUsername();
-    }
-
-    public long getValidationInterval() {
-        return getPoolProperties().getValidationInterval();
-    }
-
-    public String getValidationQuery() {
-        return getPoolProperties().getValidationQuery();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    
-    public String getValidatorClassName() {
-        return getPoolProperties().getValidatorClassName();
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    
-    public Validator getValidator() {
-        return getPoolProperties().getValidator();
-    }
-
-    public boolean isAccessToUnderlyingConnectionAllowed() {
-        return getPoolProperties().isAccessToUnderlyingConnectionAllowed();
-    }
-
-    public Boolean isDefaultAutoCommit() {
-        return getPoolProperties().isDefaultAutoCommit();
-    }
-
-    public Boolean isDefaultReadOnly() {
-        return getPoolProperties().isDefaultReadOnly();
-    }
-
-    public boolean isLogAbandoned() {
-        return getPoolProperties().isLogAbandoned();
-    }
-
-    public boolean isPoolSweeperEnabled() {
-        return getPoolProperties().isPoolSweeperEnabled();
-    }
-
-    public boolean isRemoveAbandoned() {
-        return getPoolProperties().isRemoveAbandoned();
-    }
-
-    public int getAbandonWhenPercentageFull() {
-        return getPoolProperties().getAbandonWhenPercentageFull();
-    }
-
-    public boolean isTestOnBorrow() {
-        return getPoolProperties().isTestOnBorrow();
-    }
-
-    public boolean isTestOnConnect() {
-        return getPoolProperties().isTestOnConnect();
-    }
-
-    public boolean isTestOnReturn() {
-        return getPoolProperties().isTestOnReturn();
-    }
-
-    public boolean isTestWhileIdle() {
-        return getPoolProperties().isTestWhileIdle();
-    }
-
-
-    public Boolean getDefaultAutoCommit() {
-        return getPoolProperties().getDefaultAutoCommit();
-    }
-
-    public Boolean getDefaultReadOnly() {
-        return getPoolProperties().getDefaultReadOnly();
-    }
-
-    public InterceptorDefinition[] getJdbcInterceptorsAsArray() {
-        return getPoolProperties().getJdbcInterceptorsAsArray();
-    }
-
-    public boolean getUseLock() {
-        return getPoolProperties().getUseLock();
-    }
-
-    public boolean isFairQueue() {
-        return getPoolProperties().isFairQueue();
-    }
-
-    public boolean isJmxEnabled() {
-        return getPoolProperties().isJmxEnabled();
-    }
-
-    public boolean isUseEquals() {
-        return getPoolProperties().isUseEquals();
-    }
-
-    public void setAbandonWhenPercentageFull(int percentage) {
-        getPoolProperties().setAbandonWhenPercentageFull(percentage);
-    }
-
-    public void setAccessToUnderlyingConnectionAllowed(boolean accessToUnderlyingConnectionAllowed) {
-        getPoolProperties().setAccessToUnderlyingConnectionAllowed(accessToUnderlyingConnectionAllowed);
-    }
-
-    public void setDbProperties(Properties dbProperties) {
-        getPoolProperties().setDbProperties(dbProperties);
-    }
-
-    public void setDefaultReadOnly(Boolean defaultReadOnly) {
-        getPoolProperties().setDefaultReadOnly(defaultReadOnly);
-    }
-
-    public void setMaxAge(long maxAge) {
-        getPoolProperties().setMaxAge(maxAge);
-    }
-
-    public void setName(String name) {
-        getPoolProperties().setName(name);
-    }
-
-    public String getPoolName() {
-        return getPoolProperties().getName();
-    }
-    
-
-    public void setConnectionProperties(String connectionProperties) {
-        getPoolProperties().setConnectionProperties(connectionProperties);
-        
-    }
-
-    public void setDefaultAutoCommit(Boolean defaultAutoCommit) {
-        getPoolProperties().setDefaultAutoCommit(defaultAutoCommit);
-    }
-
-    public void setDefaultCatalog(String defaultCatalog) {
-        getPoolProperties().setDefaultCatalog(defaultCatalog);
-    }
-
-    public void setDefaultTransactionIsolation(int defaultTransactionIsolation) {
-        getPoolProperties().setDefaultTransactionIsolation(defaultTransactionIsolation);
-    }
-
-    public void setDriverClassName(String driverClassName) {
-        getPoolProperties().setDriverClassName(driverClassName);
-    }
-    
-    
-    public void setFairQueue(boolean fairQueue) {
-        getPoolProperties().setFairQueue(fairQueue);
-    }
-
-    
-    public void setInitialSize(int initialSize) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    
-    public void setInitSQL(String initSQL) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    
-    public void setJdbcInterceptors(String jdbcInterceptors) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    
-    public void setJmxEnabled(boolean jmxEnabled) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    
-    public void setLogAbandoned(boolean logAbandoned) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    
-    public void setMaxActive(int maxActive) {
-        // TODO Auto-generated method stub
-        
-    }
-
-     
-    public void setMaxIdle(int maxIdle) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    
-    public void setMaxWait(int maxWait) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    
-    public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    
-    public void setMinIdle(int minIdle) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    
-    public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    
-    public void setPassword(String password) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    
-    public void setRemoveAbandoned(boolean removeAbandoned) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    
-    public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    
-    public void setTestOnBorrow(boolean testOnBorrow) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    
-    public void setTestOnConnect(boolean testOnConnect) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    
-    public void setTestOnReturn(boolean testOnReturn) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    
-    public void setTestWhileIdle(boolean testWhileIdle) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    
-    public void setTimeBetweenEvictionRunsMillis(int timeBetweenEvictionRunsMillis) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    
-    public void setUrl(String url) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    
-    public void setUseEquals(boolean useEquals) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    
-    public void setUseLock(boolean useLock) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    
-    public void setUsername(String username) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    
-    public void setValidationInterval(long validationInterval) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    
-    public void setValidationQuery(String validationQuery) {
-        // TODO Auto-generated method stub
-        
-    }
-    
-    /**
-     * {@inheritDoc}
-     */
-    
-    public void setValidatorClassName(String className) {
-        getPoolProperties().setValidatorClassName(className);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    
-    public int getSuspectTimeout() {
-        return getPoolProperties().getSuspectTimeout(); 
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    
-    public void setSuspectTimeout(int seconds) {
-        //no op
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    public void setDataSource(Object ds) {
-        getPoolProperties().setDataSource(ds);
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    public Object getDataSource() {
-        return getPoolProperties().getDataSource();
-    }
-
-
-    /** 
-     * {@inheritDoc}
-     */
-    public void setDataSourceJNDI(String jndiDS) {
-        //noop
-    }
-
-    /** 
-     * {@inheritDoc}
-     */
-    public String getDataSourceJNDI() {
-        return getPoolProperties().getDataSourceJNDI();
-    }
-    
-    /** 
-     * {@inheritDoc}
-     */
-    public boolean isAlternateUsernameAllowed() {
-        return getPoolProperties().isAlternateUsernameAllowed();
-    }
-    
-    /** 
-     * {@inheritDoc}
-     */
-    public void setAlternateUsernameAllowed(boolean alternateUsernameAllowed) {
-        //noop
-    }
-
-}
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPoolMBean.java b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPoolMBean.java
deleted file mode 100644 (file)
index 7632d37..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/* 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.pool.jmx;
-
-import org.apache.tomcat.jdbc.pool.PoolConfiguration;
-
-public interface ConnectionPoolMBean extends PoolConfiguration  {
-
-    //=================================================================
-    //       POOL STATS
-    //=================================================================
-
-    public int getSize();
-
-    public int getIdle();
-
-    public int getActive();
-    
-    public boolean isPoolSweeperEnabled();
-    
-    public int getNumIdle();
-    
-    public int getNumActive();
-    
-    public int getWaitCount();
-    
-    //=================================================================
-    //       POOL OPERATIONS
-    //=================================================================
-    public void checkIdle();
-
-    public void checkAbandoned();
-
-    public void testIdle();
-
-    //=================================================================
-    //       POOL NOTIFICATIONS
-    //=================================================================
-
-    
-}
diff --git a/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/mbeans-descriptors.xml b/modules/jdbc-pool/java/org/apache/tomcat/jdbc/pool/mbeans-descriptors.xml
deleted file mode 100644 (file)
index 897782b..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-<?xml version="1.0"?>
-<!--
-  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.
--->
-<mbeans-descriptors>
-
-    <mbean        name="TomcatJDBCPool"
-           description="Provides per diagnostic metrics and notifications for JDBC operations"
-                domain="tomcat"
-                 group="jdbc"
-                  type="org.apache.tomcat.jdbc.pool.DataSource">
-
-    <attribute    name="className"
-           description="Fully qualified class name of the managed object"
-                  type="java.lang.String"
-             writeable="false"/>
-             
-    <attribute    name="size"
-           description="The number of established connections in the pool, idle and in use"
-                  type="java.lang.Integer"
-             writeable="false"/>
-
-    <attribute    name="idle"
-           description="The number of established connections in the pool that are idle"
-                  type="java.lang.Integer"
-             writeable="false"/>
-
-    <attribute    name="numIdle"
-           description="Same as the idle attribute"
-                  type="java.lang.Integer"
-             writeable="false"/>
-
-    <attribute    name="active"
-           description="The number of established connections in the pool that are in use"
-                  type="java.lang.Integer"
-             writeable="false"/>
-    
-    <attribute    name="numActive"
-           description="Same as the active attribute"
-                  type="java.lang.Integer"
-             writeable="false"/>
-
-    <attribute    name="poolSweeperEnabled"
-           description="Returns true if the pool has a background thread running"
-                  type="java.lang.Boolean"
-                    is="true"
-             writeable="false"/>
-
-    <attribute    name="url"
-           description="The JDBC url for this connection pool"
-                  type="java.lang.String"
-             writeable="false"/>
-
-    <attribute    name="driverClassName"
-           description="The JDBC driver class for this connection pool"
-                  type="java.lang.String"
-             writeable="false"/>
-
-    <attribute    name="defaultAutoCommit"
-           description="The JDBC auto commit setting for new connections"
-                  type="java.lang.Boolean"
-                    is="true"
-             writeable="false"/>
-
-    <attribute    name="defaultReadOnly"
-           description="The JDBC read only setting for new connections"
-                  type="java.lang.Boolean"
-                    is="true"
-             writeable="false"/>
-
-    <attribute    name="defaultTransactionIsolation"
-           description="The JDBC transaction isolation setting for new connections"
-                  type="java.lang.Integer"
-             writeable="false"/>
-
-    <attribute    name="connectionProperties"
-           description="The connection properties that will be set for new connections. Format of the string will be [propertyName=property;]*"
-                  type="java.lang.String"
-             writeable="false"/>
-
-    <attribute    name="defaultCatalog"
-           description="The JDBC transaction isolation setting for new connections"
-                  type="java.lang.String"
-             writeable="false"/>
-
-    <attribute    name="initialSize"
-           description="The number of connections opened at pool startup"
-                  type="java.lang.Integer"
-             writeable="false"/>
-
-    <attribute    name="maxActive"
-           description="The maximum number of open connections"
-                  type="java.lang.Integer"
-             writeable="false"/>
-
-    <attribute    name="maxIdle"
-           description="The max number of idle connections"
-                  type="java.lang.Integer"
-             writeable="false"/>
-    
-    <attribute    name="minIdle"
-           description="The minimum number of open connections"
-                  type="java.lang.Integer"
-             writeable="false"/>
-    
-    <attribute    name="maxWait"
-           description="The time to wait in milliseconds before a SQLException is thrown when a connection is requested"
-                  type="java.lang.Integer"
-             writeable="false"/>
-
-    <attribute    name="validationQuery"
-           description="The query to run during validation"
-                  type="java.lang.String"
-             writeable="false"/>
-
-    <attribute    name="testOnBorrow"
-           description="True if validation happens when a connection is requested"
-                  type="java.lang.Boolean"
-                    is="true"
-             writeable="false"/>
-
-    <attribute    name="testOnReturn"
-           description="True if validation happens when a connection is returned"
-                  type="java.lang.Boolean"
-                    is="true"
-             writeable="false"/>
-
-    <attribute    name="testWhileIdle"
-           description="True if validation happens when a connection is not in use (idle)"
-                  type="java.lang.Boolean"
-                    is="true"
-             writeable="false"/>
-
-    <attribute    name="timeBetweenEvictionRunsMillis"
-           description="Sleep time for background thread in between pool checks"
-                  type="java.lang.Integer"
-             writeable="false"/>
-
-    <attribute    name="numTestsPerEvictionRun"
-           description="Not in use"
-                  type="java.lang.Integer"
-             writeable="false"/>
-
-    <attribute    name="minEvictableIdleTimeMillis"
-           description="Minimum amount of time a connection stays idle before it is evicted"
-                  type="java.lang.Integer"
-             writeable="false"/>
-
-    <attribute    name="accessToUnderlyingConnectionAllowed"
-           description="Returns true if one can retrieve the actual JDBC connection"
-                  type="java.lang.Boolean"
-                    is="true"
-             writeable="false"/>
-
-    <attribute    name="removeAbandoned"
-           description="Returns true if connection in use can be timed out"
-                  type="java.lang.Boolean"
-                    is="true"
-             writeable="false"/>
-
-    <attribute    name="removeAbandonedTimeout"
-           description="Timeout in seconds for connections in use"
-                  type="java.lang.Integer"
-             writeable="false"/>
-
-    <attribute    name="logAbandoned"
-           description="If true, stack trace will be recorded and printed out for timed out connection"
-                  type="java.lang.Boolean"
-                    is="true"
-             writeable="false"/>
-
-    <attribute    name="loginTimeout"
-           description="Not in use"
-                  type="java.lang.Integer"
-             writeable="false"/>
-
-
-    <attribute    name="name"
-           description="The name of the connection pool, will be used in the ObjectName of the actual pool"
-                  type="java.lang.String"
-             writeable="false"/>
-    
-    <attribute    name="password"
-           description="For security purposes,this doesn't return anything"
-                  type="java.lang.String"
-             writeable="false"/>
-    
-    <attribute    name="username"
-           description="The username used to open connections"
-                  type="java.lang.String"
-             writeable="false"/>
-
-    <attribute    name="validationInterval"
-           description="If larger than zero than validation will only occur after the interval milliseconds has passed"
-                  type="java.lang.Long"
-             writeable="false"/>
-
-    <attribute    name="initSQL"
-           description="A SQL executed once per connection, when it is established"
-                  type="java.lang.String"
-             writeable="false"/>
-
-    <attribute    name="testOnConnect"
-           description="Validate connection after connection has been established"
-                  type="java.lang.Boolean"
-                    is="true"
-             writeable="false"/>
-
-    <attribute    name="jdbcInterceptors"
-           description="The interceptors configured for this pool"
-                  type="java.lang.String"
-             writeable="false"/>
-
-    <operation    name="checkIdle" 
-                  description="forces a check of idle connections" 
-                  impact="ACTION" 
-                  returnType="void" />
-                  
-    <operation    name="checkAbandoned" 
-                  description="forces a check of abandoned connections" 
-                  impact="ACTION" 
-                  returnType="void" />
-    
-    <operation    name="testIdle" 
-                  description="forces a validation of abandoned connections" 
-                  impact="ACTION" 
-                  returnType="void" />
-  </mbean>
-
-</mbeans-descriptors>
diff --git a/modules/jdbc-pool/pom.xml b/modules/jdbc-pool/pom.xml
new file mode 100644 (file)
index 0000000..1cc2889
--- /dev/null
@@ -0,0 +1,110 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
+  <modelVersion>4.0.0</modelVersion>\r
+  <groupId>org.apache.tomcat</groupId>\r
+  <artifactId>jdbc-pool</artifactId>\r
+  <version>1.2-SNAPSHOT</version>\r
+  <packaging>jar</packaging>\r
+\r
+  <name>jdbc-pool</name>\r
+  <url>http://people.apache.org/~fhanik/jdbc-pool/</url>\r
+  \r
+  <properties>\r
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\r
+  </properties>\r
+  \r
+  <mailingLists>\r
+    <mailingList>\r
+      <name>Development List</name>\r
+      <subscribe>dev-subscribe@tomcat.apache.org</subscribe>\r
+      <unsubscribe>dev-unsubscribe@tomcat.apache.org</unsubscribe>\r
+      <post>dev@tomcat.apache.org</post>\r
+    </mailingList>\r
+    <mailingList>\r
+      <name>Users List</name>\r
+      <subscribe>users-subscribe@tomcat.apache.org</subscribe>\r
+      <unsubscribe>users-unsubscribe@tomcat.apache.org</unsubscribe>\r
+      <post>users@tomcat.apache.org</post>\r
+    </mailingList>\r
+  </mailingLists>\r
+  \r
+  <distributionManagement>\r
+    <snapshotRepository>\r
+      <id>apache.snapshots.https</id>\r
+      <name>Apache Development Snapshot Repository</name>\r
+      <url>https://repository.apache.org/content/repositories/snapshots</url>\r
+      <uniqueVersion>false</uniqueVersion>\r
+    </snapshotRepository>\r
+  </distributionManagement>  \r
+\r
+  <scm>\r
+    <connection>scm:svn:https://svn.apache.org/repos/asf/tomcat/trunk/modules/jdbc-pool</connection>\r
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/tomcat/trunk/modules/jdbc-pool</developerConnection>\r
+    <url>http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool</url>\r
+  </scm>  \r
+\r
+  <dependencies>\r
+    <dependency>\r
+      <groupId>org.apache.tomcat</groupId>\r
+      <artifactId>juli</artifactId>\r
+      <version>6.0.32</version>\r
+    </dependency>\r
+    <dependency>\r
+      <groupId>junit</groupId>\r
+      <artifactId>junit</artifactId>\r
+      <version>3.8.1</version>\r
+      <scope>test</scope>\r
+    </dependency>\r
+    <dependency>\r
+      <groupId>org.apache.tomcat</groupId>\r
+      <artifactId>dbcp</artifactId>\r
+      <version>6.0.32</version>\r
+      <scope>test</scope>\r
+    </dependency>\r
+    <dependency>\r
+      <groupId>com.h2database</groupId>\r
+      <artifactId>h2</artifactId>\r
+      <version>1.3.152</version>\r
+      <scope>test</scope>\r
+    </dependency>\r
+  </dependencies>\r
+  <build>\r
+    <plugins>\r
+      <plugin>\r
+        <groupId>org.apache.maven.plugins</groupId>\r
+        <artifactId>maven-compiler-plugin</artifactId>\r
+        <configuration>\r
+          <source>1.6</source>\r
+          <target>1.6</target>\r
+          <optimize>true</optimize>\r
+          <debug>true</debug>\r
+          <showDeprecation>true</showDeprecation>\r
+          <showWarnings>true</showWarnings>\r
+        </configuration>\r
+      </plugin>\r
+      <plugin>\r
+        <groupId>org.apache.maven.plugins</groupId>\r
+        <artifactId>maven-gpg-plugin</artifactId>\r
+        <version>1.2</version>\r
+        <executions>\r
+          <execution>\r
+            <id>sign-artifacts</id>\r
+            <phase>verify</phase>\r
+            <goals>\r
+              <goal>sign</goal>\r
+            </goals>\r
+          </execution>\r
+        </executions>\r
+      </plugin>\r
+      <plugin>\r
+        <groupId>org.apache.maven.plugins</groupId>\r
+        <artifactId>maven-eclipse-plugin</artifactId>\r
+        <version>2.5.1</version>\r
+        <configuration>\r
+          <downloadSources>true</downloadSources>\r
+          <downloadJavadocs>false</downloadJavadocs>\r
+        </configuration>\r
+      </plugin>\r
+    </plugins>    \r
+  </build>  \r
+</project>\r
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java
new file mode 100644 (file)
index 0000000..5fd7007
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * 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.naming;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.RefAddr;
+import javax.naming.Reference;
+import javax.naming.spi.ObjectFactory;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+/**
+ * Simple way of configuring generic resources by using reflection.
+ * Example usage:
+ * <pre><code>
+ * &lt;Resource factory=&quot;org.apache.tomcat.jdbc.naming.GenericNamingResourcesFactory&quot;
+ *              name=&quot;jdbc/test&quot;
+ *              type=&quot;org.apache.derby.jdbc.ClientXADataSource&quot;
+ *              databaseName=&quot;sample&quot;
+ *              createDatabase=&quot;create&quot;
+ *              serverName=&quot;localhost&quot;
+ *              port=&quot;1527&quot;/&gt;
+ * </code></pre>
+ * 
+ */
+public class GenericNamingResourcesFactory implements ObjectFactory {
+    private static final Log log = LogFactory.getLog(GenericNamingResourcesFactory.class);
+    
+    public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
+        if ((obj == null) || !(obj instanceof Reference)) {
+            return null;
+        }
+        Reference ref = (Reference) obj;
+        Enumeration<RefAddr> refs = ref.getAll();
+        
+        String type = ref.getClassName();
+        Object o = Class.forName(type).newInstance();
+        
+        while (refs.hasMoreElements()) {
+            RefAddr addr = refs.nextElement();
+            String param = addr.getType();
+            String value = null;
+            if (addr.getContent()!=null) {
+                value = addr.getContent().toString();
+            }
+            if (setProperty(o, param, value,false)) {
+                
+            } else {
+                log.debug("Property not configured["+param+"]. No setter found on["+o+"].");
+            }
+        }
+        return o;
+    }
+
+    public static boolean setProperty(Object o, String name, String value,boolean invokeSetProperty) {
+        if (log.isDebugEnabled())
+            log.debug("IntrospectionUtils: setProperty(" +
+                    o.getClass() + " " + name + "=" + value + ")");
+
+        String setter = "set" + capitalize(name);
+
+        try {
+            Method methods[] = o.getClass().getMethods();
+            Method setPropertyMethodVoid = null;
+            Method setPropertyMethodBool = null;
+
+            // First, the ideal case - a setFoo( String ) method
+            for (int i = 0; i < methods.length; i++) {
+                Class<?> paramT[] = methods[i].getParameterTypes();
+                if (setter.equals(methods[i].getName()) && paramT.length == 1
+                        && "java.lang.String".equals(paramT[0].getName())) {
+
+                    methods[i].invoke(o, new Object[] { value });
+                    return true;
+                }
+            }
+
+            // Try a setFoo ( int ) or ( boolean )
+            for (int i = 0; i < methods.length; i++) {
+                boolean ok = true;
+                if (setter.equals(methods[i].getName())
+                        && methods[i].getParameterTypes().length == 1) {
+
+                    // match - find the type and invoke it
+                    Class<?> paramType = methods[i].getParameterTypes()[0];
+                    Object params[] = new Object[1];
+
+                    // Try a setFoo ( int )
+                    if ("java.lang.Integer".equals(paramType.getName())
+                            || "int".equals(paramType.getName())) {
+                        try {
+                            params[0] = new Integer(value);
+                        } catch (NumberFormatException ex) {
+                            ok = false;
+                        }
+                    // Try a setFoo ( long )
+                    }else if ("java.lang.Long".equals(paramType.getName())
+                                || "long".equals(paramType.getName())) {
+                            try {
+                                params[0] = new Long(value);
+                            } catch (NumberFormatException ex) {
+                                ok = false;
+                            }
+
+                        // Try a setFoo ( boolean )
+                    } else if ("java.lang.Boolean".equals(paramType.getName())
+                            || "boolean".equals(paramType.getName())) {
+                        params[0] = new Boolean(value);
+
+                        // Try a setFoo ( InetAddress )
+                    } else if ("java.net.InetAddress".equals(paramType
+                            .getName())) {
+                        try {
+                            params[0] = InetAddress.getByName(value);
+                        } catch (UnknownHostException exc) {
+                            if (log.isDebugEnabled())
+                                log.debug("IntrospectionUtils: Unable to resolve host name:" + value);
+                            ok = false;
+                        }
+
+                        // Unknown type
+                    } else {
+                        if (log.isDebugEnabled())
+                            log.debug("IntrospectionUtils: Unknown type " +
+                                    paramType.getName());
+                    }
+
+                    if (ok) {
+                        methods[i].invoke(o, params);
+                        return true;
+                    }
+                }
+
+                // save "setProperty" for later
+                if ("setProperty".equals(methods[i].getName())) {
+                    if (methods[i].getReturnType()==Boolean.TYPE){
+                        setPropertyMethodBool = methods[i];
+                    }else {
+                        setPropertyMethodVoid = methods[i];    
+                    }
+                    
+                }
+            }
+
+            // Ok, no setXXX found, try a setProperty("name", "value")
+            if (setPropertyMethodBool != null || setPropertyMethodVoid != null) {
+                Object params[] = new Object[2];
+                params[0] = name;
+                params[1] = value;
+                if (setPropertyMethodBool != null) {
+                    try {
+                        return (Boolean) setPropertyMethodBool.invoke(o, params);
+                    }catch (IllegalArgumentException biae) {
+                        //the boolean method had the wrong
+                        //parameter types. lets try the other
+                        if (setPropertyMethodVoid!=null) {
+                            setPropertyMethodVoid.invoke(o, params);
+                            return true;
+                        }else {
+                            throw biae;
+                        }
+                    }
+                } else {
+                    setPropertyMethodVoid.invoke(o, params);
+                    return true;
+                }
+            }
+
+        } catch (IllegalArgumentException ex2) {
+            log.warn("IAE " + o + " " + name + " " + value, ex2);
+        } catch (SecurityException ex1) {
+            if (log.isDebugEnabled())
+                log.debug("IntrospectionUtils: SecurityException for " +
+                        o.getClass() + " " + name + "=" + value + ")", ex1);
+        } catch (IllegalAccessException iae) {
+            if (log.isDebugEnabled())
+                log.debug("IntrospectionUtils: IllegalAccessException for " +
+                        o.getClass() + " " + name + "=" + value + ")", iae);
+        } catch (InvocationTargetException ie) {
+            if (log.isDebugEnabled())
+                log.debug("IntrospectionUtils: InvocationTargetException for " +
+                        o.getClass() + " " + name + "=" + value + ")", ie);
+        }
+        return false;
+    } 
+    
+    public static String capitalize(String name) {
+        if (name == null || name.length() == 0) {
+            return name;
+        }
+        char chars[] = name.toCharArray();
+        chars[0] = Character.toUpperCase(chars[0]);
+        return new String(chars);
+    }
+
+}
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ConnectionPool.java
new file mode 100644 (file)
index 0000000..0faccfe
--- /dev/null
@@ -0,0 +1,1201 @@
+/*
+ * 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.pool;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+
+/**
+ * Implementation of simple connection pool.
+ * The ConnectionPool uses a {@link PoolProperties} object for storing all the meta information about the connection pool.
+ * As the underlying implementation, the connection pool uses {@link java.util.concurrent.BlockingQueue} to store active and idle connections.
+ * A custom implementation of a fair {@link FairBlockingQueue} blocking queue is provided with the connection pool itself. 
+ * @author Filip Hanik
+ * @version 1.0
+ */
+
+public class ConnectionPool {
+    /**
+     * Prefix type for JMX registration
+     */
+    public static final String POOL_JMX_TYPE_PREFIX = "tomcat.jdbc:type=";
+    
+    /**
+     * Logger
+     */
+    private static final Log log = LogFactory.getLog(ConnectionPool.class);
+
+    //===============================================================================
+    //         INSTANCE/QUICK ACCESS VARIABLE
+    //===============================================================================
+    /**
+     * Carries the size of the pool, instead of relying on a queue implementation
+     * that usually iterates over to get an exact count
+     */
+    private AtomicInteger size = new AtomicInteger(0);
+
+    /**
+     * All the information about the connection pool
+     * These are the properties the pool got instantiated with
+     */
+    private PoolConfiguration poolProperties;
+
+    /**
+     * Contains all the connections that are in use
+     * TODO - this shouldn't be a blocking queue, simply a list to hold our objects
+     */
+    private BlockingQueue<PooledConnection> busy;
+
+    /**
+     * Contains all the idle connections
+     */
+    private BlockingQueue<PooledConnection> idle;
+
+    /**
+     * The thread that is responsible for checking abandoned and idle threads
+     */
+    private volatile PoolCleaner poolCleaner;
+
+    /**
+     * Pool closed flag
+     */
+    private volatile boolean closed = false;
+
+    /**
+     * Since newProxyInstance performs the same operation, over and over
+     * again, it is much more optimized if we simply store the constructor ourselves.
+     */
+    private Constructor<?> proxyClassConstructor;
+
+    /**
+     * Executor service used to cancel Futures
+     */
+    private ThreadPoolExecutor cancellator = new ThreadPoolExecutor(0,1,1000,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
+    
+    /**
+     * reference to the JMX mbean
+     */
+    protected org.apache.tomcat.jdbc.pool.jmx.ConnectionPool jmxPool = null;
+    
+    /**
+     * counter to track how many threads are waiting for a connection
+     */
+    private AtomicInteger waitcount = new AtomicInteger(0);
+    
+    //===============================================================================
+    //         PUBLIC METHODS
+    //===============================================================================
+
+    /**
+     * Instantiate a connection pool. This will create connections if initialSize is larger than 0.
+     * The {@link PoolProperties} should not be reused for another connection pool.
+     * @param prop PoolProperties - all the properties for this connection pool
+     * @throws SQLException
+     */
+    public ConnectionPool(PoolConfiguration prop) throws SQLException {
+        //setup quick access variables and pools
+        init(prop);
+    }
+
+
+    /**
+     * Retrieves a Connection future. If a connection is not available, one can block using future.get()
+     * until a connection has become available.
+     * If a connection is not retrieved, the Future must be cancelled in order for the connection to be returned
+     * to the pool.
+     * @return a Future containing a reference to the connection or the future connection
+     * @throws SQLException
+     */
+    public Future<Connection> getConnectionAsync() throws SQLException {
+        try {
+            PooledConnection pc = borrowConnection(0, null, null);
+            if (pc!=null) {
+                return new ConnectionFuture(pc);
+            } 
+        }catch (SQLException x) {
+            if (x.getMessage().indexOf("NoWait")<0) {
+                throw x;
+            }
+        }
+        //we can only retrieve a future if the underlying queue supports it.
+        if (idle instanceof FairBlockingQueue<?>) {
+            Future<PooledConnection> pcf = ((FairBlockingQueue<PooledConnection>)idle).pollAsync();
+            return new ConnectionFuture(pcf);
+        } else if (idle instanceof MultiLockFairBlockingQueue<?>) {
+                Future<PooledConnection> pcf = ((MultiLockFairBlockingQueue<PooledConnection>)idle).pollAsync();
+                return new ConnectionFuture(pcf);
+        } else {
+            throw new SQLException("Connection pool is misconfigured, doesn't support async retrieval. Set the 'fair' property to 'true'");
+        }
+    }
+    
+    /**
+     * Borrows a connection from the pool. If a connection is available (in the idle queue) or the pool has not reached 
+     * {@link PoolProperties#maxActive maxActive} connections a connection is returned immediately.
+     * If no connection is available, the pool will attempt to fetch a connection for {@link PoolProperties#maxWait maxWait} milliseconds.
+     * @return Connection - a java.sql.Connection/javax.sql.PooledConnection reflection proxy, wrapping the underlying object.
+     * @throws SQLException - if the wait times out or a failure occurs creating a connection
+     */
+    public Connection getConnection() throws SQLException {
+        //check out a connection
+        PooledConnection con = borrowConnection(-1,null,null);
+        return setupConnection(con);
+    }
+
+       
+    /**
+     * Borrows a connection from the pool. If a connection is available (in the
+     * idle queue) or the pool has not reached {@link PoolProperties#maxActive
+     * maxActive} connections a connection is returned immediately. If no
+     * connection is available, the pool will attempt to fetch a connection for
+     * {@link PoolProperties#maxWait maxWait} milliseconds.
+     * 
+     * @return Connection - a java.sql.Connection/javax.sql.PooledConnection
+     *         reflection proxy, wrapping the underlying object.
+     * @throws SQLException
+     *             - if the wait times out or a failure occurs creating a
+     *             connection
+     */
+    public Connection getConnection(String username, String password) throws SQLException {
+        // check out a connection
+        PooledConnection con = borrowConnection(-1, username, password);
+        return setupConnection(con);
+    }
+    
+    /**
+     * Returns the name of this pool
+     * @return String - the name of the pool
+     */
+    public String getName() {
+        return getPoolProperties().getPoolName();
+    }
+    
+    /**
+     * Return the number of threads waiting for a connection
+     * @return number of threads waiting for a connection
+     */
+    public int getWaitCount() {
+        return waitcount.get();
+    }
+
+    /**
+     * Returns the pool properties associated with this connection pool
+     * @return PoolProperties
+     * 
+     */
+    public PoolConfiguration getPoolProperties() {
+        return this.poolProperties;
+    }
+
+    /**
+     * Returns the total size of this pool, this includes both busy and idle connections
+     * @return int - number of established connections to the database
+     */
+    public int getSize() {
+        return size.get();
+    }
+
+    /**
+     * Returns the number of connections that are in use
+     * @return int - number of established connections that are being used by the application
+     */
+    public int getActive() {
+        return busy.size();
+    }
+
+    /**
+     * Returns the number of idle connections
+     * @return int - number of established connections not being used
+     */
+    public int getIdle() {
+        return idle.size();
+    }
+
+    /**
+     * Returns true if {@link #close close} has been called, and the connection pool is unusable
+     * @return boolean
+     */
+    public  boolean isClosed() {
+        return this.closed;
+    }
+
+    //===============================================================================
+    //         PROTECTED METHODS
+    //===============================================================================
+    
+    
+    /**
+     * configures a pooled connection as a proxy.
+     * This Proxy implements {@link java.sql.Connection} and {@link javax.sql.PooledConnection} interfaces.
+     * All calls on {@link java.sql.Connection} methods will be propagated down to the actual JDBC connection except for the 
+     * {@link java.sql.Connection#close()} method.
+     * @param con a {@link PooledConnection} to wrap in a Proxy
+     * @return a {@link java.sql.Connection} object wrapping a pooled connection.
+     * @throws SQLException if an interceptor can't be configured, if the proxy can't be instantiated
+     */
+    protected Connection setupConnection(PooledConnection con) throws SQLException {
+        //fetch previously cached interceptor proxy - one per connection
+        JdbcInterceptor handler = con.getHandler();
+        if (handler==null) {
+            //build the proxy handler
+            handler = new ProxyConnection(this,con,getPoolProperties().isUseEquals());
+            //set up the interceptor chain
+            PoolProperties.InterceptorDefinition[] proxies = getPoolProperties().getJdbcInterceptorsAsArray();
+            for (int i=proxies.length-1; i>=0; i--) {
+                try {
+                    //create a new instance
+                    JdbcInterceptor interceptor = proxies[i].getInterceptorClass().newInstance();
+                    //configure properties
+                    interceptor.setProperties(proxies[i].getProperties());
+                    //setup the chain
+                    interceptor.setNext(handler);
+                    //call reset
+                    interceptor.reset(this, con);
+                    //configure the last one to be held by the connection
+                    handler = interceptor;
+                }catch(Exception x) {
+                    SQLException sx = new SQLException("Unable to instantiate interceptor chain.");
+                    sx.initCause(x);
+                    throw sx;
+                }
+            }
+            //cache handler for the next iteration
+            con.setHandler(handler);
+        } else {
+            JdbcInterceptor next = handler;
+            //we have a cached handler, reset it
+            while (next!=null) {
+                next.reset(this, con);
+                next = next.getNext();
+            }
+        }
+
+        try {
+            getProxyConstructor(con.getXAConnection() != null);
+            //create the proxy
+            //TODO possible optimization, keep track if this connection was returned properly, and don't generate a new facade
+            Connection connection = (Connection)proxyClassConstructor.newInstance(new Object[] { handler });
+            //return the connection
+            return connection;
+        }catch (Exception x) {
+            SQLException s = new SQLException();
+            s.initCause(x);
+            throw s;
+        }
+
+    }
+    
+    /**
+     * Creates and caches a {@link java.lang.reflect.Constructor} used to instantiate the proxy object.
+     * We cache this, since the creation of a constructor is fairly slow. 
+     * @return constructor used to instantiate the wrapper object
+     * @throws NoSuchMethodException
+     */
+    public Constructor<?> getProxyConstructor(boolean xa) throws NoSuchMethodException {
+        //cache the constructor
+        if (proxyClassConstructor == null ) {
+            Class<?> proxyClass = xa ?
+                Proxy.getProxyClass(ConnectionPool.class.getClassLoader(), new Class[] {java.sql.Connection.class,javax.sql.PooledConnection.class, javax.sql.XAConnection.class}) :
+                Proxy.getProxyClass(ConnectionPool.class.getClassLoader(), new Class[] {java.sql.Connection.class,javax.sql.PooledConnection.class});
+            proxyClassConstructor = proxyClass.getConstructor(new Class[] { InvocationHandler.class });
+        }
+        return proxyClassConstructor;
+    }
+
+    /**
+     * Closes the pool and all disconnects all idle connections
+     * Active connections will be closed upon the {@link java.sql.Connection#close close} method is called
+     * on the underlying connection instead of being returned to the pool
+     * @param force - true to even close the active connections
+     */
+    protected void close(boolean force) {
+        //are we already closed
+        if (this.closed) return;
+        //prevent other threads from entering
+        this.closed = true;
+        //stop background thread
+        if (poolCleaner!=null) {
+            poolCleaner.stopRunning();
+        }
+
+        /* release all idle connections */
+        BlockingQueue<PooledConnection> pool = (idle.size()>0)?idle:(force?busy:idle);
+        while (pool.size()>0) {
+            try {
+                //retrieve the next connection
+                PooledConnection con = pool.poll(1000, TimeUnit.MILLISECONDS);
+                //close it and retrieve the next one, if one is available
+                while (con != null) {
+                    //close the connection
+                    if (pool==idle)
+                        release(con);
+                    else
+                        abandon(con);
+                    con = pool.poll(1000, TimeUnit.MILLISECONDS);
+                } //while
+            } catch (InterruptedException ex) {
+                Thread.interrupted();
+            }
+            if (pool.size()==0 && force && pool!=busy) pool = busy;
+        }
+        if (this.getPoolProperties().isJmxEnabled()) this.jmxPool = null;
+        PoolProperties.InterceptorDefinition[] proxies = getPoolProperties().getJdbcInterceptorsAsArray();
+        for (int i=0; i<proxies.length; i++) {
+            try {
+                proxies[i].getInterceptorClass().newInstance().poolClosed(this);
+            }catch (Exception x) {
+                log.debug("Unable to inform interceptor of pool closure.",x);
+            }
+        }
+    } //closePool
+
+
+    /**
+     * Initialize the connection pool - called from the constructor
+     * @param properties PoolProperties - properties used to initialize the pool with
+     * @throws SQLException if initialization fails
+     */
+    protected void init(PoolConfiguration properties) throws SQLException {
+        poolProperties = properties;
+        //make space for 10 extra in case we flow over a bit
+        busy = new ArrayBlockingQueue<PooledConnection>(properties.getMaxActive(),false);
+        //busy = new FairBlockingQueue<PooledConnection>();
+        //make space for 10 extra in case we flow over a bit
+        if (properties.isFairQueue()) {
+            idle = new FairBlockingQueue<PooledConnection>();
+            //idle = new MultiLockFairBlockingQueue<PooledConnection>();
+        } else {
+            idle = new ArrayBlockingQueue<PooledConnection>(properties.getMaxActive(),properties.isFairQueue());
+        }
+
+        //if the evictor thread is supposed to run, start it now
+        if (properties.isPoolSweeperEnabled()) {
+            poolCleaner = new PoolCleaner("[Pool-Cleaner]:" + properties.getName(), this, properties.getTimeBetweenEvictionRunsMillis());
+            poolCleaner.start();
+        } //end if
+
+        //make sure the pool is properly configured
+        if (properties.getMaxActive()<1) {
+            log.warn("maxActive is smaller than 1, setting maxActive to: "+PoolProperties.DEFAULT_MAX_ACTIVE);
+            properties.setMaxActive(PoolProperties.DEFAULT_MAX_ACTIVE);
+        }
+        if (properties.getMaxActive()<properties.getInitialSize()) {
+            log.warn("initialSize is larger than maxActive, setting initialSize to: "+properties.getMaxActive());
+            properties.setInitialSize(properties.getMaxActive());
+        }
+        if (properties.getMinIdle()>properties.getMaxActive()) {
+            log.warn("minIdle is larger than maxActive, setting minIdle to: "+properties.getMaxActive());
+            properties.setMinIdle(properties.getMaxActive());
+        }
+        if (properties.getMaxIdle()>properties.getMaxActive()) {
+            log.warn("maxIdle is larger than maxActive, setting maxIdle to: "+properties.getMaxActive());
+            properties.setMaxIdle(properties.getMaxActive());
+        }
+        if (properties.getMaxIdle()<properties.getMinIdle()) {
+            log.warn("maxIdle is smaller than minIdle, setting maxIdle to: "+properties.getMinIdle());
+            properties.setMaxIdle(properties.getMinIdle());
+        }
+        
+        //create JMX MBean
+        if (this.getPoolProperties().isJmxEnabled()) createMBean();
+        
+        //Parse and create an initial set of interceptors. Letting them know the pool has started.
+        //These interceptors will not get any connection.
+        PoolProperties.InterceptorDefinition[] proxies = getPoolProperties().getJdbcInterceptorsAsArray();
+        for (int i=0; i<proxies.length; i++) {
+            try {
+                if (log.isDebugEnabled()) {
+                    log.debug("Creating interceptor instance of class:"+proxies[i].getInterceptorClass());
+                }
+                proxies[i].getInterceptorClass().newInstance().poolStarted(this);
+            }catch (Exception x) {
+                log.error("Unable to inform interceptor of pool start.",x);
+                if (jmxPool!=null) jmxPool.notify(org.apache.tomcat.jdbc.pool.jmx.ConnectionPool.NOTIFY_INIT, getStackTrace(x));
+                close(true);
+                SQLException ex = new SQLException();
+                ex.initCause(x);
+                throw ex;
+            }
+        }
+        
+        //initialize the pool with its initial set of members
+        PooledConnection[] initialPool = new PooledConnection[poolProperties.getInitialSize()];
+        try {
+            for (int i = 0; i < initialPool.length; i++) {
+                initialPool[i] = this.borrowConnection(0, null, null); //don't wait, should be no contention
+            } //for
+
+        } catch (SQLException x) {
+            if (jmxPool!=null) jmxPool.notify(org.apache.tomcat.jdbc.pool.jmx.ConnectionPool.NOTIFY_INIT, getStackTrace(x));
+            close(true);
+            throw x;
+        } finally {
+            //return the members as idle to the pool
+            for (int i = 0; i < initialPool.length; i++) {
+                if (initialPool[i] != null) {
+                    try {this.returnConnection(initialPool[i]);}catch(Exception x){/*NOOP*/}
+                } //end if
+            } //for
+        } //catch
+        
+        closed = false;
+    }
+
+
+//===============================================================================
+//         CONNECTION POOLING IMPL LOGIC
+//===============================================================================
+
+    /**
+     * thread safe way to abandon a connection
+     * signals a connection to be abandoned.
+     * this will disconnect the connection, and log the stack trace if logAbanded=true
+     * @param con PooledConnection
+     */
+    protected void abandon(PooledConnection con) {
+        if (con == null)
+            return;
+        try {
+            con.lock();
+            String trace = con.getStackTrace();
+            if (getPoolProperties().isLogAbandoned()) {
+                log.warn("Connection has been abandoned " + con + ":" + trace);
+            }
+            if (jmxPool!=null) {
+                jmxPool.notify(org.apache.tomcat.jdbc.pool.jmx.ConnectionPool.NOTIFY_ABANDON, trace);
+            }
+            //release the connection
+            release(con);
+        } finally {
+            con.unlock();
+        }
+    }
+    
+    /**
+     * thread safe way to abandon a connection
+     * signals a connection to be abandoned.
+     * this will disconnect the connection, and log the stack trace if logAbanded=true
+     * @param con PooledConnection
+     */
+    protected void suspect(PooledConnection con) {
+        if (con == null)
+            return;
+        if (con.isSuspect())
+            return;
+        try {
+            con.lock();
+            String trace = con.getStackTrace();
+            if (getPoolProperties().isLogAbandoned()) {
+                log.warn("Connection has been marked suspect, possibly abandoned " + con + "["+(System.currentTimeMillis()-con.getTimestamp())+" ms.]:" + trace);
+            }
+            if (jmxPool!=null) {
+                jmxPool.notify(org.apache.tomcat.jdbc.pool.jmx.ConnectionPool.SUSPECT_ABANDONED_NOTIFICATION, trace);
+            }
+            con.setSuspect(true);
+        } finally {
+            con.unlock();
+        }
+    }
+
+    /**
+     * thread safe way to release a connection
+     * @param con PooledConnection
+     */
+    protected void release(PooledConnection con) {
+        if (con == null)
+            return;
+        try {
+            con.lock();
+            if (con.release()) {
+                //counter only decremented once
+                size.addAndGet(-1);
+                con.setHandler(null);
+            }
+        } finally {
+            con.unlock();
+        }
+        // we've asynchronously reduced the number of connections
+        // we could have threads stuck in idle.poll(timeout) that will never be
+        // notified
+        if (waitcount.get() > 0) {
+            idle.offer(create(true));
+        }
+    }
+
+    /**
+     * Thread safe way to retrieve a connection from the pool
+     * @param wait - time to wait, overrides the maxWait from the properties, 
+     * set to -1 if you wish to use maxWait, 0 if you wish no wait time. 
+     * @return PooledConnection
+     * @throws SQLException
+     */
+    private PooledConnection borrowConnection(int wait, String username, String password) throws SQLException {
+
+        if (isClosed()) {
+            throw new SQLException("Connection pool closed.");
+        } //end if
+
+        //get the current time stamp
+        long now = System.currentTimeMillis();
+        //see if there is one available immediately
+        PooledConnection con = idle.poll();
+
+        while (true) {
+            if (con!=null) {
+                //configure the connection and return it
+                PooledConnection result = borrowConnection(now, con, username, password);
+                //null should never be returned, but was in a previous impl.
+                if (result!=null) return result;
+            }
+            
+            //if we get here, see if we need to create one
+            //this is not 100% accurate since it doesn't use a shared
+            //atomic variable - a connection can become idle while we are creating 
+            //a new connection
+            if (size.get() < getPoolProperties().getMaxActive()) {
+                //atomic duplicate check
+                if (size.addAndGet(1) > getPoolProperties().getMaxActive()) {
+                    //if we got here, two threads passed through the first if
+                    size.decrementAndGet();
+                } else {
+                    //create a connection, we're below the limit
+                    return createConnection(now, con, username, password);
+                }
+            } //end if
+
+            //calculate wait time for this iteration
+            long maxWait = wait;
+            //if the passed in wait time is -1, means we should use the pool property value
+            if (wait==-1) {
+                maxWait = (getPoolProperties().getMaxWait()<=0)?Long.MAX_VALUE:getPoolProperties().getMaxWait();
+            }
+            
+            long timetowait = Math.max(0, maxWait - (System.currentTimeMillis() - now));
+            waitcount.incrementAndGet();
+            try {
+                //retrieve an existing connection
+                con = idle.poll(timetowait, TimeUnit.MILLISECONDS);
+            } catch (InterruptedException ex) {
+                Thread.interrupted();//clear the flag, and bail out
+                SQLException sx = new SQLException("Pool wait interrupted.");
+                sx.initCause(ex);
+                throw sx;
+            } finally {
+                waitcount.decrementAndGet();
+            }
+            if (maxWait==0 && con == null) { //no wait, return one if we have one
+                throw new SQLException("[" + Thread.currentThread().getName()+"] " +
+                        "NoWait: Pool empty. Unable to fetch a connection, none available["+busy.size()+" in use].");
+            }
+            //we didn't get a connection, lets see if we timed out
+            if (con == null) {
+                if ((System.currentTimeMillis() - now) >= maxWait) {
+                    throw new SQLException("[" + Thread.currentThread().getName()+"] " +
+                        "Timeout: Pool empty. Unable to fetch a connection in " + (maxWait / 1000) +
+                        " seconds, none available["+busy.size()+" in use].");
+                } else {
+                    //no timeout, lets try again
+                    continue;
+                }
+            }
+        } //while
+    }
+
+    /**
+     * Creates a JDBC connection and tries to connect to the database.
+     * @param now timestamp of when this was called
+     * @param notUsed Argument not used
+     * @return a PooledConnection that has been connected
+     * @throws SQLException
+     */
+    protected PooledConnection createConnection(long now, PooledConnection notUsed, String username, String password) throws SQLException {
+        //no connections where available we'll create one
+        PooledConnection con = create(false);
+        if (username!=null) con.getAttributes().put(con.PROP_USER, username);
+        if (password!=null) con.getAttributes().put(con.PROP_PASSWORD, password);
+        boolean error = false;
+        try {
+            //connect and validate the connection
+            con.lock();
+            con.connect();
+            if (con.validate(PooledConnection.VALIDATE_INIT)) {
+                //no need to lock a new one, its not contented
+                con.setTimestamp(now);
+                if (getPoolProperties().isLogAbandoned()) {
+                    con.setStackTrace(getThreadDump());
+                }
+                if (!busy.offer(con)) {
+                    log.debug("Connection doesn't fit into busy array, connection will not be traceable.");
+                }
+                return con;
+            } else {
+                //validation failed, make sure we disconnect
+                //and clean up
+                error =true;
+            } //end if
+        } catch (Exception e) {
+            error = true;
+            if (log.isDebugEnabled())
+                log.debug("Unable to create a new JDBC connection.", e);
+            if (e instanceof SQLException) {
+                throw (SQLException)e;
+            } else {
+                SQLException ex = new SQLException(e.getMessage());
+                ex.initCause(e);
+                throw ex;
+            }
+        } finally {
+            // con can never be null here
+            if (error ) {
+                release(con);
+            }
+            con.unlock();
+        }//catch
+        return null;
+    }
+
+    /**
+     * Validates and configures a previously idle connection
+     * @param now - timestamp  
+     * @param con - the connection to validate and configure
+     * @return con
+     * @throws SQLException if a validation error happens
+     */
+    protected PooledConnection borrowConnection(long now, PooledConnection con, String username, String password) throws SQLException {
+        //we have a connection, lets set it up
+        
+        //flag to see if we need to nullify
+        boolean setToNull = false;
+        try {
+            con.lock();
+            boolean usercheck = con.checkUser(username, password);
+            
+            if (con.isReleased()) {
+                return null;
+            }
+            
+            if (!con.isDiscarded() && !con.isInitialized()) {
+                //attempt to connect
+                con.connect();
+            }
+            
+            if (usercheck) {
+                if ((!con.isDiscarded()) && con.validate(PooledConnection.VALIDATE_BORROW)) {
+                    //set the timestamp
+                    con.setTimestamp(now);
+                    if (getPoolProperties().isLogAbandoned()) {
+                        //set the stack trace for this pool
+                        con.setStackTrace(getThreadDump());
+                    }
+                    if (!busy.offer(con)) {
+                        log.debug("Connection doesn't fit into busy array, connection will not be traceable.");
+                    }
+                    return con;
+                }
+            }
+            //if we reached here, that means the connection
+            //is either has another principal, is discarded or validation failed.
+            //we will make one more attempt
+            //in order to guarantee that the thread that just acquired
+            //the connection shouldn't have to poll again.
+            try {
+                con.reconnect();
+                if (con.validate(PooledConnection.VALIDATE_INIT)) {
+                    //set the timestamp
+                    con.setTimestamp(now);
+                    if (getPoolProperties().isLogAbandoned()) {
+                        //set the stack trace for this pool
+                        con.setStackTrace(getThreadDump());
+                    }
+                    if (!busy.offer(con)) {
+                        log.debug("Connection doesn't fit into busy array, connection will not be traceable.");
+                    }
+                    return con;
+                } else {
+                    //validation failed.
+                    release(con);
+                    setToNull = true;
+                    throw new SQLException("Failed to validate a newly established connection.");
+                }
+            } catch (Exception x) {
+                release(con);
+                setToNull = true;
+                if (x instanceof SQLException) {
+                    throw (SQLException)x;
+                } else {
+                    SQLException ex  = new SQLException(x.getMessage());
+                    ex.initCause(x);
+                    throw ex;
+                }
+            }
+        } finally {
+            con.unlock();
+            if (setToNull) {
+                con = null;
+            }
+        }
+    }
+
+    /**
+     * Determines if a connection should be closed upon return to the pool.
+     * @param con - the connection
+     * @param action - the validation action that should be performed
+     * @return true if the connection should be closed
+     */
+    protected boolean shouldClose(PooledConnection con, int action) {
+        if (con.isDiscarded()) return true;
+        if (isClosed()) return true;
+        if (!con.validate(action)) return true;
+        if (getPoolProperties().getMaxAge()>0 ) {
+            return (System.currentTimeMillis()-con.getLastConnected()) > getPoolProperties().getMaxAge();
+        } else {
+            return false;
+        }
+    }
+    
+    /**
+     * Returns a connection to the pool
+     * If the pool is closed, the connection will be released
+     * If the connection is not part of the busy queue, it will be released.
+     * If {@link PoolProperties#testOnReturn} is set to true it will be validated
+     * @param con PooledConnection to be returned to the pool
+     */
+    protected void returnConnection(PooledConnection con) {
+        if (isClosed()) {
+            //if the connection pool is closed
+            //close the connection instead of returning it
+            release(con);
+            return;
+        } //end if
+
+        if (con != null) {
+            try {
+                con.lock();
+
+                if (busy.remove(con)) {
+                    
+                    if (!shouldClose(con,PooledConnection.VALIDATE_RETURN)) {
+                        con.setStackTrace(null);
+                        con.setTimestamp(System.currentTimeMillis());
+                        if (((idle.size()>=poolProperties.getMaxIdle()) && !poolProperties.isPoolSweeperEnabled()) || (!idle.offer(con))) {
+                            if (log.isDebugEnabled()) {
+                                log.debug("Connection ["+con+"] will be closed and not returned to the pool, idle["+idle.size()+"]>=maxIdle["+poolProperties.getMaxIdle()+"] idle.offer failed.");
+                            }
+                            release(con);
+                        }
+                    } else {
+                        if (log.isDebugEnabled()) {
+                            log.debug("Connection ["+con+"] will be closed and not returned to the pool.");
+                        }
+                        release(con);
+                    } //end if
+                } else {
+                    if (log.isDebugEnabled()) {
+                        log.debug("Connection ["+con+"] will be closed and not returned to the pool, busy.remove failed.");
+                    }
+                    release(con);
+                }
+            } finally {
+                con.unlock();
+            }
+        } //end if
+    } //checkIn
+
+    /**
+     * Determines if a connection should be abandoned based on 
+     * {@link PoolProperties#abandonWhenPercentageFull} setting.
+     * @return true if the connection should be abandoned
+     */
+    protected boolean shouldAbandon() {
+        if (poolProperties.getAbandonWhenPercentageFull()==0) return true;
+        float used = busy.size();
+        float max  = poolProperties.getMaxActive();
+        float perc = poolProperties.getAbandonWhenPercentageFull();
+        return (used/max*100f)>=perc;
+    }
+    
+    /**
+     * Iterates through all the busy connections and checks for connections that have timed out
+     */
+    public void checkAbandoned() {
+        try {
+            if (busy.size()==0) return;
+            Iterator<PooledConnection> locked = busy.iterator();
+            int sto = getPoolProperties().getSuspectTimeout();
+            while (locked.hasNext()) {
+                PooledConnection con = locked.next();
+                boolean setToNull = false;
+                try {
+                    con.lock();
+                    //the con has been returned to the pool
+                    //ignore it
+                    if (idle.contains(con))
+                        continue;
+                    long time = con.getTimestamp();
+                    long now = System.currentTimeMillis();
+                    if (shouldAbandon() && (now - time) > con.getAbandonTimeout()) {
+                        busy.remove(con);
+                        abandon(con);
+                        setToNull = true;
+                    } else if (sto > 0 && (now - time) > (sto*1000)) {
+                        suspect(con);
+                    } else {
+                        //do nothing
+                    } //end if
+                } finally {
+                    con.unlock();
+                    if (setToNull)
+                        con = null;
+                }
+            } //while
+        } catch (ConcurrentModificationException e) {
+            log.debug("checkAbandoned failed." ,e);
+        } catch (Exception e) {
+            log.warn("checkAbandoned failed, it will be retried.",e);
+        }
+    }
+
+    /**
+     * Iterates through the idle connections and resizes the idle pool based on parameters
+     * {@link PoolProperties#maxIdle}, {@link PoolProperties#minIdle}, {@link PoolProperties#minEvictableIdleTimeMillis}
+     */
+    public void checkIdle() {
+        try {
+            if (idle.size()==0) return;
+            long now = System.currentTimeMillis();
+            Iterator<PooledConnection> unlocked = idle.iterator();
+            while ( (idle.size()>=getPoolProperties().getMinIdle()) && unlocked.hasNext()) {
+                PooledConnection con = unlocked.next();
+                boolean setToNull = false;
+                try {
+                    con.lock();
+                    //the con been taken out, we can't clean it up
+                    if (busy.contains(con))
+                        continue;
+                    long time = con.getTimestamp();
+                    if ((con.getReleaseTime()>0) && ((now - time) > con.getReleaseTime()) && (getSize()>getPoolProperties().getMinIdle())) {
+                        release(con);
+                        idle.remove(con);
+                        setToNull = true;
+                    } else {
+                        //do nothing
+                    } //end if
+                } finally {
+                    con.unlock();
+                    if (setToNull)
+                        con = null;
+                }
+            } //while
+        } catch (ConcurrentModificationException e) {
+            log.debug("checkIdle failed." ,e);
+        } catch (Exception e) {
+            log.warn("checkIdle failed, it will be retried.",e);
+        }
+
+    }
+
+    /**
+     * Forces a validation of all idle connections if {@link PoolProperties#testWhileIdle} is set.
+     */
+    public void testAllIdle() {
+        try {
+            if (idle.size()==0) return;
+            Iterator<PooledConnection> unlocked = idle.iterator();
+            while (unlocked.hasNext()) {
+                PooledConnection con = unlocked.next();
+                try {
+                    con.lock();
+                    //the con been taken out, we can't clean it up
+                    if (busy.contains(con))
+                        continue;
+                    if (!con.validate(PooledConnection.VALIDATE_IDLE)) {
+                        idle.remove(con);
+                        release(con);
+                    }
+                } finally {
+                    con.unlock();
+                }
+            } //while
+        } catch (ConcurrentModificationException e) {
+            log.debug("testAllIdle failed." ,e);
+        } catch (Exception e) {
+            log.warn("testAllIdle failed, it will be retried.",e);
+        }
+
+    }
+
+    /**
+     * Creates a stack trace representing the existing thread's current state.
+     * @return a string object representing the current state.
+     * TODO investigate if we simply should store {@link java.lang.Thread#getStackTrace()} elements
+     */
+    protected static String getThreadDump() {
+        Exception x = new Exception();
+        x.fillInStackTrace();
+        return getStackTrace(x);
+    }
+
+    /**
+     * Convert an exception into a String
+     * @param x - the throwable
+     * @return a string representing the stack trace
+     */
+    public static String getStackTrace(Throwable x) {
+        if (x == null) {
+            return null;
+        } else {
+            java.io.ByteArrayOutputStream bout = new java.io.ByteArrayOutputStream();
+            java.io.PrintStream writer = new java.io.PrintStream(bout);
+            x.printStackTrace(writer);
+            String result = bout.toString();
+            return (x.getMessage()!=null && x.getMessage().length()>0)? x.getMessage()+";"+result:result;
+        } //end if
+    }
+
+
+    /**
+     * Create a new pooled connection object. Not connected nor validated.
+     * @return a pooled connection object
+     */
+    protected PooledConnection create(boolean incrementCounter) {
+        if (incrementCounter) size.incrementAndGet();
+        PooledConnection con = new PooledConnection(getPoolProperties(), this);
+        return con;
+    }
+
+    /**
+     * Hook to perform final actions on a pooled connection object once it has been disconnected and will be discarded
+     * @param con
+     */
+    protected void finalize(PooledConnection con) {
+        JdbcInterceptor handler = con.getHandler();
+        while (handler!=null) {
+            handler.reset(null, null);
+            handler=handler.getNext();
+        }
+    }
+    
+    /**
+     * Hook to perform final actions on a pooled connection object once it has been disconnected and will be discarded
+     * @param con
+     */
+    protected void disconnectEvent(PooledConnection con, boolean finalizing) {
+        JdbcInterceptor handler = con.getHandler();
+        while (handler!=null) {
+            handler.disconnected(this, con, finalizing);
+            handler=handler.getNext();
+        }
+    }
+
+    /**
+     * Return the object that is potentially registered in JMX for notifications
+     * @return the object implementing the {@link org.apache.tomcat.jdbc.pool.jmx.ConnectionPoolMBean} interface 
+     */
+    public org.apache.tomcat.jdbc.pool.jmx.ConnectionPool getJmxPool() {
+        return jmxPool;
+    }
+
+    /**
+     * Create MBean object that can be registered.
+     */
+    protected void createMBean() {
+        try {
+            jmxPool = new org.apache.tomcat.jdbc.pool.jmx.ConnectionPool(this);
+        } catch (Exception x) {
+            log.warn("Unable to start JMX integration for connection pool. Instance["+getName()+"] can't be monitored.",x);
+        }
+    }
+
+    /**
+     * Tread safe wrapper around a future for the regular queue
+     * This one retrieves the pooled connection object
+     * and performs the initialization according to 
+     * interceptors and validation rules.
+     * This class is thread safe and is cancellable
+     * @author fhanik
+     *
+     */
+    protected class ConnectionFuture implements Future<Connection>, Runnable {
+        Future<PooledConnection> pcFuture = null;
+        AtomicBoolean configured = new AtomicBoolean(false);
+        CountDownLatch latch = new CountDownLatch(1);
+        Connection result = null;
+        SQLException cause = null;
+        AtomicBoolean cancelled = new AtomicBoolean(false);
+        volatile PooledConnection pc = null;
+        public ConnectionFuture(Future<PooledConnection> pcf) {
+            this.pcFuture = pcf;
+        }
+        
+        public ConnectionFuture(PooledConnection pc) throws SQLException {
+            this.pc = pc;
+            result = ConnectionPool.this.setupConnection(pc);
+            configured.set(true);
+        }
+        /**
+         * {@inheritDoc}
+         */
+        public boolean cancel(boolean mayInterruptIfRunning) {
+            if (pc!=null) {
+                return false;
+            } else if ((!cancelled.get()) && cancelled.compareAndSet(false, true)) {
+                //cancel by retrieving the connection and returning it to the pool
+                ConnectionPool.this.cancellator.execute(this);
+            }
+            return true;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public Connection get() throws InterruptedException, ExecutionException {
+            try {
+                return get(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
+            }catch (TimeoutException x) {
+                throw new ExecutionException(x);
+            }
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public Connection get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+            PooledConnection pc = this.pc!=null?this.pc:pcFuture.get(timeout,unit);
+            if (pc!=null) {
+                if (result!=null) return result;
+                if (configured.compareAndSet(false, true)) {
+                    try {
+                        pc = borrowConnection(System.currentTimeMillis(),pc, null, null);
+                        result = ConnectionPool.this.setupConnection(pc);
+                    } catch (SQLException x) {
+                        cause = x;
+                    } finally {
+                        latch.countDown();
+                    }
+                } else {
+                    //if we reach here, another thread is configuring the actual connection 
+                    latch.await(timeout,unit); //this shouldn't block for long
+                }
+                if (result==null) throw new ExecutionException(cause);
+                return result;
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public boolean isCancelled() {
+            return pc==null && (pcFuture.isCancelled() || cancelled.get());
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public boolean isDone() {
+            return pc!=null || pcFuture.isDone();
+        }
+        
+        /**
+         * run method to be executed when cancelled by an executor
+         */
+        public void run() {
+            try {
+                Connection con = get(); //complete this future
+                con.close(); //return to the pool
+            }catch (ExecutionException ex) {
+                //we can ignore this
+            }catch (Exception x) {
+                ConnectionPool.log.error("Unable to cancel ConnectionFuture.",x);
+            }
+        }
+        
+    }
+
+    protected class PoolCleaner extends Thread {
+        protected ConnectionPool pool;
+        protected long sleepTime;
+        protected volatile boolean run = true;
+        PoolCleaner(String name, ConnectionPool pool, long sleepTime) {
+            super(name);
+            this.setDaemon(true);
+            this.pool = pool;
+            this.sleepTime = sleepTime;
+            if (sleepTime <= 0) {
+                log.warn("Database connection pool evicter thread interval is set to 0, defaulting to 30 seconds");
+                this.sleepTime = 1000 * 30;
+            } else if (sleepTime < 1000) {
+                log.warn("Database connection pool evicter thread interval is set to lower than 1 second.");
+            }
+        }
+
+        @Override
+        public void run() {
+            while (run) {
+                try {
+                    sleep(sleepTime);
+                } catch (InterruptedException e) {
+                    // ignore it
+                    Thread.interrupted();
+                    continue;
+                } //catch
+
+                if (pool.isClosed()) {
+                    if (pool.getSize() <= 0) {
+                        run = false;
+                    }
+                } else {
+                    try {
+                        if (pool.getPoolProperties().isRemoveAbandoned())
+                            pool.checkAbandoned();
+                        if (pool.getPoolProperties().getMinIdle()<pool.idle.size())
+                            pool.checkIdle();
+                        if (pool.getPoolProperties().isTestWhileIdle())
+                            pool.testAllIdle();
+                    } catch (Exception x) {
+                        log.error("", x);
+                    } //catch
+                } //end if
+            } //while
+        } //run
+
+        public void stopRunning() {
+            run = false;
+            interrupt();
+        }
+    }
+}
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSource.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSource.java
new file mode 100644 (file)
index 0000000..de837d8
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * 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.pool;
+
+import java.lang.management.ManagementFactory;
+import java.util.Hashtable;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanRegistration;
+import javax.management.MBeanServer;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectName;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+
+
+/**
+ * A DataSource that can be instantiated through IoC and implements the DataSource interface
+ * since the DataSourceProxy is used as a generic proxy.
+ * The DataSource simply wraps a {@link ConnectionPool} in order to provide a standard interface to the user.
+ * @author Filip Hanik
+ * @version 1.0
+ */
+public class DataSource extends DataSourceProxy implements javax.sql.DataSource,MBeanRegistration, org.apache.tomcat.jdbc.pool.jmx.ConnectionPoolMBean {
+    private static final Log log = LogFactory.getLog(DataSource.class);
+
+    /**
+     * Constructor for reflection only. A default set of pool properties will be created.
+     */
+    public DataSource() {
+        super();
+    }
+    
+    /**
+     * Constructs a DataSource object wrapping a connection
+     * @param poolProperties
+     */
+    public DataSource(PoolConfiguration poolProperties) {
+        super(poolProperties);
+    }
+
+//===============================================================================
+//  JMX Operations - Register the actual pool itself under the tomcat.jdbc domain
+//===============================================================================
+    protected volatile ObjectName oname = null;
+
+    /**
+     * Unregisters the underlying connection pool mbean.<br/>
+     * {@inheritDoc}
+     */
+    public void postDeregister() {
+        if (oname!=null) unregisterJmx();
+    }
+
+    /**
+     * no-op<br/>
+     * {@inheritDoc}
+     */
+    public void postRegister(Boolean registrationDone) {
+        // NOOP
+    }
+
+
+    /**
+     * no-op<br/>
+     * {@inheritDoc}
+     */
+    public void preDeregister() throws Exception {
+        // NOOP
+    }
+
+    /**
+     * If the connection pool MBean exists, it will be registered during this operation.<br/>
+     * {@inheritDoc}
+     */
+    public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception {
+        try {
+            this.oname = createObjectName(name);
+            if (oname!=null) registerJmx();
+        }catch (MalformedObjectNameException x) {
+            log.error("Unable to create object name for JDBC pool.",x);
+        }
+        return name;   
+    }
+    
+    /**
+     * Creates the ObjectName for the ConnectionPoolMBean object to be registered
+     * @param original the ObjectName for the DataSource
+     * @return the ObjectName for the ConnectionPoolMBean
+     * @throws MalformedObjectNameException
+     */
+    public ObjectName createObjectName(ObjectName original) throws MalformedObjectNameException {
+        String domain = "tomcat.jdbc";
+        Hashtable<String,String> properties = original.getKeyPropertyList();
+        String origDomain = original.getDomain();
+        properties.put("type", "ConnectionPool");
+        properties.put("class", this.getClass().getName());
+        if (original.getKeyProperty("path")!=null) {
+            properties.put("engine", origDomain);
+        }
+        ObjectName name = new ObjectName(domain,properties);
+        return name;
+    }
+    
+    /**
+     * Registers the ConnectionPoolMBean under a unique name based on the ObjectName for the DataSource
+     */
+    protected void registerJmx() {
+        try {
+            if (pool.getJmxPool()!=null) {
+                MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+                mbs.registerMBean(pool.getJmxPool(), oname);
+            }
+        } catch (Exception e) {
+            log.error("Unable to register JDBC pool with JMX",e);
+        }
+    }
+    
+    /**
+     * 
+     */
+    protected void unregisterJmx() {
+        try {
+            MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+            mbs.unregisterMBean(oname);
+        } catch (InstanceNotFoundException ignore) {
+            // NOOP
+        } catch (Exception e) {
+            log.error("Unable to unregister JDBC pool with JMX",e);
+        }
+    }
+
+
+}
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceFactory.java
new file mode 100644 (file)
index 0000000..32e5a4e
--- /dev/null
@@ -0,0 +1,538 @@
+/*
+ * 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.pool;
+
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.util.Hashtable;
+import java.util.Properties;
+
+import javax.management.ObjectName;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.RefAddr;
+import javax.naming.Reference;
+import javax.naming.spi.ObjectFactory;
+import javax.sql.DataSource;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+
+/**
+ * <p>JNDI object factory that creates an instance of
+ * <code>BasicDataSource</code> that has been configured based on the
+ * <code>RefAddr</code> values of the specified <code>Reference</code>,
+ * which must match the names and data types of the
+ * <code>BasicDataSource</code> bean properties.</p>
+ * <br/>
+ * Properties available for configuration:<br/>
+ * <a href="http://commons.apache.org/dbcp/configuration.html">Commons DBCP properties</a><br/>
+ *<ol>
+ *  <li>initSQL - A query that gets executed once, right after the connection is established.</li>
+ *  <li>testOnConnect - run validationQuery after connection has been established.</li>
+ *  <li>validationInterval - avoid excess validation, only run validation at most at this frequency - time in milliseconds.</li>
+ *  <li>jdbcInterceptors - a semicolon separated list of classnames extending {@link JdbcInterceptor} class.</li>
+ *  <li>jmxEnabled - true of false, whether to register the pool with JMX.</li>
+ *  <li>fairQueue - true of false, whether the pool should sacrifice a little bit of performance for true fairness.</li>
+ *</ol>
+ * @author Craig R. McClanahan
+ * @author Dirk Verbeeck
+ * @author Filip Hanik
+ */
+public class DataSourceFactory implements ObjectFactory {
+    private static final Log log = LogFactory.getLog(DataSourceFactory.class);
+
+    protected final static String PROP_DEFAULTAUTOCOMMIT = "defaultAutoCommit";
+    protected final static String PROP_DEFAULTREADONLY = "defaultReadOnly";
+    protected final static String PROP_DEFAULTTRANSACTIONISOLATION = "defaultTransactionIsolation";
+    protected final static String PROP_DEFAULTCATALOG = "defaultCatalog";
+    
+    protected final static String PROP_DRIVERCLASSNAME = "driverClassName";
+    protected final static String PROP_PASSWORD = "password";
+    protected final static String PROP_URL = "url";
+    protected final static String PROP_USERNAME = "username";
+
+    protected final static String PROP_MAXACTIVE = "maxActive";
+    protected final static String PROP_MAXIDLE = "maxIdle";
+    protected final static String PROP_MINIDLE = "minIdle";
+    protected final static String PROP_INITIALSIZE = "initialSize";
+    protected final static String PROP_MAXWAIT = "maxWait";
+    protected final static String PROP_MAXAGE = "maxAge";
+    
+    protected final static String PROP_TESTONBORROW = "testOnBorrow";
+    protected final static String PROP_TESTONRETURN = "testOnReturn";
+    protected final static String PROP_TESTWHILEIDLE = "testWhileIdle";
+    protected final static String PROP_TESTONCONNECT = "testOnConnect";
+    protected final static String PROP_VALIDATIONQUERY = "validationQuery";
+    protected final static String PROP_VALIDATOR_CLASS_NAME = "validatorClassName";
+    
+    protected final static String PROP_TIMEBETWEENEVICTIONRUNSMILLIS = "timeBetweenEvictionRunsMillis";
+    protected final static String PROP_NUMTESTSPEREVICTIONRUN = "numTestsPerEvictionRun";
+    protected final static String PROP_MINEVICTABLEIDLETIMEMILLIS = "minEvictableIdleTimeMillis";
+    
+    protected final static String PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED = "accessToUnderlyingConnectionAllowed";
+    
+    protected final static String PROP_REMOVEABANDONED = "removeAbandoned";
+    protected final static String PROP_REMOVEABANDONEDTIMEOUT = "removeAbandonedTimeout";
+    protected final static String PROP_LOGABANDONED = "logAbandoned";
+    protected final static String PROP_ABANDONWHENPERCENTAGEFULL = "abandonWhenPercentageFull";
+    
+    protected final static String PROP_POOLPREPAREDSTATEMENTS = "poolPreparedStatements";
+    protected final static String PROP_MAXOPENPREPAREDSTATEMENTS = "maxOpenPreparedStatements";
+    protected final static String PROP_CONNECTIONPROPERTIES = "connectionProperties";
+    
+    protected final static String PROP_INITSQL = "initSQL";
+    protected final static String PROP_INTERCEPTORS = "jdbcInterceptors";
+    protected final static String PROP_VALIDATIONINTERVAL = "validationInterval";
+    protected final static String PROP_JMX_ENABLED = "jmxEnabled";
+    protected final static String PROP_FAIR_QUEUE = "fairQueue";
+    
+    protected static final String PROP_USE_EQUALS = "useEquals";
+    protected static final String PROP_USE_CON_LOCK = "useLock";
+    
+    protected static final String PROP_DATASOURCE= "dataSource";
+    protected static final String PROP_DATASOURCE_JNDI = "dataSourceJNDI";
+    
+    protected static final String PROP_SUSPECT_TIMEOUT = "suspectTimeout";
+    
+    protected static final String PROP_ALTERNATE_USERNAME_ALLOWED = "alternateUsernameAllowed";
+    
+    
+    public static final int UNKNOWN_TRANSACTIONISOLATION = -1;
+    
+    public static final String OBJECT_NAME = "object_name";
+
+
+    protected final static String[] ALL_PROPERTIES = {
+        PROP_DEFAULTAUTOCOMMIT,
+        PROP_DEFAULTREADONLY,
+        PROP_DEFAULTTRANSACTIONISOLATION,
+        PROP_DEFAULTCATALOG,
+        PROP_DRIVERCLASSNAME,
+        PROP_MAXACTIVE,
+        PROP_MAXIDLE,
+        PROP_MINIDLE,
+        PROP_INITIALSIZE,
+        PROP_MAXWAIT,
+        PROP_TESTONBORROW,
+        PROP_TESTONRETURN,
+        PROP_TIMEBETWEENEVICTIONRUNSMILLIS,
+        PROP_NUMTESTSPEREVICTIONRUN,
+        PROP_MINEVICTABLEIDLETIMEMILLIS,
+        PROP_TESTWHILEIDLE,
+        PROP_TESTONCONNECT,
+        PROP_PASSWORD,
+        PROP_URL,
+        PROP_USERNAME,
+        PROP_VALIDATIONQUERY,
+        PROP_VALIDATIONINTERVAL,
+        PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED,
+        PROP_REMOVEABANDONED,
+        PROP_REMOVEABANDONEDTIMEOUT,
+        PROP_LOGABANDONED,
+        PROP_POOLPREPAREDSTATEMENTS,
+        PROP_MAXOPENPREPAREDSTATEMENTS,
+        PROP_CONNECTIONPROPERTIES,
+        PROP_INITSQL,
+        PROP_INTERCEPTORS,
+        PROP_JMX_ENABLED,
+        PROP_FAIR_QUEUE,
+        PROP_USE_EQUALS,
+        OBJECT_NAME,
+        PROP_ABANDONWHENPERCENTAGEFULL,
+        PROP_MAXAGE,
+        PROP_USE_CON_LOCK,
+        PROP_DATASOURCE,
+        PROP_DATASOURCE_JNDI,
+        PROP_ALTERNATE_USERNAME_ALLOWED
+    };
+
+    // -------------------------------------------------- ObjectFactory Methods
+
+    /**
+     * <p>Create and return a new <code>BasicDataSource</code> instance.  If no
+     * instance can be created, return <code>null</code> instead.</p>
+     *
+     * @param obj The possibly null object containing location or
+     *  reference information that can be used in creating an object
+     * @param name The name of this object relative to <code>nameCtx</code>
+     * @param nameCtx The context relative to which the <code>name</code>
+     *  parameter is specified, or <code>null</code> if <code>name</code>
+     *  is relative to the default initial context
+     * @param environment The possibly null environment that is used in
+     *  creating this object
+     *
+     * @exception Exception if an exception occurs creating the instance
+     */
+    public Object getObjectInstance(Object obj, Name name, Context nameCtx,
+                                    Hashtable<?,?> environment) throws Exception {
+
+        // We only know how to deal with <code>javax.naming.Reference</code>s
+        // that specify a class name of "javax.sql.DataSource"
+        if ((obj == null) || !(obj instanceof Reference)) {
+            return null;
+        }
+        Reference ref = (Reference) obj;
+        boolean XA = false;
+        boolean ok = false;
+        if ("javax.sql.DataSource".equals(ref.getClassName())) {
+            ok = true;
+        }
+        if ("javax.sql.XADataSource".equals(ref.getClassName())) {
+            ok = true;
+            XA = true;
+        }
+        if (org.apache.tomcat.jdbc.pool.DataSource.class.getName().equals(ref.getClassName())) {
+            ok = true;
+        }
+        
+        if (!ok) {
+            log.warn(ref.getClassName()+" is not a valid class name/type for this JNDI factory.");
+            return null;
+        }
+        
+
+        Properties properties = new Properties();
+        for (int i = 0; i < ALL_PROPERTIES.length; i++) {
+            String propertyName = ALL_PROPERTIES[i];
+            RefAddr ra = ref.get(propertyName);
+            if (ra != null) {
+                String propertyValue = ra.getContent().toString();
+                properties.setProperty(propertyName, propertyValue);
+            }
+        }
+
+        return createDataSource(properties,nameCtx,XA);
+    }
+    
+    public static PoolConfiguration parsePoolProperties(Properties properties) throws IOException{
+        PoolConfiguration poolProperties = new PoolProperties();
+        String value = null;
+
+        value = properties.getProperty(PROP_DEFAULTAUTOCOMMIT);
+        if (value != null) {
+            poolProperties.setDefaultAutoCommit(Boolean.valueOf(value));
+        }
+
+        value = properties.getProperty(PROP_DEFAULTREADONLY);
+        if (value != null) {
+            poolProperties.setDefaultReadOnly(Boolean.valueOf(value));
+        }
+
+        value = properties.getProperty(PROP_DEFAULTTRANSACTIONISOLATION);
+        if (value != null) {
+            int level = UNKNOWN_TRANSACTIONISOLATION;
+            if ("NONE".equalsIgnoreCase(value)) {
+                level = Connection.TRANSACTION_NONE;
+            } else if ("READ_COMMITTED".equalsIgnoreCase(value)) {
+                level = Connection.TRANSACTION_READ_COMMITTED;
+            } else if ("READ_UNCOMMITTED".equalsIgnoreCase(value)) {
+                level = Connection.TRANSACTION_READ_UNCOMMITTED;
+            } else if ("REPEATABLE_READ".equalsIgnoreCase(value)) {
+                level = Connection.TRANSACTION_REPEATABLE_READ;
+            } else if ("SERIALIZABLE".equalsIgnoreCase(value)) {
+                level = Connection.TRANSACTION_SERIALIZABLE;
+            } else {
+                try {
+                    level = Integer.parseInt(value);
+                } catch (NumberFormatException e) {
+                    System.err.println("Could not parse defaultTransactionIsolation: " + value);
+                    System.err.println("WARNING: defaultTransactionIsolation not set");
+                    System.err.println("using default value of database driver");
+                    level = UNKNOWN_TRANSACTIONISOLATION;
+                }
+            }
+            poolProperties.setDefaultTransactionIsolation(level);
+        }
+
+        value = properties.getProperty(PROP_DEFAULTCATALOG);
+        if (value != null) {
+            poolProperties.setDefaultCatalog(value);
+        }
+
+        value = properties.getProperty(PROP_DRIVERCLASSNAME);
+        if (value != null) {
+            poolProperties.setDriverClassName(value);
+        }
+
+        value = properties.getProperty(PROP_MAXACTIVE);
+        if (value != null) {
+            poolProperties.setMaxActive(Integer.parseInt(value));
+        }
+
+        value = properties.getProperty(PROP_MAXIDLE);
+        if (value != null) {
+            poolProperties.setMaxIdle(Integer.parseInt(value));
+        }
+
+        value = properties.getProperty(PROP_MINIDLE);
+        if (value != null) {
+            poolProperties.setMinIdle(Integer.parseInt(value));
+        }
+
+        value = properties.getProperty(PROP_INITIALSIZE);
+        if (value != null) {
+            poolProperties.setInitialSize(Integer.parseInt(value));
+        }
+
+        value = properties.getProperty(PROP_MAXWAIT);
+        if (value != null) {
+            poolProperties.setMaxWait(Integer.parseInt(value));
+        }
+
+        value = properties.getProperty(PROP_TESTONBORROW);
+        if (value != null) {
+            poolProperties.setTestOnBorrow(Boolean.valueOf(value).booleanValue());
+        }
+
+        value = properties.getProperty(PROP_TESTONRETURN);
+        if (value != null) {
+            poolProperties.setTestOnReturn(Boolean.valueOf(value).booleanValue());
+        }
+
+        value = properties.getProperty(PROP_TESTONCONNECT);
+        if (value != null) {
+            poolProperties.setTestOnConnect(Boolean.valueOf(value).booleanValue());
+        }
+
+        value = properties.getProperty(PROP_TIMEBETWEENEVICTIONRUNSMILLIS);
+        if (value != null) {
+            poolProperties.setTimeBetweenEvictionRunsMillis(Integer.parseInt(value));
+        }
+
+        value = properties.getProperty(PROP_NUMTESTSPEREVICTIONRUN);
+        if (value != null) {
+            poolProperties.setNumTestsPerEvictionRun(Integer.parseInt(value));
+        }
+
+        value = properties.getProperty(PROP_MINEVICTABLEIDLETIMEMILLIS);
+        if (value != null) {
+            poolProperties.setMinEvictableIdleTimeMillis(Integer.parseInt(value));
+        }
+
+        value = properties.getProperty(PROP_TESTWHILEIDLE);
+        if (value != null) {
+            poolProperties.setTestWhileIdle(Boolean.valueOf(value).booleanValue());
+        }
+
+        value = properties.getProperty(PROP_PASSWORD);
+        if (value != null) {
+            poolProperties.setPassword(value);
+        }
+
+        value = properties.getProperty(PROP_URL);
+        if (value != null) {
+            poolProperties.setUrl(value);
+        }
+
+        value = properties.getProperty(PROP_USERNAME);
+        if (value != null) {
+            poolProperties.setUsername(value);
+        }
+
+        value = properties.getProperty(PROP_VALIDATIONQUERY);
+        if (value != null) {
+            poolProperties.setValidationQuery(value);
+        }
+        
+        value = properties.getProperty(PROP_VALIDATOR_CLASS_NAME);
+        if (value != null) {
+            poolProperties.setValidatorClassName(value);
+        }
+
+        value = properties.getProperty(PROP_VALIDATIONINTERVAL);
+        if (value != null) {
+            poolProperties.setValidationInterval(Long.parseLong(value));
+        }
+
+        value = properties.getProperty(PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED);
+        if (value != null) {
+            poolProperties.setAccessToUnderlyingConnectionAllowed(Boolean.valueOf(value).booleanValue());
+        }
+
+        value = properties.getProperty(PROP_REMOVEABANDONED);
+        if (value != null) {
+            poolProperties.setRemoveAbandoned(Boolean.valueOf(value).booleanValue());
+        }
+
+        value = properties.getProperty(PROP_REMOVEABANDONEDTIMEOUT);
+        if (value != null) {
+            poolProperties.setRemoveAbandonedTimeout(Integer.parseInt(value));
+        }
+
+        value = properties.getProperty(PROP_LOGABANDONED);
+        if (value != null) {
+            poolProperties.setLogAbandoned(Boolean.valueOf(value).booleanValue());
+        }
+
+        value = properties.getProperty(PROP_POOLPREPAREDSTATEMENTS);
+        if (value != null) {
+            log.warn(PROP_POOLPREPAREDSTATEMENTS + " is not a valid setting, it will have no effect.");
+        }
+
+        value = properties.getProperty(PROP_MAXOPENPREPAREDSTATEMENTS);
+        if (value != null) {
+            log.warn(PROP_MAXOPENPREPAREDSTATEMENTS + " is not a valid setting, it will have no effect.");
+        }
+
+        value = properties.getProperty(PROP_CONNECTIONPROPERTIES);
+        if (value != null) {
+            Properties p = getProperties(value);
+            poolProperties.setDbProperties(p);
+        } else {
+            poolProperties.setDbProperties(new Properties());
+        }
+
+        if (poolProperties.getUsername()!=null) {
+            poolProperties.getDbProperties().setProperty("user",poolProperties.getUsername());
+        }
+        if (poolProperties.getPassword()!=null) {
+            poolProperties.getDbProperties().setProperty("password",poolProperties.getPassword());
+        }
+
+        value = properties.getProperty(PROP_INITSQL);
+        if (value != null) {
+            poolProperties.setInitSQL(value);
+        }
+
+        value = properties.getProperty(PROP_INTERCEPTORS);
+        if (value != null) {
+            poolProperties.setJdbcInterceptors(value);
+        }
+
+        value = properties.getProperty(PROP_JMX_ENABLED);
+        if (value != null) {
+            poolProperties.setJmxEnabled(Boolean.parseBoolean(value));
+        }
+        
+        value = properties.getProperty(PROP_FAIR_QUEUE);
+        if (value != null) {
+            poolProperties.setFairQueue(Boolean.parseBoolean(value));
+        }
+        
+        value = properties.getProperty(PROP_USE_EQUALS);
+        if (value != null) {
+            poolProperties.setUseEquals(Boolean.parseBoolean(value));
+        }
+
+        value = properties.getProperty(OBJECT_NAME);
+        if (value != null) {
+            poolProperties.setName(ObjectName.quote(value));
+        }
+        
+        value = properties.getProperty(PROP_ABANDONWHENPERCENTAGEFULL);
+        if (value != null) {
+            poolProperties.setAbandonWhenPercentageFull(Integer.parseInt(value));
+        }
+        
+        value = properties.getProperty(PROP_MAXAGE);
+        if (value != null) {
+            poolProperties.setMaxAge(Long.parseLong(value));
+        }
+        
+        value = properties.getProperty(PROP_USE_CON_LOCK);
+        if (value != null) {
+            poolProperties.setUseLock(Boolean.parseBoolean(value));
+        }
+        
+        value = properties.getProperty(PROP_DATASOURCE);
+        if (value != null) {
+            //this should never happen
+            throw new IllegalArgumentException("Can't set dataSource property as a string, this must be a javax.sql.DataSource object.");
+            
+        }
+        
+        value = properties.getProperty(PROP_DATASOURCE_JNDI);
+        if (value != null) {
+            poolProperties.setDataSourceJNDI(value);
+        }
+
+        value = properties.getProperty(PROP_SUSPECT_TIMEOUT);
+        if (value != null) {
+            poolProperties.setSuspectTimeout(Integer.parseInt(value));
+        }
+        
+        value = properties.getProperty(PROP_ALTERNATE_USERNAME_ALLOWED);
+        if (value != null) {
+            poolProperties.setAlternateUsernameAllowed(Boolean.parseBoolean(value));
+        }
+        
+        return poolProperties;
+    }
+
+    /**
+     * Creates and configures a {@link DataSource} instance based on the
+     * given properties.
+     *
+     * @param properties the datasource configuration properties
+     * @throws Exception if an error occurs creating the data source
+     */
+    public DataSource createDataSource(Properties properties) throws Exception {
+        return createDataSource(properties,null,false);
+    }
+    public DataSource createDataSource(Properties properties,Context context, boolean XA) throws Exception {
+        PoolConfiguration poolProperties = DataSourceFactory.parsePoolProperties(properties);
+        if (poolProperties.getDataSourceJNDI()!=null && poolProperties.getDataSource()==null) {
+            performJNDILookup(context, poolProperties);
+        }
+        org.apache.tomcat.jdbc.pool.DataSource dataSource = XA?
+                new org.apache.tomcat.jdbc.pool.XADataSource(poolProperties) :
+                new org.apache.tomcat.jdbc.pool.DataSource(poolProperties);
+        //initialise the pool itself
+        dataSource.createPool();
+        // Return the configured DataSource instance
+        return dataSource;
+    }
+
+    public void performJNDILookup(Context context, PoolConfiguration poolProperties) {
+        Object jndiDS = null;
+        try {
+            if (context!=null) {
+                jndiDS = context.lookup(poolProperties.getDataSourceJNDI());
+            } else {
+                log.warn("dataSourceJNDI property is configued, but local JNDI context is null.");
+            }
+        } catch (NamingException e) {
+            log.debug("The name \""+poolProperties.getDataSourceJNDI()+"\" can not be found in the local context.");
+        }
+        if (jndiDS==null) {
+            try {
+                context = (Context) (new InitialContext());
+                jndiDS = context.lookup(poolProperties.getDataSourceJNDI());
+            } catch (NamingException e) {
+                log.warn("The name \""+poolProperties.getDataSourceJNDI()+"\" can not be found in the InitialContext.");
+            }
+        }
+        if (jndiDS!=null) {
+            poolProperties.setDataSource(jndiDS);
+        }
+    }
+    
+    /**
+     * <p>Parse properties from the string. Format of the string must be [propertyName=property;]*<p>
+     * @param propText
+     * @return Properties
+     * @throws Exception
+     */
+    static protected Properties getProperties(String propText) throws IOException {
+        return PoolProperties.getProperties(propText,null);
+    }
+
+}
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/DataSourceProxy.java
new file mode 100644 (file)
index 0000000..e839991
--- /dev/null
@@ -0,0 +1,1084 @@
+/*
+ * 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.pool;
+
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.concurrent.Future;
+
+import javax.sql.XAConnection;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorDefinition;
+
+/**
+ *
+ * The DataSource proxy lets us implements methods that don't exist in the current 
+ * compiler JDK but might be methods that are part of a future JDK DataSource interface.
+ * <br/>
+ * It's a trick to work around compiler issues when implementing interfaces. For example, 
+ * I could put in Java 6 methods of javax.sql.DataSource here, and compile it with JDK 1.5
+ * and still be able to run under Java 6 without getting NoSuchMethodException.
+ *
+ * @author Filip Hanik
+ * @version 1.0
+ */
+
+public class DataSourceProxy implements PoolConfiguration {
+    private static final Log log = LogFactory.getLog(DataSourceProxy.class);
+    
+    protected volatile ConnectionPool pool = null;
+    
+    protected PoolConfiguration poolProperties = null;
+
+    public DataSourceProxy() {
+        this(new PoolProperties());
+    }
+    
+    public DataSourceProxy(PoolConfiguration poolProperties) {
+        if (poolProperties == null) throw new NullPointerException("PoolConfiguration can not be null.");
+        this.poolProperties = poolProperties;
+    }
+
+
+    public boolean isWrapperFor(Class<?> iface) throws SQLException {
+        // we are not a wrapper of anything
+        return false;
+    }
+
+
+    public <T> T unwrap(Class<T> iface) throws SQLException {
+        //we can't unwrap anything
+        return null;
+    }
+
+    /**
+     * {@link javax.sql.DataSource#getConnection()}
+     */
+    public Connection getConnection(String username, String password) throws SQLException {
+        if (this.getPoolProperties().isAlternateUsernameAllowed()) {
+            if (pool == null)
+                return createPool().getConnection(username,password);
+            return pool.getConnection(username,password);
+        } else {
+            return getConnection();
+        }
+    }
+
+    public PoolConfiguration getPoolProperties() {
+        return poolProperties;
+    }
+
+    /**
+     * Sets up the connection pool, by creating a pooling driver.
+     * @return Driver
+     * @throws SQLException
+     */
+    public synchronized ConnectionPool createPool() throws SQLException {
+        if (pool != null) {
+            return pool;
+        } else {
+            pool = new ConnectionPool(poolProperties);
+            return pool;
+        }
+    }
+
+    /**
+     * {@link javax.sql.DataSource#getConnection()}
+     */
+
+    public Connection getConnection() throws SQLException {
+        if (pool == null)
+            return createPool().getConnection();
+        return pool.getConnection();
+    }
+    
+    /**
+     * Invokes an sync operation to retrieve the connection.
+     * @return a Future containing a reference to the connection when it becomes available 
+     * @throws SQLException
+     */
+    public Future<Connection> getConnectionAsync() throws SQLException {
+        if (pool == null)
+            return createPool().getConnectionAsync();
+        return pool.getConnectionAsync();
+    }
+    
+    /**
+     * {@link javax.sql.XADataSource#getXAConnection()} 
+     */
+    public XAConnection getXAConnection() throws SQLException {
+        Connection con = getConnection();
+        if (con instanceof XAConnection) {
+            return (XAConnection)con;
+        } else {
+            try {con.close();} catch (Exception ignore){}
+            throw new SQLException("Connection from pool does not implement javax.sql.XAConnection");
+        }
+    }
+    
+    /**
+     * {@link javax.sql.XADataSource#getXAConnection(String, String)} 
+     */
+    public XAConnection getXAConnection(String username, String password) throws SQLException {
+        Connection con = getConnection(username, password);
+        if (con instanceof XAConnection) {
+            return (XAConnection)con;
+        } else {
+            try {con.close();} catch (Exception ignore){}
+            throw new SQLException("Connection from pool does not implement javax.sql.XAConnection");
+        }
+    }
+
+
+    /**
+     * {@link javax.sql.DataSource#getConnection()}
+     */
+    public PooledConnection getPooledConnection() throws SQLException {
+        return (PooledConnection) getConnection();
+    }
+
+    /**
+     * {@link javax.sql.DataSource#getConnection()}
+     */
+    public PooledConnection getPooledConnection(String username,
+                                                String password) throws SQLException {
+        return (PooledConnection) getConnection();
+    }
+    
+    public ConnectionPool getPool() {
+        return pool;
+    }
+
+    
+    public void close() {
+        close(false);
+    }
+    public void close(boolean all) {
+        try {
+            if (pool != null) {
+                final ConnectionPool p = pool;
+                pool = null;
+                if (p!=null) {
+                    p.close(all);
+                }
+            }
+        }catch (Exception x) {
+            log.warn("Error duing connection pool closure.", x);
+        }
+    }
+
+    public int getPoolSize() throws SQLException{
+        final ConnectionPool p = pool;
+        if (p == null) return 0;
+        else return p.getSize();
+    }
+
+    
+    public String toString() {
+        return super.toString()+"{"+getPoolProperties()+"}";
+    }
+
+
+/*-----------------------------------------------------------------------*/
+//      PROPERTIES WHEN NOT USED WITH FACTORY
+/*------------------------------------------------------------------------*/
+   
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public String getPoolName() {
+        return pool.getName();
+    }
+   
+   
+    public void setPoolProperties(PoolConfiguration poolProperties) {
+        this.poolProperties = poolProperties;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setDriverClassName(String driverClassName) {
+        this.poolProperties.setDriverClassName(driverClassName);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setInitialSize(int initialSize) {
+        this.poolProperties.setInitialSize(initialSize);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setInitSQL(String initSQL) {
+        this.poolProperties.setInitSQL(initSQL);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setLogAbandoned(boolean logAbandoned) {
+        this.poolProperties.setLogAbandoned(logAbandoned);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setMaxActive(int maxActive) {
+        this.poolProperties.setMaxActive(maxActive);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setMaxIdle(int maxIdle) {
+        this.poolProperties.setMaxIdle(maxIdle);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setMaxWait(int maxWait) {
+        this.poolProperties.setMaxWait(maxWait);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) {
+        this.poolProperties.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setMinIdle(int minIdle) {
+        this.poolProperties.setMinIdle(minIdle);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
+        this.poolProperties.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setPassword(String password) {
+        this.poolProperties.setPassword(password);
+        this.poolProperties.getDbProperties().setProperty("password",this.poolProperties.getPassword());
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setRemoveAbandoned(boolean removeAbandoned) {
+        this.poolProperties.setRemoveAbandoned(removeAbandoned);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) {
+        this.poolProperties.setRemoveAbandonedTimeout(removeAbandonedTimeout);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setTestOnBorrow(boolean testOnBorrow) {
+        this.poolProperties.setTestOnBorrow(testOnBorrow);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setTestOnConnect(boolean testOnConnect) {
+        this.poolProperties.setTestOnConnect(testOnConnect);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setTestOnReturn(boolean testOnReturn) {
+        this.poolProperties.setTestOnReturn(testOnReturn);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setTestWhileIdle(boolean testWhileIdle) {
+        this.poolProperties.setTestWhileIdle(testWhileIdle);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setTimeBetweenEvictionRunsMillis(int timeBetweenEvictionRunsMillis) {
+        this.poolProperties.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setUrl(String url) {
+        this.poolProperties.setUrl(url);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setUsername(String username) {
+        this.poolProperties.setUsername(username);
+        this.poolProperties.getDbProperties().setProperty("user",getPoolProperties().getUsername());
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setValidationInterval(long validationInterval) {
+        this.poolProperties.setValidationInterval(validationInterval);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setValidationQuery(String validationQuery) {
+        this.poolProperties.setValidationQuery(validationQuery);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    
+    public void setValidatorClassName(String className) {
+        this.poolProperties.setValidatorClassName(className);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setJdbcInterceptors(String interceptors) {
+        this.getPoolProperties().setJdbcInterceptors(interceptors);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setJmxEnabled(boolean enabled) {
+        this.getPoolProperties().setJmxEnabled(enabled);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setFairQueue(boolean fairQueue) {
+        this.getPoolProperties().setFairQueue(fairQueue);
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setUseLock(boolean useLock) {
+        this.getPoolProperties().setUseLock(useLock);
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setDefaultCatalog(String catalog) {
+        this.getPoolProperties().setDefaultCatalog(catalog);
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setDefaultAutoCommit(Boolean autocommit) {
+        this.getPoolProperties().setDefaultAutoCommit(autocommit);
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setDefaultTransactionIsolation(int defaultTransactionIsolation) {
+        this.getPoolProperties().setDefaultTransactionIsolation(defaultTransactionIsolation);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setConnectionProperties(String properties) {
+        try {
+            java.util.Properties prop = DataSourceFactory
+                    .getProperties(properties);
+            Iterator<?> i = prop.keySet().iterator();
+            while (i.hasNext()) {
+                String key = (String) i.next();
+                String value = prop.getProperty(key);
+                getPoolProperties().getDbProperties().setProperty(key, value);
+            }
+
+        } catch (Exception x) {
+            log.error("Unable to parse connection properties.", x);
+            throw new RuntimeException(x);
+        }
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setUseEquals(boolean useEquals) {
+        this.getPoolProperties().setUseEquals(useEquals);
+    }
+
+    /**
+     * no-op
+     * {@link javax.sql.DataSource#getLogWriter}
+     */
+    public PrintWriter getLogWriter() throws SQLException {
+        return null;
+    }
+
+
+    /**
+     * no-op
+     * {@link javax.sql.DataSource#setLogWriter(PrintWriter)}
+     */
+    public void setLogWriter(PrintWriter out) throws SQLException {
+        // NOOP
+    }
+
+    /**
+     * no-op
+     * {@link javax.sql.DataSource#getLoginTimeout}
+     */
+    public int getLoginTimeout() {
+        if (poolProperties == null) {
+            return 0;
+        } else {
+            return poolProperties.getMaxWait() / 1000;
+        }
+    }
+
+    /**
+     * {@link javax.sql.DataSource#setLoginTimeout(int)}
+     */
+    public void setLoginTimeout(int i) {
+        if (poolProperties == null) {
+            return;
+        } else {
+            poolProperties.setMaxWait(1000 * i);
+        }
+
+    }    
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    
+    public int getSuspectTimeout() {
+        return getPoolProperties().getSuspectTimeout(); 
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    
+    public void setSuspectTimeout(int seconds) {
+        getPoolProperties().setSuspectTimeout(seconds);
+    }
+    
+  //===============================================================================
+//  Expose JMX attributes through Tomcat's dynamic reflection
+//===============================================================================
+    /**
+     * If the pool has not been created, it will be created during this call.
+     * @return the number of established but idle connections
+     */
+    public int getIdle() {
+        try {
+            return createPool().getIdle();
+        }catch (SQLException x) {
+            throw new RuntimeException(x);
+        }
+    }
+
+    /**
+     * {@link #getIdle()}
+     */
+    public int getNumIdle() {
+        return getIdle();
+    }
+
+    /**
+     * Forces an abandon check on the connection pool.
+     * If connections that have been abandoned exists, they will be closed during this run
+     */
+    public void checkAbandoned() {
+        try {
+            createPool().checkAbandoned();
+        }catch (SQLException x) {
+            throw new RuntimeException(x);
+        }
+    }
+
+    /**
+     * Forces a check for resizing of the idle connections
+     */
+    public void checkIdle() {
+        try {
+            createPool().checkIdle();
+        }catch (SQLException x) {
+            throw new RuntimeException(x);
+        }
+    }
+
+    /**
+     * @return number of connections in use by the application
+     */
+    public int getActive() {
+        try {
+            return createPool().getActive();
+        }catch (SQLException x) {
+            throw new RuntimeException(x);
+        }
+    }
+    
+    /**
+     * @return number of connections in use by the application
+     * {@link DataSource#getActive()}
+     */
+    public int getNumActive() {
+        return getActive();
+    }
+
+    /**
+     * @return number of threads waiting for a connection
+     */
+    public int getWaitCount() {
+        try {
+            return createPool().getWaitCount();
+        }catch (SQLException x) {
+            throw new RuntimeException(x);
+        }
+    }
+
+    /**
+     * @return the current size of the pool
+     */
+    public int getSize() {
+        try {
+            return createPool().getSize();
+        }catch (SQLException x) {
+            throw new RuntimeException(x);
+        }
+    }
+
+    /**
+     * Performs a validation on idle connections
+     */
+    public void testIdle() {
+        try {
+            createPool().testAllIdle();
+        }catch (SQLException x) {
+            throw new RuntimeException(x);
+        }
+    }    
+    //=========================================================
+    //  PROPERTIES / CONFIGURATION
+    //=========================================================    
+    
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public String getConnectionProperties() {
+        return getPoolProperties().getConnectionProperties();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public Properties getDbProperties() {
+        return getPoolProperties().getDbProperties();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public String getDefaultCatalog() {
+        return getPoolProperties().getDefaultCatalog();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public int getDefaultTransactionIsolation() {
+        return getPoolProperties().getDefaultTransactionIsolation();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public String getDriverClassName() {
+        return getPoolProperties().getDriverClassName();
+    }
+
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public int getInitialSize() {
+        return getPoolProperties().getInitialSize();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public String getInitSQL() {
+        return getPoolProperties().getInitSQL();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public String getJdbcInterceptors() {
+        return getPoolProperties().getJdbcInterceptors();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public int getMaxActive() {
+        return getPoolProperties().getMaxActive();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public int getMaxIdle() {
+        return getPoolProperties().getMaxIdle();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public int getMaxWait() {
+        return getPoolProperties().getMaxWait();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public int getMinEvictableIdleTimeMillis() {
+        return getPoolProperties().getMinEvictableIdleTimeMillis();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public int getMinIdle() {
+        return getPoolProperties().getMinIdle();
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public long getMaxAge() {
+        return getPoolProperties().getMaxAge();
+    }    
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public String getName() {
+        return getPoolProperties().getName();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public int getNumTestsPerEvictionRun() {
+        return getPoolProperties().getNumTestsPerEvictionRun();
+    }
+
+    /**
+     * @return DOES NOT RETURN THE PASSWORD, IT WOULD SHOW UP IN JMX
+     */
+    public String getPassword() {
+        return "Password not available as DataSource/JMX operation.";
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public int getRemoveAbandonedTimeout() {
+        return getPoolProperties().getRemoveAbandonedTimeout();
+    }
+
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public int getTimeBetweenEvictionRunsMillis() {
+        return getPoolProperties().getTimeBetweenEvictionRunsMillis();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public String getUrl() {
+        return getPoolProperties().getUrl();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public String getUsername() {
+        return getPoolProperties().getUsername();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public long getValidationInterval() {
+        return getPoolProperties().getValidationInterval();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public String getValidationQuery() {
+        return getPoolProperties().getValidationQuery();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    
+    public String getValidatorClassName() {
+        return getPoolProperties().getValidatorClassName();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    
+    public Validator getValidator() {
+        return getPoolProperties().getValidator();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public boolean isAccessToUnderlyingConnectionAllowed() {
+        return getPoolProperties().isAccessToUnderlyingConnectionAllowed();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public Boolean isDefaultAutoCommit() {
+        return getPoolProperties().isDefaultAutoCommit();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public Boolean isDefaultReadOnly() {
+        return getPoolProperties().isDefaultReadOnly();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public boolean isLogAbandoned() {
+        return getPoolProperties().isLogAbandoned();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public boolean isPoolSweeperEnabled() {
+        return getPoolProperties().isPoolSweeperEnabled();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public boolean isRemoveAbandoned() {
+        return getPoolProperties().isRemoveAbandoned();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public int getAbandonWhenPercentageFull() {
+        return getPoolProperties().getAbandonWhenPercentageFull();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public boolean isTestOnBorrow() {
+        return getPoolProperties().isTestOnBorrow();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public boolean isTestOnConnect() {
+        return getPoolProperties().isTestOnConnect();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public boolean isTestOnReturn() {
+        return getPoolProperties().isTestOnReturn();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public boolean isTestWhileIdle() {
+        return getPoolProperties().isTestWhileIdle();
+    }
+
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public Boolean getDefaultAutoCommit() {
+        return getPoolProperties().getDefaultAutoCommit();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public Boolean getDefaultReadOnly() {
+        return getPoolProperties().getDefaultReadOnly();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public InterceptorDefinition[] getJdbcInterceptorsAsArray() {
+        return getPoolProperties().getJdbcInterceptorsAsArray();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public boolean getUseLock() {
+        return getPoolProperties().getUseLock();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public boolean isFairQueue() {
+        return getPoolProperties().isFairQueue();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public boolean isJmxEnabled() {
+        return getPoolProperties().isJmxEnabled();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public boolean isUseEquals() {
+        return getPoolProperties().isUseEquals();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setAbandonWhenPercentageFull(int percentage) {
+        getPoolProperties().setAbandonWhenPercentageFull(percentage);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setAccessToUnderlyingConnectionAllowed(boolean accessToUnderlyingConnectionAllowed) {
+        getPoolProperties().setAccessToUnderlyingConnectionAllowed(accessToUnderlyingConnectionAllowed);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setDbProperties(Properties dbProperties) {
+        getPoolProperties().setDbProperties(dbProperties);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setDefaultReadOnly(Boolean defaultReadOnly) {
+        getPoolProperties().setDefaultReadOnly(defaultReadOnly);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setMaxAge(long maxAge) {
+        getPoolProperties().setMaxAge(maxAge);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setName(String name) {
+        getPoolProperties().setName(name);
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public void setDataSource(Object ds) {
+        getPoolProperties().setDataSource(ds);
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public Object getDataSource() {
+        return getPoolProperties().getDataSource();
+    }
+    
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public void setDataSourceJNDI(String jndiDS) {
+        getPoolProperties().setDataSourceJNDI(jndiDS);
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public String getDataSourceJNDI() {
+        return getPoolProperties().getDataSourceJNDI();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    public boolean isAlternateUsernameAllowed() {
+        return getPoolProperties().isAlternateUsernameAllowed();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    public void setAlternateUsernameAllowed(boolean alternateUsernameAllowed) {
+        getPoolProperties().setAlternateUsernameAllowed(alternateUsernameAllowed);
+    }
+    
+}
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/FairBlockingQueue.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/FairBlockingQueue.java
new file mode 100644 (file)
index 0000000..ea56e86
--- /dev/null
@@ -0,0 +1,512 @@
+/*
+ * 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.pool;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.NoSuchElementException;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ *
+ * A simple implementation of a blocking queue with fairness waiting.
+ * invocations to method poll(...) will get handed out in the order they were received.
+ * Locking is fine grained, a shared lock is only used during the first level of contention, waiting is done in a 
+ * lock per thread basis so that order is guaranteed once the thread goes into a suspended monitor state.
+ * <br/>
+ * Not all of the methods of the {@link java.util.concurrent.BlockingQueue} are implemented.
+ * @author Filip Hanik
+ *
+ */
+
+public class FairBlockingQueue<E> implements BlockingQueue<E> {
+    
+    /**
+     * This little sucker is used to reorder the way to do 
+     * {@link java.util.concurrent.locks.Lock#lock()},
+     * {@link java.util.concurrent.locks.Lock#unlock()}
+     * and 
+     * {@link java.util.concurrent.CountDownLatch#countDown()}
+     * during the {@link #poll(long, TimeUnit)} operation.
+     * On Linux, it performs much better if we count down while we hold the global
+     * lock, on Solaris its the other way around.
+     * Until we have tested other platforms we only check for Linux.
+     */
+    final static boolean isLinux = "Linux".equals(System.getProperty("os.name")) &&
+                                   (!Boolean.getBoolean(FairBlockingQueue.class.getName()+".ignoreOS"));
+    
+    /**
+     * Phase one entry lock in order to give out 
+     * per-thread-locks for the waiting phase we have 
+     * a phase one lock during the contention period.
+     */
+    final ReentrantLock lock = new ReentrantLock(false);
+
+    /**
+     * All the objects in the pool are stored in a simple linked list
+     */
+    final LinkedList<E> items;
+
+    /**
+     * All threads waiting for an object are stored in a linked list
+     */
+    final LinkedList<ExchangeCountDownLatch<E>> waiters;
+    
+    /**
+     * Creates a new fair blocking queue.
+     */
+    public FairBlockingQueue() {
+        items = new LinkedList<E>();
+        waiters = new LinkedList<ExchangeCountDownLatch<E>>();
+    }
+
+    //------------------------------------------------------------------
+    // USED BY CONPOOL IMPLEMENTATION
+    //------------------------------------------------------------------
+    /**
+     * Will always return true, queue is unbounded.
+     * {@inheritDoc}
+     */
+    public boolean offer(E e) {
+        //during the offer, we will grab the main lock
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        ExchangeCountDownLatch<E> c = null;
+        try {
+            //check to see if threads are waiting for an object
+            if (waiters.size() > 0) {
+                //if threads are waiting grab the latch for that thread
+                c = waiters.poll();
+                //give the object to the thread instead of adding it to the pool
+                c.setItem(e);
+                if (isLinux) c.countDown();
+            } else {
+                //we always add first, so that the most recently used object will be given out
+                items.addFirst(e);
+            }
+        } finally {
+            lock.unlock();
+        }
+        //if we exchanged an object with another thread, wake it up.
+        if (!isLinux && c!=null) c.countDown();
+        //we have an unbounded queue, so always return true
+        return true;
+    }
+
+    /**
+     * Will never timeout, as it invokes the {@link #offer(Object)} method.
+     * Once a lock has been acquired, the  
+     * {@inheritDoc}
+     */
+    public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException {
+        return offer(e);
+    }
+
+    /**
+     * Fair retrieval of an object in the queue.
+     * Objects are returned in the order the threads requested them.
+     * {@inheritDoc}
+     */
+    public E poll(long timeout, TimeUnit unit) throws InterruptedException {
+        E result = null;
+        final ReentrantLock lock = this.lock;
+        boolean error = true;
+        //acquire the global lock until we know what to do
+        lock.lock();
+        try {
+            //check to see if we have objects
+            result = items.poll();
+            if (result==null && timeout>0) {
+                //the queue is empty we will wait for an object
+                ExchangeCountDownLatch<E> c = new ExchangeCountDownLatch<E>(1);
+                //add to the bottom of the wait list
+                waiters.addLast(c);
+                //unlock the global lock
+                lock.unlock();
+                //wait for the specified timeout
+                if (!c.await(timeout, unit)) {
+                    //if we timed out, remove ourselves from the waitlist
+                    lock.lock();
+                    waiters.remove(c);
+                    lock.unlock();
+                }
+                //return the item we received, can be null if we timed out
+                result = c.getItem();
+            } else {
+                //we have an object, release
+                lock.unlock();
+            }
+            error = false;
+        } finally {
+            if (error && lock.isHeldByCurrentThread()) {
+                lock.unlock();
+            }
+        }
+        return result;
+    }
+    
+    /**
+     * Request an item from the queue asynchronously
+     * @return - a future pending the result from the queue poll request
+     */
+    public Future<E> pollAsync() {
+        Future<E> result = null;
+        final ReentrantLock lock = this.lock;
+        boolean error = true;
+        //grab the global lock
+        lock.lock();
+        try {
+            //check to see if we have objects in the queue
+            E item = items.poll();
+            if (item==null) {
+                //queue is empty, add ourselves as waiters
+                ExchangeCountDownLatch<E> c = new ExchangeCountDownLatch<E>(1);
+                waiters.addLast(c);
+                lock.unlock();
+                //return a future that will wait for the object
+                result = new ItemFuture<E>(c);
+            } else {
+                lock.unlock();
+                //return a future with the item
+                result = new ItemFuture<E>(item);
+            }
+            error = false;
+        } finally {
+            if (error && lock.isHeldByCurrentThread()) {
+                lock.unlock();
+            }
+        }
+        return result;
+    }
+    
+    /**
+     * {@inheritDoc}
+     */
+    public boolean remove(Object e) {
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            return items.remove(e);
+        } finally {
+            lock.unlock();
+        }
+    }
+    
+    /**
+     * {@inheritDoc}
+     */
+    public int size() {
+        return items.size();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Iterator<E> iterator() {
+        return new FairIterator();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public E poll() {
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            return items.poll();
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean contains(Object e) {
+        final ReentrantLock lock = this.lock;
+        lock.lock();
+        try {
+            return items.contains(e);
+        } finally {
+            lock.unlock();
+        }
+    }
+
+
+    //------------------------------------------------------------------
+    // NOT USED BY CONPOOL IMPLEMENTATION
+    //------------------------------------------------------------------
+    /**
+     * {@inheritDoc}
+     */
+    public boolean add(E e) {
+        return offer(e);
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws UnsupportedOperationException - this operation is not supported
+     */
+    public int drainTo(Collection<? super E> c, int maxElements) {
+        throw new UnsupportedOperationException("int drainTo(Collection<? super E> c, int maxElements)");
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws UnsupportedOperationException - this operation is not supported
+     */
+    
+    public int drainTo(Collection<? super E> c) {
+        return drainTo(c,Integer.MAX_VALUE);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void put(E e) throws InterruptedException {
+        offer(e);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int remainingCapacity() {
+        return Integer.MAX_VALUE - size();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public E take() throws InterruptedException {
+        return this.poll(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean addAll(Collection<? extends E> c) {
+        Iterator<? extends E> i = c.iterator();
+        while (i.hasNext()) {
+            E e = i.next();
+            offer(e);
+        }
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws UnsupportedOperationException - this operation is not supported
+     */
+    public void clear() {
+        throw new UnsupportedOperationException("void clear()");
+
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws UnsupportedOperationException - this operation is not supported
+     */
+    public boolean containsAll(Collection<?> c) {
+        throw new UnsupportedOperationException("boolean containsAll(Collection<?> c)");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isEmpty() {
+        return size() == 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws UnsupportedOperationException - this operation is not supported
+     */
+    public boolean removeAll(Collection<?> c) {
+        throw new UnsupportedOperationException("boolean removeAll(Collection<?> c)");
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws UnsupportedOperationException - this operation is not supported
+     */
+    public boolean retainAll(Collection<?> c) {
+        throw new UnsupportedOperationException("boolean retainAll(Collection<?> c)");
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws UnsupportedOperationException - this operation is not supported
+     */
+    public Object[] toArray() {
+        throw new UnsupportedOperationException("Object[] toArray()");
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws UnsupportedOperationException - this operation is not supported
+     */
+    public <T> T[] toArray(T[] a) {
+        throw new UnsupportedOperationException("<T> T[] toArray(T[] a)");
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws UnsupportedOperationException - this operation is not supported
+     */
+    public E element() {
+        throw new UnsupportedOperationException("E element()");
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws UnsupportedOperationException - this operation is not supported
+     */
+    public E peek() {
+        throw new UnsupportedOperationException("E peek()");
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws UnsupportedOperationException - this operation is not supported
+     */
+    public E remove() {
+        throw new UnsupportedOperationException("E remove()");
+    }
+
+
+
+    //------------------------------------------------------------------
+    // Non cancellable Future used to check and see if a connection has been made available
+    //------------------------------------------------------------------
+    protected class ItemFuture<T> implements Future<T> {
+        protected volatile T item = null;
+        protected volatile ExchangeCountDownLatch<T> latch = null;
+        protected volatile boolean canceled = false;
+        
+        public ItemFuture(T item) {
+            this.item = item;
+        }
+        
+        public ItemFuture(ExchangeCountDownLatch<T> latch) {
+            this.latch = latch;
+        }
+        
+        public boolean cancel(boolean mayInterruptIfRunning) {
+            return false; //don't allow cancel for now
+        }
+
+        public T get() throws InterruptedException, ExecutionException {
+            if (item!=null) {
+                return item;
+            } else if (latch!=null) {
+                latch.await();
+                return latch.getItem();
+            } else {
+                throw new ExecutionException("ItemFuture incorrectly instantiated. Bug in the code?", new Exception());
+            }
+        }
+
+        public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+            if (item!=null) {
+                return item;
+            } else if (latch!=null) {
+                boolean timedout = !latch.await(timeout, unit);
+                if (timedout) throw new TimeoutException();
+                else return latch.getItem();
+            } else {
+                throw new ExecutionException("ItemFuture incorrectly instantiated. Bug in the code?", new Exception());
+            }
+        }
+
+        public boolean isCancelled() {
+            return false;
+        }
+
+        public boolean isDone() {
+            return (item!=null || latch.getItem()!=null);
+        }
+        
+    }
+
+    //------------------------------------------------------------------
+    // Count down latch that can be used to exchange information
+    //------------------------------------------------------------------
+    protected class ExchangeCountDownLatch<T> extends CountDownLatch {
+        protected volatile T item;
+        public ExchangeCountDownLatch(int i) {
+            super(i);
+        }
+        public T getItem() {
+            return item;
+        }
+        public void setItem(T item) {
+            this.item = item;
+        }
+    }
+
+    //------------------------------------------------------------------
+    // Iterator safe from concurrent modification exceptions
+    //------------------------------------------------------------------
+    protected class FairIterator implements Iterator<E> {
+        E[] elements = null;
+        int index;
+        E element = null;
+
+        public FairIterator() {
+            final ReentrantLock lock = FairBlockingQueue.this.lock;
+            lock.lock();
+            try {
+                elements = (E[]) new Object[FairBlockingQueue.this.items.size()];
+                FairBlockingQueue.this.items.toArray(elements);
+                index = 0;
+            } finally {
+                lock.unlock();
+            }
+        }
+        public boolean hasNext() {
+            return index<elements.length;
+        }
+
+        public E next() {
+            if (!hasNext()) {
+                throw new NoSuchElementException();
+            }
+            element = elements[index++];
+            return element;
+        }
+
+        public void remove() {
+            final ReentrantLock lock = FairBlockingQueue.this.lock;
+            lock.lock();
+            try {
+                if (element!=null) {
+                    FairBlockingQueue.this.items.remove(element);
+                }
+            } finally {
+                lock.unlock();
+            }
+        }
+
+    }
+}
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/JdbcInterceptor.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/JdbcInterceptor.java
new file mode 100644 (file)
index 0000000..8d8096c
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * 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.pool;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.Map;
+
+import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty;
+
+/**
+ * Abstract class that is to be extended for implementations of interceptors.
+ * Everytime an operation is called on the {@link java.sql.Connection} object the 
+ * {@link #invoke(Object, Method, Object[])} method on the interceptor will be called.
+ * Interceptors are useful to change or improve behavior of the connection pool.<br/>
+ * Interceptors can receive a set of properties. Each sub class is responsible for parsing the properties during runtime when they 
+ * are needed or simply override the {@link #setProperties(Map)} method. 
+ * Properties arrive in a key-value pair of Strings as they were received through the configuration.
+ * This method is called once per cached connection object when the object is first configured.
+ * 
+ * @author Filip Hanik
+ * @version 1.0
+ */
+public abstract class JdbcInterceptor implements InvocationHandler {
+    /**
+     * {@link java.sql.Connection#close()} method name
+     */
+    public static final String CLOSE_VAL = "close";
+    /**
+     * {@link Object#toString()} method name
+     */
+    public static final String TOSTRING_VAL = "toString";
+    /**
+     * {@link java.sql.Connection#isClosed()} method name
+     */
+    public static final String ISCLOSED_VAL = "isClosed";
+    /**
+     * {@link javax.sql.PooledConnection#getConnection()} method name
+     */
+    public static final String GETCONNECTION_VAL = "getConnection";
+    /**
+     * {@link java.sql.Wrapper#unwrap(Class)} method name
+     */
+    public static final String UNWRAP_VAL = "unwrap";
+    /**
+     * {@link java.sql.Wrapper#isWrapperFor(Class)} method name
+     */
+    public static final String ISWRAPPERFOR_VAL = "isWrapperFor";
+
+    
+    /**
+     * Properties for this interceptor.
+     */
+    protected Map<String,InterceptorProperty> properties = null; 
+    
+    /**
+     * The next interceptor in the chain
+     */
+    private JdbcInterceptor next = null;
+    /**
+     * Property that decides how we do string comparison, default is to use
+     * {@link String#equals(Object)}. If set to <code>false</code> then the
+     * equality operator (==) is used.
+     */
+    private boolean useEquals = true;
+
+    /**
+     * Public constructor for instantation through reflection
+     */
+    public JdbcInterceptor() {
+        // NOOP
+    }
+
+    /**
+     * Gets invoked each time an operation on {@link java.sql.Connection} is invoked.
+     * {@inheritDoc}
+     */
+    
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+        if (getNext()!=null) return getNext().invoke(this,method,args);
+        else throw new NullPointerException();
+    }
+
+    /**
+     * Returns the next interceptor in the chain
+     * @return the next interceptor in the chain
+     */
+    public JdbcInterceptor getNext() {
+        return next;
+    }
+
+    /**
+     * configures the next interceptor in the chain
+     * @param next
+     */
+    public void setNext(JdbcInterceptor next) {
+        this.next = next;
+    }
+    
+    /**
+     * Performs a string comparison, using references unless the useEquals property is set to true.
+     * @param name1
+     * @param name2
+     * @return true if name1 is equal to name2 based on {@link #useEquals}
+     */
+    public boolean compare(String name1, String name2) {
+        if (isUseEquals()) {
+            return name1.equals(name2);
+        } else {
+            return name1==name2;
+        }
+    }
+    
+    /**
+     * Compares a method name (String) to a method (Method)
+     * {@link #compare(String,String)}
+     * Uses reference comparison unless the useEquals property is set to true
+     * @param methodName
+     * @param method
+     * @return true if the name matches
+     */
+    public boolean compare(String methodName, Method method) {
+        return compare(methodName, method.getName());
+    }
+    
+    /**
+     * Gets called each time the connection is borrowed from the pool
+     * This means that if an interceptor holds a reference to the connection
+     * the interceptor can be reused for another connection.
+     * <br/>
+     * This method may be called with null as both arguments when we are closing down the connection.
+     * @param parent - the connection pool owning the connection
+     * @param con - the pooled connection
+     */
+    public abstract void reset(ConnectionPool parent, PooledConnection con);
+    
+    /**
+     * Called when {@link java.sql.Connection#close()} is called on the underlying connection.
+     * This is to notify the interceptors, that the physical connection has been released.
+     * Implementation of this method should be thought through with care, as no actions should trigger an exception.
+     * @param parent - the connection pool that this connection belongs to
+     * @param con    - the pooled connection that holds this connection
+     * @param finalizing - if this connection is finalizing. True means that the pooled connection will not reconnect the underlying connection
+     */
+    public void disconnected(ConnectionPool parent, PooledConnection con, boolean finalizing) {
+    }
+        
+    
+    /**
+     * Returns the properties configured for this interceptor
+     * @return the configured properties for this interceptor
+     */
+    public Map<String,InterceptorProperty> getProperties() {
+        return properties;
+    }
+
+    /**
+     * Called during the creation of an interceptor
+     * The properties can be set during the configuration of an interceptor
+     * Override this method to perform type casts between string values and object properties
+     * @param properties
+     */
+    public void setProperties(Map<String,InterceptorProperty> properties) {
+        this.properties = properties;
+        final String useEquals = "useEquals";
+        InterceptorProperty p = properties.get(useEquals);
+        if (p!=null) {
+            setUseEquals(Boolean.parseBoolean(p.getValue()));
+        }
+    }
+    
+    /**
+     * @return true if the compare method uses the Object.equals(Object) method
+     *         false if comparison is done on a reference level
+     */
+    public boolean isUseEquals() {
+        return useEquals;
+    }
+    
+    /**
+     * Set to true if string comparisons (for the {@link #compare(String, Method)} and {@link #compare(String, String)} methods) should use the Object.equals(Object) method
+     * The default is false
+     * @param useEquals
+     */
+    public void setUseEquals(boolean useEquals) {
+        this.useEquals = useEquals;
+    }
+    
+    /**
+     * This method is invoked by a connection pool when the pool is closed.
+     * Interceptor classes can override this method if they keep static
+     * variables or other tracking means around.
+     * <b>This method is only invoked on a single instance of the interceptor, and not on every instance created.</b>
+     * @param pool - the pool that is being closed.
+     */
+    public void poolClosed(ConnectionPool pool) {
+        // NOOP
+    }
+
+    /**
+     * This method is invoked by a connection pool when the pool is first started up, usually when the first connection is requested.
+     * Interceptor classes can override this method if they keep static
+     * variables or other tracking means around.
+     * <b>This method is only invoked on a single instance of the interceptor, and not on every instance created.</b>
+     * @param pool - the pool that is being closed.
+     */
+    public void poolStarted(ConnectionPool pool) {
+        // NOOP
+    }
+
+}
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/MultiLockFairBlockingQueue.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/MultiLockFairBlockingQueue.java
new file mode 100644 (file)
index 0000000..f5fd28e
--- /dev/null
@@ -0,0 +1,537 @@
+/*
+ * 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.pool;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.NoSuchElementException;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * <b>EXPERIMENTAL AND NOT YET COMPLETE!</b>
+ *
+ *
+ * An implementation of a blocking queue with fairness waiting and lock dispersal to avoid contention.
+ * invocations to method poll(...) will get handed out in the order they were received.
+ * Locking is fine grained, a shared lock is only used during the first level of contention, waiting is done in a 
+ * lock per thread basis so that order is guaranteed once the thread goes into a suspended monitor state.
+ * <br/>
+ * Not all of the methods of the {@link java.util.concurrent.BlockingQueue} are implemented.
+ * @author Filip Hanik
+ *
+ */
+
+public class MultiLockFairBlockingQueue<E> implements BlockingQueue<E> {
+    
+    final int LOCK_COUNT = Runtime.getRuntime().availableProcessors();
+    
+    final AtomicInteger putQueue = new AtomicInteger(0);
+    final AtomicInteger pollQueue = new AtomicInteger(0);
+    
+    public int getNextPut() {
+        int idx = Math.abs(putQueue.incrementAndGet()) % LOCK_COUNT;
+        return idx;
+    }
+    
+    public int getNextPoll() {
+        int idx = Math.abs(pollQueue.incrementAndGet()) % LOCK_COUNT;
+        return idx;
+    }
+    /**
+     * Phase one entry lock in order to give out 
+     * per-thread-locks for the waiting phase we have 
+     * a phase one lock during the contention period.
+     */
+    private final ReentrantLock[] locks = new ReentrantLock[LOCK_COUNT];
+
+    /**
+     * All the objects in the pool are stored in a simple linked list
+     */
+    final LinkedList<E>[] items;
+
+    /**
+     * All threads waiting for an object are stored in a linked list
+     */
+    final LinkedList<ExchangeCountDownLatch<E>>[] waiters;
+    
+    /**
+     * Creates a new fair blocking queue.
+     */
+    public MultiLockFairBlockingQueue() {
+        items = new LinkedList[LOCK_COUNT];
+        waiters = new LinkedList[LOCK_COUNT];
+        for (int i=0; i<LOCK_COUNT; i++) {
+            items[i] = new LinkedList<E>();
+            waiters[i] = new LinkedList<ExchangeCountDownLatch<E>>();
+            locks[i] = new ReentrantLock(false);
+        }
+    }
+
+    //------------------------------------------------------------------
+    // USED BY CONPOOL IMPLEMENTATION
+    //------------------------------------------------------------------
+    /**
+     * Will always return true, queue is unbounded.
+     * {@inheritDoc}
+     */
+    public boolean offer(E e) {
+        int idx = getNextPut();
+        //during the offer, we will grab the main lock
+        final ReentrantLock lock = this.locks[idx];
+        lock.lock();
+        ExchangeCountDownLatch<E> c = null;
+        try {
+            //check to see if threads are waiting for an object
+            if (waiters[idx].size() > 0) {
+                //if threads are waiting grab the latch for that thread
+                c = waiters[idx].poll();
+                //give the object to the thread instead of adding it to the pool
+                c.setItem(e);
+            } else {
+                //we always add first, so that the most recently used object will be given out
+                items[idx].addFirst(e);
+            }
+        } finally {
+            lock.unlock();
+        }
+        //if we exchanged an object with another thread, wake it up.
+        if (c!=null) c.countDown();
+        //we have an unbounded queue, so always return true
+        return true;
+    }
+
+    /**
+     * Will never timeout, as it invokes the {@link #offer(Object)} method.
+     * Once a lock has been acquired, the  
+     * {@inheritDoc}
+     */
+    public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException {
+        return offer(e);
+    }
+
+    /**
+     * Fair retrieval of an object in the queue.
+     * Objects are returned in the order the threads requested them.
+     * {@inheritDoc}
+     */
+    public E poll(long timeout, TimeUnit unit) throws InterruptedException {
+        int idx = getNextPoll();
+        E result = null;
+        final ReentrantLock lock = this.locks[idx];
+        boolean error = true;
+        //acquire the global lock until we know what to do
+        lock.lock();
+        try {
+            //check to see if we have objects
+            result = items[idx].poll();
+            if (result==null && timeout>0) {
+                //the queue is empty we will wait for an object
+                ExchangeCountDownLatch<E> c = new ExchangeCountDownLatch<E>(1);
+                //add to the bottom of the wait list
+                waiters[idx].addLast(c);
+                //unlock the global lock
+                lock.unlock();
+                //wait for the specified timeout
+                if (!c.await(timeout, unit)) {
+                    //if we timed out, remove ourselves from the waitlist
+                    lock.lock();
+                    waiters[idx].remove(c);
+                    lock.unlock();
+                }
+                //return the item we received, can be null if we timed out
+                result = c.getItem();
+            } else {
+                //we have an object, release
+                lock.unlock();
+            }
+            error = false;
+        } finally {
+            if (error && lock.isHeldByCurrentThread()) {
+                lock.unlock();
+            }
+        }
+        return result;
+    }
+    
+    /**
+     * Request an item from the queue asynchronously
+     * @return - a future pending the result from the queue poll request
+     */
+    public Future<E> pollAsync() {
+        int idx = getNextPoll();
+        Future<E> result = null;
+        final ReentrantLock lock = this.locks[idx];
+        boolean error = true;
+        //grab the global lock
+        lock.lock();
+        try {
+            //check to see if we have objects in the queue
+            E item = items[idx].poll();
+            if (item==null) {
+                //queue is empty, add ourselves as waiters
+                ExchangeCountDownLatch<E> c = new ExchangeCountDownLatch<E>(1);
+                waiters[idx].addLast(c);
+                lock.unlock();
+                //return a future that will wait for the object
+                result = new ItemFuture<E>(c);
+            } else {
+                lock.unlock();
+                //return a future with the item
+                result = new ItemFuture<E>(item);
+            }
+            error = false;
+        } finally {
+            if (error && lock.isHeldByCurrentThread()) {
+                lock.unlock();
+            }
+        }
+        return result;
+    }
+    
+    /**
+     * {@inheritDoc}
+     */
+    public boolean remove(Object e) {
+        for (int idx=0; idx<LOCK_COUNT; idx++) {
+            final ReentrantLock lock = this.locks[idx];
+            lock.lock();
+            try {
+                boolean result = items[idx].remove(e);
+                if (result) return result;
+            } finally {
+                lock.unlock();
+            }
+        }
+        return false;
+    }
+    
+    /**
+     * {@inheritDoc}
+     */
+    public int size() {
+        int size = 0;
+        for (int idx=0; idx<LOCK_COUNT; idx++) {
+            size += items[idx].size();
+        }
+        return size;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Iterator<E> iterator() {
+        return new FairIterator();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public E poll() {
+        int idx = getNextPoll();
+        final ReentrantLock lock = this.locks[idx];
+        lock.lock();
+        try {
+            return items[idx].poll();
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean contains(Object e) {
+        for (int idx=0; idx<LOCK_COUNT; idx++) {
+            boolean result = items[idx].contains(e);
+            if (result) return result;
+        }
+        return false;
+    }
+
+
+    //------------------------------------------------------------------
+    // NOT USED BY CONPOOL IMPLEMENTATION
+    //------------------------------------------------------------------
+    /**
+     * {@inheritDoc}
+     */
+    public boolean add(E e) {
+        return offer(e);
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws UnsupportedOperationException - this operation is not supported
+     */
+    public int drainTo(Collection<? super E> c, int maxElements) {
+        throw new UnsupportedOperationException("int drainTo(Collection<? super E> c, int maxElements)");
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws UnsupportedOperationException - this operation is not supported
+     */
+    public int drainTo(Collection<? super E> c) {
+        return drainTo(c,Integer.MAX_VALUE);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void put(E e) throws InterruptedException {
+        offer(e);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int remainingCapacity() {
+        return Integer.MAX_VALUE - size();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public E take() throws InterruptedException {
+        return this.poll(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean addAll(Collection<? extends E> c) {
+        Iterator<? extends E> i = c.iterator();
+        while (i.hasNext()) {
+            E e = i.next();
+            offer(e);
+        }
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws UnsupportedOperationException - this operation is not supported
+     */
+    public void clear() {
+        throw new UnsupportedOperationException("void clear()");
+
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws UnsupportedOperationException - this operation is not supported
+     */
+    public boolean containsAll(Collection<?> c) {
+        throw new UnsupportedOperationException("boolean containsAll(Collection<?> c)");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isEmpty() {
+        return size() == 0;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws UnsupportedOperationException - this operation is not supported
+     */
+    public boolean removeAll(Collection<?> c) {
+        throw new UnsupportedOperationException("boolean removeAll(Collection<?> c)");
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws UnsupportedOperationException - this operation is not supported
+     */
+    public boolean retainAll(Collection<?> c) {
+        throw new UnsupportedOperationException("boolean retainAll(Collection<?> c)");
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws UnsupportedOperationException - this operation is not supported
+     */
+    public Object[] toArray() {
+        throw new UnsupportedOperationException("Object[] toArray()");
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws UnsupportedOperationException - this operation is not supported
+     */
+    public <T> T[] toArray(T[] a) {
+        throw new UnsupportedOperationException("<T> T[] toArray(T[] a)");
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws UnsupportedOperationException - this operation is not supported
+     */
+    public E element() {
+        throw new UnsupportedOperationException("E element()");
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws UnsupportedOperationException - this operation is not supported
+     */
+    public E peek() {
+        throw new UnsupportedOperationException("E peek()");
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws UnsupportedOperationException - this operation is not supported
+     */
+    public E remove() {
+        throw new UnsupportedOperationException("E remove()");
+    }
+
+
+
+    //------------------------------------------------------------------
+    // Non cancellable Future used to check and see if a connection has been made available
+    //------------------------------------------------------------------
+    protected class ItemFuture<T> implements Future<T> {
+        protected volatile T item = null;
+        protected volatile ExchangeCountDownLatch<T> latch = null;
+        protected volatile boolean canceled = false;
+        
+        public ItemFuture(T item) {
+            this.item = item;
+        }
+        
+        public ItemFuture(ExchangeCountDownLatch<T> latch) {
+            this.latch = latch;
+        }
+        
+        public boolean cancel(boolean mayInterruptIfRunning) {
+            return false; //don't allow cancel for now
+        }
+
+        public T get() throws InterruptedException, ExecutionException {
+            if (item!=null) {
+                return item;
+            } else if (latch!=null) {
+                latch.await();
+                return latch.getItem();
+            } else {
+                throw new ExecutionException("ItemFuture incorrectly instantiated. Bug in the code?", new Exception());
+            }
+        }
+
+        public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+            if (item!=null) {
+                return item;
+            } else if (latch!=null) {
+                boolean timedout = !latch.await(timeout, unit);
+                if (timedout) throw new TimeoutException();
+                else return latch.getItem();
+            } else {
+                throw new ExecutionException("ItemFuture incorrectly instantiated. Bug in the code?", new Exception());
+            }
+        }
+
+        public boolean isCancelled() {
+            return false;
+        }
+
+        public boolean isDone() {
+            return (item!=null || latch.getItem()!=null);
+        }
+        
+    }
+
+    //------------------------------------------------------------------
+    // Count down latch that can be used to exchange information
+    //------------------------------------------------------------------
+    protected class ExchangeCountDownLatch<T> extends CountDownLatch {
+        protected volatile T item;
+        public ExchangeCountDownLatch(int i) {
+            super(i);
+        }
+        public T getItem() {
+            return item;
+        }
+        public void setItem(T item) {
+            this.item = item;
+        }
+    }
+
+    //------------------------------------------------------------------
+    // Iterator safe from concurrent modification exceptions
+    //------------------------------------------------------------------
+    protected class FairIterator implements Iterator<E> {
+        E[] elements = null;
+        int index;
+        E element = null;
+
+        public FairIterator() {
+            ArrayList<E> list = new ArrayList<E>(MultiLockFairBlockingQueue.this.size());
+            for (int idx=0; idx<LOCK_COUNT; idx++) {
+                final ReentrantLock lock = MultiLockFairBlockingQueue.this.locks[idx];
+                lock.lock();
+                try {
+                    elements = (E[]) new Object[MultiLockFairBlockingQueue.this.items[idx].size()];
+                    MultiLockFairBlockingQueue.this.items[idx].toArray(elements);
+                    
+                } finally {
+                    lock.unlock();
+                }
+            }
+            index = 0;
+            elements = (E[]) new Object[list.size()];
+            list.toArray(elements);
+        }
+        public boolean hasNext() {
+            return index<elements.length;
+        }
+
+        public E next() {
+            if (!hasNext()) {
+                throw new NoSuchElementException();
+            }
+            element = elements[index++];
+            return element;
+        }
+
+        public void remove() {
+            for (int idx=0; idx<LOCK_COUNT; idx++) {
+                final ReentrantLock lock = MultiLockFairBlockingQueue.this.locks[idx];
+                lock.lock();
+                try {
+                    boolean result = MultiLockFairBlockingQueue.this.items[idx].remove(elements[index]);
+                    if (result) break;
+                } finally {
+                    lock.unlock();
+                }
+            }
+            
+        }
+
+    }
+}
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolConfiguration.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolConfiguration.java
new file mode 100644 (file)
index 0000000..b8d2515
--- /dev/null
@@ -0,0 +1,791 @@
+/*
+ * 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.pool;
+
+import java.util.Properties;
+
+import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorDefinition;
+
+/**
+ * A list of properties that are configurable for a connection pool.
+ * The {@link DataSource} object also implements this interface so that it can be easily configured through
+ * an IoC container without having to specify a secondary object with a setter method.
+ * @author fhanik
+ *
+ */
+
+public interface PoolConfiguration {
+
+    /**
+     * JMX prefix for interceptors that register themselves with JMX
+     */
+    public static final String PKG_PREFIX = "org.apache.tomcat.jdbc.pool.interceptor.";
+
+    /**
+     * Connections that have been abandoned (timed out) wont get closed and reported up unless the number of connections in use are 
+     * above the percentage defined by abandonWhenPercentageFull. 
+     * The value should be between 0-100. 
+     * The default value is 0, which implies that connections are eligible for 
+     * closure as soon as removeAbandonedTimeout has been reached.
+     * @param percentage a value between 0 and 100 to indicate when connections that have been abandoned/timed out are considered abandoned
+     */
+    public void setAbandonWhenPercentageFull(int percentage);
+
+    /**
+     * Connections that have been abandoned (timed out) wont get closed and reported up unless the number of connections in use are 
+     * above the percentage defined by abandonWhenPercentageFull. 
+     * The value should be between 0-100. 
+     * The default value is 0, which implies that connections are eligible for 
+     * closure as soon as removeAbandonedTimeout has been reached.
+     * @return percentage - a value between 0 and 100 to indicate when connections that have been abandoned/timed out are considered abandoned
+     */
+    public int getAbandonWhenPercentageFull();
+
+    /**
+     * Returns true if a fair queue is being used by the connection pool
+     * @return true if a fair waiting queue is being used
+     */
+    public boolean isFairQueue();
+
+    /**
+     * Set to true if you wish that calls to getConnection 
+     * should be treated fairly in a true FIFO fashion. 
+     * This uses the {@link FairBlockingQueue} implementation for the list of the idle connections. 
+     * The default value is true. 
+     * This flag is required when you want to use asynchronous connection retrieval.
+     * @param fairQueue
+     */
+    public void setFairQueue(boolean fairQueue);
+    
+    /**
+     * Property not used. Access is always allowed.
+     * Access can be achieved by calling unwrap on the pooled connection. see {@link javax.sql.DataSource} interface 
+     * or call getConnection through reflection or cast the object as {@link javax.sql.PooledConnection}
+     * @return true
+     */
+    public boolean isAccessToUnderlyingConnectionAllowed();
+
+    /**
+     * No-op
+     * @param accessToUnderlyingConnectionAllowed parameter ignored
+     */
+    public void setAccessToUnderlyingConnectionAllowed(boolean accessToUnderlyingConnectionAllowed);
+    
+    /**
+     * The connection properties that will be sent to the JDBC driver when establishing new connections. 
+     * Format of the string is [propertyName=property;] <br/>
+     * NOTE - The "user" and "password" properties will be passed explicitly, so they do not need to be included here. 
+     * The default value is null.
+     */
+    public String getConnectionProperties();
+
+    /**
+     * The properties that will be passed into {@link java.sql.Driver#connect(String, Properties)} method.
+     * Username and password do not need to be stored here, they will be passed into the properties right before the connection is established.
+     * @param connectionProperties properties - Format of the string is [propertyName=property;]* 
+     * Example: prop1=value1;prop2=value2
+     */
+    public void setConnectionProperties(String connectionProperties);
+    
+    /**
+     * Returns the database properties that are passed into the {@link java.sql.Driver#connect(String, Properties)} method.
+     * @return database properties that are passed into the {@link java.sql.Driver#connect(String, Properties)} method.
+     */
+    public Properties getDbProperties();
+
+    /**
+     * Overrides the database properties passed into the  {@link java.sql.Driver#connect(String, Properties)} method.
+     * @param dbProperties
+     */
+    public void setDbProperties(Properties dbProperties);
+    
+    /**
+     * The default auto-commit state of connections created by this pool. 
+     * If not set (null), default is JDBC driver default (If set to null then the {@link java.sql.Connection#setAutoCommit(boolean)} method will not be called.)
+     * @return the default auto commit setting, null is Driver default.
+     */
+    public Boolean isDefaultAutoCommit();
+    
+    /**
+     * The default auto-commit state of connections created by this pool. 
+     * If not set (null), default is JDBC driver default (If set to null then the {@link java.sql.Connection#setAutoCommit(boolean)} method will not be called.)
+     * @return the default auto commit setting, null is Driver default.
+     */
+    public Boolean getDefaultAutoCommit();
+    
+    /**
+     * The default auto-commit state of connections created by this pool. 
+     * If not set (null), default is JDBC driver default (If set to null then the {@link java.sql.Connection#setAutoCommit(boolean)} method will not be called.)
+     * @param defaultAutoCommit default auto commit setting, null is Driver default.
+     */
+    public void setDefaultAutoCommit(Boolean defaultAutoCommit);
+
+    /**
+     * If non null, during connection creation the method {@link java.sql.Connection#setCatalog(String)} will be called with the set value.
+     * @return the default catalog, null if not set and accepting the driver default.
+     */
+    public String getDefaultCatalog();
+    
+    /**
+     * If non null, during connection creation the method {@link java.sql.Connection#setCatalog(String)} will be called with the set value.
+     * @param defaultCatalog null if not set and accepting the driver default.
+     */
+    public void setDefaultCatalog(String defaultCatalog);
+    
+    /**
+     * If non null, during connection creation the method {@link java.sql.Connection#setReadOnly(boolean)} will be called with the set value.
+     * @return null if not set and accepting the driver default otherwise the read only value
+     */
+    public Boolean isDefaultReadOnly();
+
+    /**
+     * If non null, during connection creation the method {@link java.sql.Connection#setReadOnly(boolean)} will be called with the set value.
+     * @return null if not set and accepting the driver default otherwise the read only value
+     */
+    public Boolean getDefaultReadOnly();
+
+    /**
+     * If non null, during connection creation the method {@link java.sql.Connection#setReadOnly(boolean)} will be called with the set value.
+     * @param defaultReadOnly null if not set and accepting the driver default.
+     */
+    public void setDefaultReadOnly(Boolean defaultReadOnly);
+
+    
+    /**
+     * Returns the default transaction isolation level. If set to {@link DataSourceFactory#UNKNOWN_TRANSACTIONISOLATION} the method
+     * {@link java.sql.Connection#setTransactionIsolation(int)} will not be called during connection creation.
+     * @return driver transaction isolation level, or -1 {@link DataSourceFactory#UNKNOWN_TRANSACTIONISOLATION} if not set.
+     */
+    public int getDefaultTransactionIsolation();
+    
+    /**
+     * If set to {@link DataSourceFactory#UNKNOWN_TRANSACTIONISOLATION} the method
+     * {@link java.sql.Connection#setTransactionIsolation(int)} will not be called during connection creation. Otherwise the method 
+     * will be called with the isolation level set by this property.
+     * @param defaultTransactionIsolation a value of {@link java.sql.Connection#TRANSACTION_NONE}, {@link java.sql.Connection#TRANSACTION_READ_COMMITTED},
+     * {@link java.sql.Connection#TRANSACTION_READ_UNCOMMITTED}, {@link java.sql.Connection#TRANSACTION_REPEATABLE_READ}, 
+     * {@link java.sql.Connection#TRANSACTION_SERIALIZABLE} or {@link DataSourceFactory#UNKNOWN_TRANSACTIONISOLATION}
+     * The last value will not be set on the connection.
+     */
+    public void setDefaultTransactionIsolation(int defaultTransactionIsolation);
+
+    /**
+     * The fully qualified Java class name of the JDBC driver to be used. The driver has to be accessible from the same classloader as tomcat-jdbc.jar
+     * @return fully qualified JDBC driver name. 
+     */
+    public String getDriverClassName();
+    
+    /**
+     * The fully qualified Java class name of the JDBC driver to be used. The driver has to be accessible from the same classloader as tomcat-jdbc.jar
+     * @param driverClassName a fully qualified Java class name of a {@link java.sql.Driver} implementation.
+     */
+    public void setDriverClassName(String driverClassName);
+    
+    /**
+     * Returns the number of connections that will be established when the connection pool is started.
+     * Default value is 10 
+     * @return number of connections to be started when pool is started
+     */
+    public int getInitialSize();
+    
+    /**
+     * Set the number of connections that will be established when the connection pool is started.
+     * Default value is 10.
+     * If this value exceeds {@link #setMaxActive(int)} it will automatically be lowered. 
+     * @param initialSize the number of connections to be established.
+     * 
+     */
+    public void setInitialSize(int initialSize);
+
+    /**
+     * boolean flag to set if stack traces should be logged for application code which abandoned a Connection. 
+     * Logging of abandoned Connections adds overhead for every Connection borrow because a stack trace has to be generated. 
+     * The default value is false.
+     * @return true if the connection pool logs stack traces when connections are borrowed from the pool.
+     */
+    public boolean isLogAbandoned();
+    
+    /**
+     * boolean flag to set if stack traces should be logged for application code which abandoned a Connection. 
+     * Logging of abandoned Connections adds overhead for every Connection borrow because a stack trace has to be generated. 
+     * The default value is false.
+     * @param logAbandoned set to true if stack traces should be recorded when {@link DataSource#getConnection()} is called.
+     */
+    public void setLogAbandoned(boolean logAbandoned);
+
+    /**
+     * The maximum number of active connections that can be allocated from this pool at the same time. The default value is 100
+     * @return the maximum number of connections used by this pool
+     */
+    public int getMaxActive();
+    
+    /**
+     * The maximum number of active connections that can be allocated from this pool at the same time. The default value is 100
+     * @param maxActive hard limit for number of managed connections by this pool
+     */
+    public void setMaxActive(int maxActive);
+
+    
+    /**
+     * The maximum number of connections that should be kept in the idle pool if {@link #isPoolSweeperEnabled()} returns false.
+     * If the If {@link #isPoolSweeperEnabled()} returns true, then the idle pool can grow up to {@link #getMaxActive}
+     * and will be shrunk according to {@link #getMinEvictableIdleTimeMillis()} setting.
+     * Default value is maxActive:100  
+     * @return the maximum number of idle connections.
+     */
+    public int getMaxIdle();
+    
+    /**
+     * The maximum number of connections that should be kept in the idle pool if {@link #isPoolSweeperEnabled()} returns false.
+     * If the If {@link #isPoolSweeperEnabled()} returns true, then the idle pool can grow up to {@link #getMaxActive}
+     * and will be shrunk according to {@link #getMinEvictableIdleTimeMillis()} setting.
+     * Default value is maxActive:100  
+     * @param maxIdle the maximum size of the idle pool
+     */
+    public void setMaxIdle(int maxIdle);
+
+    /**
+     * The maximum number of milliseconds that the pool will wait (when there are no available connections and the 
+     * {@link #getMaxActive} has been reached) for a connection to be returned 
+     * before throwing an exception. Default value is 30000 (30 seconds)
+     * @return the number of milliseconds to wait for a connection to become available if the pool is maxed out.
+     */
+    public int getMaxWait();
+
+    /**
+     * The maximum number of milliseconds that the pool will wait (when there are no available connections and the 
+     * {@link #getMaxActive} has been reached) for a connection to be returned 
+     * before throwing an exception. Default value is 30000 (30 seconds)
+     * @param maxWait the maximum number of milliseconds to wait.
+     */
+    public void setMaxWait(int maxWait);
+
+    /**
+     * The minimum amount of time an object must sit idle in the pool before it is eligible for eviction. 
+     * The default value is 60000 (60 seconds).
+     * @return the minimum amount of idle time in milliseconds before a connection is considered idle and eligible for eviction. 
+     */
+    public int getMinEvictableIdleTimeMillis();
+    
+    /**
+     * The minimum amount of time an object must sit idle in the pool before it is eligible for eviction. 
+     * The default value is 60000 (60 seconds).
+     * @param minEvictableIdleTimeMillis the number of milliseconds a connection must be idle to be eligible for eviction.
+     */
+    public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis);
+
+    /**
+     * The minimum number of established connections that should be kept in the pool at all times. 
+     * The connection pool can shrink below this number if validation queries fail and connections get closed. 
+     * Default value is derived from {@link #getInitialSize()} (also see {@link #setTestWhileIdle(boolean)}
+     * The idle pool will not shrink below this value during an eviction run, hence the number of actual connections
+     * can be between {@link #getMinIdle()} and somewhere between {@link #getMaxIdle()} and {@link #getMaxActive()}
+     * @return the minimum number of idle or established connections
+     */
+    public int getMinIdle();
+    
+    /**
+     * The minimum number of established connections that should be kept in the pool at all times. 
+     * The connection pool can shrink below this number if validation queries fail and connections get closed. 
+     * Default value is derived from {@link #getInitialSize()} (also see {@link #setTestWhileIdle(boolean)}
+     * The idle pool will not shrink below this value during an eviction run, hence the number of actual connections
+     * can be between {@link #getMinIdle()} and somewhere between {@link #getMaxIdle()} and {@link #getMaxActive()}
+     * 
+     * @param minIdle the minimum number of idle or established connections
+     */
+    public void setMinIdle(int minIdle);
+
+    /**
+     * Returns the name of the connection pool. By default a JVM unique random name is assigned.
+     * @return the name of the pool, should be unique in a JVM
+     */
+    public String getName();
+    
+    /**
+     * Sets the name of the connection pool 
+     * @param name the name of the pool, should be unique in a runtime JVM
+     */
+    public void setName(String name);
+
+    /**
+     * Property not used
+     * @return unknown value
+     */
+    public int getNumTestsPerEvictionRun();
+    
+    /**
+     * Property not used
+     * @param numTestsPerEvictionRun parameter ignored.
+     */
+    public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun);
+
+    /**
+     * Returns the password used when establishing connections to the database.
+     * @return the password in string format
+     */
+    public String getPassword();
+    
+    /**
+     * Sets the password to establish the connection with.
+     * The password will be included as a database property with the name 'password'.
+     * @param password 
+     * @see #getDbProperties()
+     */
+    public void setPassword(String password);
+
+    /**
+     * @see #getName()
+     * @return name
+     */
+    public String getPoolName();
+    
+    /**
+     * Returns the username used to establish the connection with
+     * @return the username used to establish the connection with
+     */
+    public String getUsername();
+
+    /**
+     * Sets the username used to establish the connection with
+     * It will also be a property called 'user' in the database properties.
+     * @param username
+     * @see #getDbProperties()
+     */
+    public void setUsername(String username);
+
+
+    /**
+     * boolean flag to remove abandoned connections if they exceed the removeAbandonedTimout. 
+     * If set to true a connection is considered abandoned and eligible for removal if it has 
+     * been in use longer than the {@link #getRemoveAbandonedTimeout()} and the condition for 
+     * {@link #getAbandonWhenPercentageFull()} is met.
+     * Setting this to true can recover db connections from applications that fail to close a connection. 
+     * See also {@link #isLogAbandoned()} The default value is false.
+     * @return true if abandoned connections can be closed and expelled out of the pool
+     */
+    public boolean isRemoveAbandoned();
+    
+    /**
+     * boolean flag to remove abandoned connections if they exceed the removeAbandonedTimout. 
+     * If set to true a connection is considered abandoned and eligible for removal if it has 
+     * been in use longer than the {@link #getRemoveAbandonedTimeout()} and the condition for 
+     * {@link #getAbandonWhenPercentageFull()} is met.
+     * Setting this to true can recover db connections from applications that fail to close a connection. 
+     * See also {@link #isLogAbandoned()} The default value is false.
+     * @param removeAbandoned set to true if abandoned connections can be closed and expelled out of the pool
+     */
+    public void setRemoveAbandoned(boolean removeAbandoned);
+
+    /**
+     * The time in seconds before a connection can be considered abandoned.
+     * The timer can be reset upon queries using an interceptor.
+     * @param removeAbandonedTimeout the time in seconds before a used connection can be considered abandoned
+     * @see org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer
+     */
+    public void setRemoveAbandonedTimeout(int removeAbandonedTimeout);
+
+    /**
+     * The time in seconds before a connection can be considered abandoned.
+     * The timer can be reset upon queries using an interceptor.
+     * @see org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer
+     * @return the time in seconds before a used connection can be considered abandoned
+     */ 
+    public int getRemoveAbandonedTimeout();
+
+    /**
+     * The indication of whether objects will be validated before being borrowed from the pool. 
+     * If the object fails to validate, it will be dropped from the pool, and we will attempt to borrow another. 
+     * NOTE - for a true value to have any effect, the validationQuery parameter must be set to a non-null string. 
+     * Default value is false
+     * In order to have a more efficient validation, see {@link #setValidationInterval(long)}
+     * @return true if the connection is to be validated upon borrowing a connection from the pool
+     * @see #getValidationInterval()
+     */
+    public boolean isTestOnBorrow();
+    
+    /**
+     * The indication of whether objects will be validated before being borrowed from the pool. 
+     * If the object fails to validate, it will be dropped from the pool, and we will attempt to borrow another. 
+     * NOTE - for a true value to have any effect, the validationQuery parameter must be set to a non-null string. 
+     * Default value is false
+     * In order to have a more efficient validation, see {@link #setValidationInterval(long)}
+     * @param testOnBorrow set to true if validation should take place before a connection is handed out to the application
+     * @see #getValidationInterval()
+     */
+    public void setTestOnBorrow(boolean testOnBorrow);
+    
+    /**
+     * The indication of whether objects will be validated after being returned to the pool. 
+     * If the object fails to validate, it will be dropped from the pool. 
+     * NOTE - for a true value to have any effect, the validationQuery parameter must be set to a non-null string. 
+     * Default value is false
+     * In order to have a more efficient validation, see {@link #setValidationInterval(long)}
+     * @return true if validation should take place after a connection is returned to the pool
+     * @see #getValidationInterval()
+     */
+    public boolean isTestOnReturn();
+
+    /**
+     * The indication of whether objects will be validated after being returned to the pool. 
+     * If the object fails to validate, it will be dropped from the pool. 
+     * NOTE - for a true value to have any effect, the validationQuery parameter must be set to a non-null string. 
+     * Default value is false
+     * In order to have a more efficient validation, see {@link #setValidationInterval(long)}
+     * @param testOnReturn true if validation should take place after a connection is returned to the pool
+     * @see #getValidationInterval()
+     */
+    public void setTestOnReturn(boolean testOnReturn);
+    
+    
+    /**
+     * Set to true if query validation should take place while the connection is idle.
+     * @return true if validation should take place during idle checks
+     * @see #setTimeBetweenEvictionRunsMillis(int)
+     */
+    public boolean isTestWhileIdle();
+    
+    /**
+     * Set to true if query validation should take place while the connection is idle.
+     * @param testWhileIdle true if validation should take place during idle checks
+     * @see #setTimeBetweenEvictionRunsMillis(int)
+     */
+    public void setTestWhileIdle(boolean testWhileIdle);
+    
+    /**
+     * The number of milliseconds to sleep between runs of the idle connection validation, abandoned cleaner 
+     * and idle pool resizing. This value should not be set under 1 second. 
+     * It dictates how often we check for idle, abandoned connections, and how often we validate idle connection and resize the idle pool.
+     * The default value is 5000 (5 seconds)
+     * @return the sleep time in between validations in milliseconds
+     */
+    public int getTimeBetweenEvictionRunsMillis();
+    
+    /**
+     * The number of milliseconds to sleep between runs of the idle connection validation, abandoned cleaner 
+     * and idle pool resizing. This value should not be set under 1 second. 
+     * It dictates how often we check for idle, abandoned connections, and how often we validate idle connection and resize the idle pool.
+     * The default value is 5000 (5 seconds)
+     * @param timeBetweenEvictionRunsMillis the sleep time in between validations in milliseconds
+     */
+    public void setTimeBetweenEvictionRunsMillis(int timeBetweenEvictionRunsMillis);
+    
+    /**
+     * The URL used to connect to the database
+     * @return the configured URL for this connection pool
+     * @see java.sql.Driver#connect(String, Properties)
+     */
+    public String getUrl();
+    
+    /**
+     * Sets the URL used to connect to the database
+     * @param url the configured URL for this connection pool
+     * @see java.sql.Driver#connect(String, Properties)
+     */
+    public void setUrl(String url);
+    
+    /**
+     * The SQL query that will be used to validate connections from this 
+     * pool before returning them to the caller or pool. 
+     * If specified, this query does not have to return any data, 
+     * it just can't throw a SQLException. 
+     * The default value is null. 
+     * Example values are SELECT 1(mysql), 
+     * select 1 from dual(oracle), 
+     * SELECT 1(MS Sql Server)
+     * @return the query used for validation or null if no validation is performed
+     */
+    public String getValidationQuery();
+    
+    /**
+     * The SQL query that will be used to validate connections from this 
+     * pool before returning them to the caller or pool. 
+     * If specified, this query does not have to return any data, 
+     * it just can't throw a SQLException. 
+     * The default value is null. 
+     * Example values are SELECT 1(mysql), 
+     * select 1 from dual(oracle), 
+     * SELECT 1(MS Sql Server)
+     * @param validationQuery the query used for validation or null if no validation is performed
+     */
+    public void setValidationQuery(String validationQuery);
+    
+    /**
+     * Return the name of the optional validator class - may be null.
+     *  
+     * @return the name of the optional validator class - may be null
+     */
+    public String getValidatorClassName();
+    
+    /**
+     * Set the name for an optional validator class which will be used in place of test queries. If set to
+     * null, standard validation will be used.
+     * 
+     * @param className the name of the optional validator class
+     */
+    public void setValidatorClassName(String className);
+    
+    /**
+     * @return the optional validator object - may be null
+     */
+    public Validator getValidator();
+
+    /**
+     * avoid excess validation, only run validation at most at this frequency - time in milliseconds. 
+     * If a connection is due for validation, but has been validated previously 
+     * within this interval, it will not be validated again. 
+     * The default value is 30000 (30 seconds).
+     * @return the validation interval in milliseconds
+     */
+    public long getValidationInterval();
+    
+    /**
+     * avoid excess validation, only run validation at most at this frequency - time in milliseconds. 
+     * If a connection is due for validation, but has been validated previously 
+     * within this interval, it will not be validated again. 
+     * The default value is 30000 (30 seconds).
+     * @param validationInterval the validation interval in milliseconds
+     */
+    public void setValidationInterval(long validationInterval);
+    
+    /**
+     * A custom query to be run when a connection is first created. The default value is null.
+     * This query only runs once per connection, and that is when a new connection is established to the database.
+     * If this value is non null, it will replace the validation query during connection creation. 
+     * @return the init SQL used to run against the DB or null if not set 
+     */
+    public String getInitSQL();
+    
+    /**
+     * A custom query to be run when a connection is first created. The default value is null.
+     * This query only runs once per connection, and that is when a new connection is established to the database.
+     * If this value is non null, it will replace the validation query during connection creation. 
+     * @param initSQL the init SQL used to run against the DB or null if no query should be executed 
+     */
+    public void setInitSQL(String initSQL);
+
+    /**
+     * Returns true if we should run the validation query when connecting to the database for the first time on a connection.
+     * Normally this is always set to false, unless one wants to use the validationQuery as an init query.
+     * @return true if we should run the validation query upon connect
+     */
+    public boolean isTestOnConnect();
+
+    /**
+     * Set to true if we should run the validation query when connecting to the database for the first time on a connection.
+     * Normally this is always set to false, unless one wants to use the validationQuery as an init query.
+     * Setting an {@link #setInitSQL(String)} will override this setting, as the init SQL will be used instead of the validation query
+     * @param testOnConnect set to true if we should run the validation query upon connect
+     */
+    public void setTestOnConnect(boolean testOnConnect);
+    
+    /**
+     * A semicolon separated list of classnames extending {@link org.apache.tomcat.jdbc.pool.JdbcInterceptor} class. 
+     * These interceptors will be inserted as an interceptor into the chain of operations on a java.sql.Connection object.
+     * Example interceptors are {@link org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer StatementFinalizer} to close all 
+     * used statements during the session.
+     * {@link org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer ResetAbandonedTimer} resets the timer upon every operation
+     * on the connection or a statement.
+     * {@link org.apache.tomcat.jdbc.pool.interceptor.ConnectionState ConnectionState} caches the auto commit, read only and catalog settings to avoid round trips to the DB.
+     * The default value is null.
+     * @return the interceptors that are used for connections.
+     * Example format: 'ConnectionState(useEquals=true,fast=yes);ResetAbandonedTimer'
+     */
+    public String getJdbcInterceptors();
+    
+    /**
+     * A semicolon separated list of classnames extending {@link org.apache.tomcat.jdbc.pool.JdbcInterceptor} class. 
+     * These interceptors will be inserted as an interceptor into the chain of operations on a java.sql.Connection object.
+     * Example interceptors are {@link org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer StatementFinalizer} to close all 
+     * used statements during the session.
+     * {@link org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer ResetAbandonedTimer} resets the timer upon every operation
+     * on the connection or a statement.
+     * {@link org.apache.tomcat.jdbc.pool.interceptor.ConnectionState ConnectionState} caches the auto commit, read only and catalog settings to avoid round trips to the DB.
+     * The default value is null.
+     * @param jdbcInterceptors the interceptors that are used for connections.
+     * Example format: 'ConnectionState(useEquals=true,fast=yes);ResetAbandonedTimer'
+     */
+    public void setJdbcInterceptors(String jdbcInterceptors);
+
+    /**
+     * Returns the {@link #getJdbcInterceptors()} as an array of objects with properties and the classes.
+     * @return an array of interceptors that have been configured
+     */
+    public InterceptorDefinition[] getJdbcInterceptorsAsArray();
+
+    
+    /**
+     * If set to true, the connection pool creates a {@link org.apache.tomcat.jdbc.pool.jmx.ConnectionPoolMBean} object 
+     * that can be registered with JMX to receive notifications and state about the pool.
+     * The ConnectionPool object doesn't register itself, as there is no way to keep a static non changing ObjectName across JVM restarts.
+     * @return true if the mbean object will be created upon startup.
+     */
+    public boolean isJmxEnabled();
+
+    /**
+     * If set to true, the connection pool creates a {@link org.apache.tomcat.jdbc.pool.jmx.ConnectionPoolMBean} object 
+     * that can be registered with JMX to receive notifications and state about the pool.
+     * The ConnectionPool object doesn't register itself, as there is no way to keep a static non changing ObjectName across JVM restarts.
+     * @param jmxEnabled set to to if the mbean object should be created upon startup.
+     */
+    public void setJmxEnabled(boolean jmxEnabled);
+
+    /**
+     * Returns true if the pool sweeper is enabled for the connection pool.
+     * The pool sweeper is enabled if any settings that require async intervention in the pool are turned on
+     * <source>
+        boolean result = getTimeBetweenEvictionRunsMillis()>0;
+        result = result && (isRemoveAbandoned() && getRemoveAbandonedTimeout()>0);
+        result = result || (isTestWhileIdle() && getValidationQuery()!=null);
+        return result;
+       </source> 
+     *
+     * @return true if a background thread is or will be enabled for this pool
+     */
+    public boolean isPoolSweeperEnabled();
+
+    /**
+     * Set to true if you wish the <code>ProxyConnection</code> class to use <code>String.equals</code> instead of 
+     * <code>==</code> when comparing method names. 
+     * This property does not apply to added interceptors as those are configured individually.
+     * The default value is <code>false</code>.
+     * @return true if pool uses {@link String#equals(Object)} instead of == when comparing method names on {@link java.sql.Connection} methods
+     */
+    public boolean isUseEquals();
+
+    /**
+     * Set to true if you wish the <code>ProxyConnection</code> class to use <code>String.equals</code> instead of 
+     * <code>==</code> when comparing method names. 
+     * This property does not apply to added interceptors as those are configured individually.
+     * The default value is <code>false</code>.
+     * @param useEquals set to true if the pool should use {@link String#equals(Object)} instead of ==
+     * when comparing method names on {@link java.sql.Connection} methods
+     */
+    public void setUseEquals(boolean useEquals);
+
+    /**
+     * Time in milliseconds to keep this connection alive even when used. 
+     * When a connection is returned to the pool, the pool will check to see if the 
+     * ((now - time-when-connected) > maxAge) has been reached, and if so, 
+     * it closes the connection rather than returning it to the pool. 
+     * The default value is 0, which implies that connections will be left open and no 
+     * age check will be done upon returning the connection to the pool.
+     * This is a useful setting for database sessions that leak memory as it ensures that the session
+     * will have a finite life span.
+     * @return the time in milliseconds a connection will be open for when used
+     */
+    public long getMaxAge();
+
+    /**
+     * Time in milliseconds to keep this connection alive even when used. 
+     * When a connection is returned to the pool, the pool will check to see if the 
+     * ((now - time-when-connected) > maxAge) has been reached, and if so, 
+     * it closes the connection rather than returning it to the pool. 
+     * The default value is 0, which implies that connections will be left open and no 
+     * age check will be done upon returning the connection to the pool.
+     * This is a useful setting for database sessions that leak memory as it ensures that the session
+     * will have a finite life span.
+     * @param maxAge the time in milliseconds a connection will be open for when used
+     */
+    public void setMaxAge(long maxAge);
+
+    /**
+     * Return true if a lock should be used when operations are performed on the connection object.
+     * Should be set to false unless you plan to have a background thread of your own doing idle and abandon checking
+     * such as JMX clients. If the pool sweeper is enabled, then the lock will automatically be used regardless of this setting.
+     * @return true if a lock is used.
+     */
+    public boolean getUseLock();
+
+    /**
+     * Set to true if a lock should be used when operations are performed on the connection object.
+     * Should be set to false unless you plan to have a background thread of your own doing idle and abandon checking
+     * such as JMX clients. If the pool sweeper is enabled, then the lock will automatically be used regardless of this setting.
+     * @param useLock set to true if a lock should be used on connection operations
+     */
+    public void setUseLock(boolean useLock);
+    
+    /**
+     * Similar to {@link #setRemoveAbandonedTimeout(int)} but instead of treating the connection
+     * as abandoned, and potentially closing the connection, this simply logs the warning if 
+     * {@link #isLogAbandoned()} returns true. If this value is equal or less than 0, no suspect 
+     * checking will be performed. Suspect checking only takes place if the timeout value is larger than 0 and
+     * the connection was not abandoned or if abandon check is disabled. If a connection is suspect a WARN message gets
+     * logged and a JMX notification gets sent once. 
+     * @param seconds - the amount of time in seconds that has to pass before a connection is marked suspect. 
+     */
+    public void setSuspectTimeout(int seconds);
+    
+    /**
+     * Returns the time in seconds to pass before a connection is marked an abanoned suspect.
+     * Any value lesser than or equal to 0 means the check is disabled. 
+     * @return Returns the time in seconds to pass before a connection is marked an abanoned suspect.
+     */
+    public int getSuspectTimeout();
+    
+    /**
+     * Injects a datasource that will be used to retrieve/create connections.
+     * If a data source is set, the {@link PoolConfiguration#getUrl()} and {@link PoolConfiguration#getDriverClassName()} methods are ignored
+     * and not used by the pool. If the {@link PoolConfiguration#getUsername()} and {@link PoolConfiguration#getPassword()}
+     * values are set, the method {@link javax.sql.DataSource#getConnection(String, String)} method will be called instead of the
+     * {@link javax.sql.DataSource#getConnection()} method.
+     * If the data source implements {@link javax.sql.XADataSource} the methods 
+     * {@link javax.sql.XADataSource#getXAConnection()} and {@link javax.sql.XADataSource#getXAConnection(String,String)}
+     * will be invoked.  
+     * @param ds the {@link javax.sql.DataSource} to be used for creating connections to be pooled.
+     */
+    public void setDataSource(Object ds);
+    
+    /**
+     * Returns a datasource, if one exists that is being used to create connections.
+     * This method will return null if the pool is using a {@link java.sql.Driver}
+     * @return the {@link javax.sql.DataSource} to be used for creating connections to be pooled or null if a Driver is used.
+     */
+    public Object getDataSource();
+    
+    /**
+     * Configure the connection pool to use a DataSource according to {@link PoolConfiguration#setDataSource(Object)}
+     * But instead of injecting the object, specify the JNDI location.
+     * After a successful JNDI look, the {@link PoolConfiguration#getDataSource()} will not return null. 
+     * @param jndiDS -the JNDI string @TODO specify the rules here.
+     */
+    public void setDataSourceJNDI(String jndiDS);
+    
+    /**
+     * Returns the JNDI string configured for data source usage.
+     * @return the JNDI string or null if not set
+     */
+    public String getDataSourceJNDI();
+    
+    /**
+     * Returns true if the call {@link DataSource#getConnection(String, String) getConnection(username,password)} is 
+     * allowed. This is used for when the pool is used by an application accessing multiple schemas.
+     * There is a performance impact turning this option on.
+     * @return true if {@link DataSource#getConnection(String, String) getConnection(username,password)} is honored, false if it is ignored.
+     */
+    public boolean isAlternateUsernameAllowed();
+    
+    /**
+     * Set to true if the call {@link DataSource#getConnection(String, String) getConnection(username,password)} is 
+     * allowed and honored.. This is used for when the pool is used by an application accessing multiple schemas.
+     * There is a performance impact turning this option on, even when not used due to username checks.
+     * @param alternateUsernameAllowed - set true if {@link DataSource#getConnection(String, String) getConnection(username,password)} is honored, 
+     * false if it is to be ignored.
+     */
+    public void setAlternateUsernameAllowed(boolean alternateUsernameAllowed);
+    
+
+}
\ No newline at end of file
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java
new file mode 100644 (file)
index 0000000..6fd20d4
--- /dev/null
@@ -0,0 +1,1053 @@
+/*
+ * 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.pool;
+
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicInteger;
+
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+
+/**
+ * @author Filip Hanik
+ *
+ */
+public class PoolProperties implements PoolConfiguration {
+    private static final Log log = LogFactory.getLog(PoolProperties.class);
+    
+    public static final int DEFAULT_MAX_ACTIVE = 100;
+    
+    protected static AtomicInteger poolCounter = new AtomicInteger(0);
+    protected Properties dbProperties = new Properties();
+    protected String url = null;
+    protected String driverClassName = null;
+    protected Boolean defaultAutoCommit = null;
+    protected Boolean defaultReadOnly = null;
+    protected int defaultTransactionIsolation = DataSourceFactory.UNKNOWN_TRANSACTIONISOLATION;
+    protected String defaultCatalog = null;
+    protected String connectionProperties;
+    protected int initialSize = 10;
+    protected int maxActive = DEFAULT_MAX_ACTIVE;
+    protected int maxIdle = maxActive;
+    protected int minIdle = initialSize;
+    protected int maxWait = 30000;
+    protected String validationQuery;
+    protected String validatorClassName;
+    protected Validator validator;
+    protected boolean testOnBorrow = false;
+    protected boolean testOnReturn = false;
+    protected boolean testWhileIdle = false;
+    protected int timeBetweenEvictionRunsMillis = 5000;
+    protected int numTestsPerEvictionRun;
+    protected int minEvictableIdleTimeMillis = 60000;
+    protected final boolean accessToUnderlyingConnectionAllowed = true;
+    protected boolean removeAbandoned = false;
+    protected int removeAbandonedTimeout = 60;
+    protected boolean logAbandoned = false;
+    protected String name = "Tomcat Connection Pool["+(poolCounter.addAndGet(1))+"-"+System.identityHashCode(PoolProperties.class)+"]";
+    protected String password;
+    protected String username;
+    protected long validationInterval = 30000;
+    protected boolean jmxEnabled = true;
+    protected String initSQL;
+    protected boolean testOnConnect =false;
+    protected String jdbcInterceptors=null;
+    protected boolean fairQueue = true;
+    protected boolean useEquals = true;
+    protected int abandonWhenPercentageFull = 0;
+    protected long maxAge = 0;
+    protected boolean useLock = false;
+    protected InterceptorDefinition[] interceptors = null;
+    protected int suspectTimeout = 0;
+    protected Object dataSource = null;
+    protected String dataSourceJNDI = null;
+    protected boolean alternateUsernameAllowed = false;
+    
+    
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setAbandonWhenPercentageFull(int percentage) {
+        if (percentage<0) abandonWhenPercentageFull = 0;
+        else if (percentage>100) abandonWhenPercentageFull = 100;
+        else abandonWhenPercentageFull = percentage;
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public int getAbandonWhenPercentageFull() {
+        return abandonWhenPercentageFull;
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public boolean isFairQueue() {
+        return fairQueue;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setFairQueue(boolean fairQueue) {
+        this.fairQueue = fairQueue;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public boolean isAccessToUnderlyingConnectionAllowed() {
+        return accessToUnderlyingConnectionAllowed;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public String getConnectionProperties() {
+        return connectionProperties;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public Properties getDbProperties() {
+        return dbProperties;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public Boolean isDefaultAutoCommit() {
+        return defaultAutoCommit;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public String getDefaultCatalog() {
+        return defaultCatalog;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public Boolean isDefaultReadOnly() {
+        return defaultReadOnly;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public int getDefaultTransactionIsolation() {
+        return defaultTransactionIsolation;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public String getDriverClassName() {
+        return driverClassName;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public int getInitialSize() {
+        return initialSize;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public boolean isLogAbandoned() {
+        return logAbandoned;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public int getMaxActive() {
+        return maxActive;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public int getMaxIdle() {
+        return maxIdle;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public int getMaxWait() {
+        return maxWait;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public int getMinEvictableIdleTimeMillis() {
+        return minEvictableIdleTimeMillis;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public int getMinIdle() {
+        return minIdle;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public String getName() {
+        return name;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public int getNumTestsPerEvictionRun() {
+        return numTestsPerEvictionRun;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public String getPassword() {
+        return password;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public String getPoolName() {
+        return getName();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public boolean isRemoveAbandoned() {
+        return removeAbandoned;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public int getRemoveAbandonedTimeout() {
+        return removeAbandonedTimeout;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public boolean isTestOnBorrow() {
+        return testOnBorrow;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public boolean isTestOnReturn() {
+        return testOnReturn;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public boolean isTestWhileIdle() {
+        return testWhileIdle;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public int getTimeBetweenEvictionRunsMillis() {
+        return timeBetweenEvictionRunsMillis;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public String getUrl() {
+        return url;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public String getUsername() {
+        return username;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public String getValidationQuery() {
+        return validationQuery;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    
+    public String getValidatorClassName() {
+        return validatorClassName;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    
+    public Validator getValidator() {
+        return validator;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public long getValidationInterval() {
+        return validationInterval;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public String getInitSQL() {
+        return initSQL;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public boolean isTestOnConnect() {
+        return testOnConnect;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public String getJdbcInterceptors() {
+        return jdbcInterceptors;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public InterceptorDefinition[] getJdbcInterceptorsAsArray() {
+        if (interceptors == null) {
+            if (jdbcInterceptors==null) {
+                interceptors = new InterceptorDefinition[0];
+            } else {
+                String[] interceptorValues = jdbcInterceptors.split(";");
+                InterceptorDefinition[] definitions = new InterceptorDefinition[interceptorValues.length];
+                for (int i=0; i<interceptorValues.length; i++) {
+                    int propIndex = interceptorValues[i].indexOf("(");
+                    int endIndex = interceptorValues[i].indexOf(")");
+                    if (propIndex<0 || endIndex<0 || endIndex <= propIndex) {
+                        definitions[i] = new InterceptorDefinition(interceptorValues[i].trim());
+                    } else {
+                        String name = interceptorValues[i].substring(0,propIndex).trim();
+                        definitions[i] = new InterceptorDefinition(name);
+                        String propsAsString = interceptorValues[i].substring(propIndex+1, interceptorValues[i].length()-1);
+                        String[] props = propsAsString.split(",");
+                        for (int j=0; j<props.length; j++) {
+                            int pidx = props[j].indexOf("=");
+                            String propName = props[j].substring(0,pidx).trim();
+                            String propValue = props[j].substring(pidx+1).trim();
+                            definitions[i].addProperty(new InterceptorProperty(propName,propValue));
+                        }
+                    }
+                }
+                interceptors = definitions;
+            }
+        }
+        return interceptors;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setAccessToUnderlyingConnectionAllowed(boolean accessToUnderlyingConnectionAllowed) {
+        // NOOP
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setConnectionProperties(String connectionProperties) {
+        this.connectionProperties = connectionProperties;
+        getProperties(connectionProperties, getDbProperties());
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setDbProperties(Properties dbProperties) {
+        this.dbProperties = dbProperties;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setDefaultAutoCommit(Boolean defaultAutoCommit) {
+        this.defaultAutoCommit = defaultAutoCommit;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setDefaultCatalog(String defaultCatalog) {
+        this.defaultCatalog = defaultCatalog;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setDefaultReadOnly(Boolean defaultReadOnly) {
+        this.defaultReadOnly = defaultReadOnly;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setDefaultTransactionIsolation(int defaultTransactionIsolation) {
+        this.defaultTransactionIsolation = defaultTransactionIsolation;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setDriverClassName(String driverClassName) {
+        this.driverClassName = driverClassName;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setInitialSize(int initialSize) {
+        this.initialSize = initialSize;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setLogAbandoned(boolean logAbandoned) {
+        this.logAbandoned = logAbandoned;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setMaxActive(int maxActive) {
+        this.maxActive = maxActive;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setMaxIdle(int maxIdle) {
+        this.maxIdle = maxIdle;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setMaxWait(int maxWait) {
+        this.maxWait = maxWait;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) {
+        this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setMinIdle(int minIdle) {
+        this.minIdle = minIdle;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
+        this.numTestsPerEvictionRun = numTestsPerEvictionRun;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setRemoveAbandoned(boolean removeAbandoned) {
+        this.removeAbandoned = removeAbandoned;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) {
+        this.removeAbandonedTimeout = removeAbandonedTimeout;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setTestOnBorrow(boolean testOnBorrow) {
+        this.testOnBorrow = testOnBorrow;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setTestWhileIdle(boolean testWhileIdle) {
+        this.testWhileIdle = testWhileIdle;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setTestOnReturn(boolean testOnReturn) {
+        this.testOnReturn = testOnReturn;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setTimeBetweenEvictionRunsMillis(int
+                                                 timeBetweenEvictionRunsMillis) {
+        this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setValidationInterval(long validationInterval) {
+        this.validationInterval = validationInterval;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setValidationQuery(String validationQuery) {
+        this.validationQuery = validationQuery;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    
+    public void setValidatorClassName(String className) {
+        this.validatorClassName = className;
+        
+        validator = null;
+        
+        if (className == null) {
+            return;
+        }
+        
+        try {
+            Class<Validator> validatorClass = (Class<Validator>)Class.forName(className);
+            validator = validatorClass.newInstance();
+        } catch (ClassNotFoundException e) {
+            log.warn("The class "+className+" cannot be found.", e);
+        } catch (ClassCastException e) {
+            log.warn("The class "+className+" does not implement the Validator interface.", e);
+        } catch (InstantiationException e) {
+            log.warn("An object of class "+className+" cannot be instantiated. Make sure that "+
+                     "it includes an implicit or explicit no-arg constructor.", e);
+        } catch (IllegalAccessException e) {
+            log.warn("The class "+className+" or its no-arg constructor are inaccessible.", e);
+        }
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setInitSQL(String initSQL) {
+        this.initSQL = initSQL;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setTestOnConnect(boolean testOnConnect) {
+        this.testOnConnect = testOnConnect;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setJdbcInterceptors(String jdbcInterceptors) {
+        this.jdbcInterceptors = jdbcInterceptors;
+        this.interceptors = null;
+    }
+
+    
+    public String toString() {
+        StringBuilder buf = new StringBuilder("ConnectionPool[");
+        try {
+            String[] fields = DataSourceFactory.ALL_PROPERTIES;
+            for (int i=0; i<fields.length; i++) {
+                final String[] prefix = new String[] {"get","is"};
+                for (int j=0; j<prefix.length; j++) {
+
+                    String name = prefix[j] + fields[i].substring(0, 1).toUpperCase() +
+                                  fields[i].substring(1);
+                    Method m = null;
+                    try {
+                        m = getClass().getMethod(name);
+                    }catch (NoSuchMethodException nm) {
+                        continue;
+                    }
+                    buf.append(fields[i]);
+                    buf.append("=");
+                    buf.append(m.invoke(this, new Object[0]));
+                    buf.append("; ");
+                    break;
+                }
+            }
+        }catch (Exception x) {
+            //shouldn;t happen
+            x.printStackTrace();
+        }
+        return buf.toString();
+    }
+
+    public static int getPoolCounter() {
+        return poolCounter.get();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public boolean isJmxEnabled() {
+        return jmxEnabled;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setJmxEnabled(boolean jmxEnabled) {
+        this.jmxEnabled = jmxEnabled;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public Boolean getDefaultAutoCommit() {
+        return defaultAutoCommit;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public Boolean getDefaultReadOnly() {
+        return defaultReadOnly;
+    }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    
+    public int getSuspectTimeout() {
+        return this.suspectTimeout;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    
+    public void setSuspectTimeout(int seconds) {
+        this.suspectTimeout = seconds;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public boolean isPoolSweeperEnabled() {
+        boolean timer = getTimeBetweenEvictionRunsMillis()>0;
+        boolean result = timer && (isRemoveAbandoned() && getRemoveAbandonedTimeout()>0);
+        result = result || (timer && getSuspectTimeout()>0); 
+        result = result || (timer && isTestWhileIdle() && getValidationQuery()!=null);
+        result = result || (timer && getMinEvictableIdleTimeMillis()>0); 
+        return result;
+    }
+
+
+    public static class InterceptorDefinition {
+        protected String className;
+        protected Map<String,InterceptorProperty> properties = new HashMap<String,InterceptorProperty>();
+        protected volatile Class<?> clazz = null;
+        public InterceptorDefinition(String className) {
+            this.className = className;
+        }
+
+        public String getClassName() {
+            return className;
+        }
+        public void addProperty(String name, String value) {
+            InterceptorProperty p = new InterceptorProperty(name,value);
+            addProperty(p);
+        }
+        
+        public void addProperty(InterceptorProperty p) {
+            properties.put(p.getName(), p);
+        }
+        
+        public Map<String,InterceptorProperty> getProperties() {
+            return properties;
+        }
+        
+        public Class<? extends JdbcInterceptor> getInterceptorClass() throws ClassNotFoundException {
+            if (clazz==null) {
+                if (getClassName().indexOf(".")<0) {
+                    if (log.isDebugEnabled()) {
+                        log.debug("Loading interceptor class:"+PoolConfiguration.PKG_PREFIX+getClassName());
+                    }
+                    clazz = Class.forName(PoolConfiguration.PKG_PREFIX+getClassName(), true, this.getClass().getClassLoader());
+                } else {
+                    if (log.isDebugEnabled()) {
+                        log.debug("Loading interceptor class:"+getClassName());
+                    }
+                    clazz = Class.forName(getClassName(), true, this.getClass().getClassLoader());
+                }
+            }
+            return (Class<? extends JdbcInterceptor>)clazz;
+        }
+    } 
+    
+    public static class InterceptorProperty {
+        String name;
+        String value;
+        public InterceptorProperty(String name, String value) {
+            assert(name!=null);
+            this.name = name;
+            this.value = value;
+        }
+        public String getName() {
+            return name;
+        }
+        public String getValue() {
+            return value;
+        }
+        
+        public boolean getValueAsBoolean(boolean def) {
+            if (value==null) return def;
+            if ("true".equals(value)) return true;
+            if ("false".equals(value)) return false;
+            return def;
+        }
+        
+        public int getValueAsInt(int def) {
+            if (value==null) return def;
+            try {
+                int v = Integer.parseInt(value);
+                return v;
+            }catch (NumberFormatException nfe) {
+                return def;
+            }
+        }
+        
+        public long getValueAsLong(long def) {
+            if (value==null) return def;
+            try {
+                return Long.parseLong(value);
+            }catch (NumberFormatException nfe) {
+                return def;
+            }
+        }
+
+        public byte getValueAsByte(byte def) {
+            if (value==null) return def;
+            try {
+                return Byte.parseByte(value);
+            }catch (NumberFormatException nfe) {
+                return def;
+            }
+        }
+        
+        public short getValueAsShort(short def) {
+            if (value==null) return def;
+            try {
+                return Short.parseShort(value);
+            }catch (NumberFormatException nfe) {
+                return def;
+            }
+        }
+
+        public float getValueAsFloat(float def) {
+            if (value==null) return def;
+            try {
+                return Float.parseFloat(value);
+            }catch (NumberFormatException nfe) {
+                return def;
+            }
+        }
+
+        public double getValueAsDouble(double def) {
+            if (value==null) return def;
+            try {
+                return Double.parseDouble(value);
+            }catch (NumberFormatException nfe) {
+                return def;
+            }
+        }
+        public char getValueAschar(char def) {
+            if (value==null) return def;
+            try {
+                return value.charAt(0);
+            }catch (StringIndexOutOfBoundsException nfe) {
+                return def;
+            }
+        }
+        
+        public int hashCode() {
+            return name.hashCode();
+        }
+        
+        public boolean equals(Object o) {
+            if (o==this) return true;
+            if (o instanceof InterceptorProperty) {
+                InterceptorProperty other = (InterceptorProperty)o;
+                return other.name.equals(this.name);
+            }
+            return false;
+        }
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public boolean isUseEquals() {
+        return useEquals;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setUseEquals(boolean useEquals) {
+        this.useEquals = useEquals;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public long getMaxAge() {
+        return maxAge;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setMaxAge(long maxAge) {
+        this.maxAge = maxAge;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public boolean getUseLock() {
+        return useLock;
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    
+    public void setUseLock(boolean useLock) {
+        this.useLock = useLock;
+    }
+    
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public void setDataSource(Object ds) {
+        this.dataSource = ds;
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public Object getDataSource() {
+        return dataSource;
+    }
+    
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public void setDataSourceJNDI(String jndiDS) {
+        this.dataSourceJNDI = jndiDS;
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public String getDataSourceJNDI() {
+        return this.dataSourceJNDI;
+    }
+    
+        
+    public static Properties getProperties(String propText, Properties props) {
+        if (props==null) props = new Properties();
+        if (propText != null) {
+            try {
+                props.load(new ByteArrayInputStream(propText.replace(';', '\n').getBytes()));
+            }catch (IOException x) {
+                throw new RuntimeException(x);
+            }
+        }
+        return props;
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public boolean isAlternateUsernameAllowed() {
+        return alternateUsernameAllowed;
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public void setAlternateUsernameAllowed(boolean alternateUsernameAllowed) {
+        this.alternateUsernameAllowed = alternateUsernameAllowed;
+    }
+    
+}
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolUtilities.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolUtilities.java
new file mode 100644 (file)
index 0000000..0b2a5ed
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 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.pool;
+
+import java.util.Properties;
+
+/**
+ * 
+ * @author fhanik
+ *
+ */
+public class PoolUtilities {
+    
+    public static final String PROP_USER = "user";
+    
+    public static final String PROP_PASSWORD = "password";
+    
+    public static Properties clone(Properties p) {
+        Properties c = new Properties();
+        c.putAll(p);
+        return c;
+    }
+    
+    public static Properties cloneWithoutPassword(Properties p) {
+        Properties result = clone(p);
+        result.remove(PROP_PASSWORD);
+        return result;
+    }
+}
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PooledConnection.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PooledConnection.java
new file mode 100644 (file)
index 0000000..e4108b8
--- /dev/null
@@ -0,0 +1,670 @@
+/*
+ * 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.pool;
+
+
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.HashMap;
+import java.util.Properties;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Represents a pooled connection
+ * and holds a reference to the {@link java.sql.Connection} object
+ * @author Filip Hanik
+ * @version 1.0
+ */
+public class PooledConnection {
+    /**
+     * Logger
+     */
+    private static final Log log = LogFactory.getLog(PooledConnection.class);
+
+    public static final String PROP_USER = PoolUtilities.PROP_USER;
+    
+    public static final String PROP_PASSWORD = PoolUtilities.PROP_PASSWORD;
+    
+    /**
+     * Validate when connection is borrowed flag
+     */
+    public static final int VALIDATE_BORROW = 1;
+    /**
+     * Validate when connection is returned flag
+     */
+    public static final int VALIDATE_RETURN = 2;
+    /**
+     * Validate when connection is idle flag
+     */
+    public static final int VALIDATE_IDLE = 3;
+    /**
+     * Validate when connection is initialized flag
+     */
+    public static final int VALIDATE_INIT = 4;
+    /**
+     * The properties for the connection pool
+     */
+    protected PoolConfiguration poolProperties;
+    /**
+     * The underlying database connection
+     */
+    private volatile java.sql.Connection connection;
+    
+    /**
+     * If using a XAConnection underneath.
+     */
+    protected volatile javax.sql.XAConnection xaConnection;
+    /**
+     * When we track abandon traces, this string holds the thread dump
+     */
+    private String abandonTrace = null;
+    /**
+     * Timestamp the connection was last 'touched' by the pool
+     */
+    private volatile long timestamp;
+    /**
+     * Lock for this connection only
+     */
+    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(false);
+    /**
+     * Set to true if this connection has been discarded by the pool
+     */
+    private volatile boolean discarded = false;
+    /**
+     * The Timestamp when the last time the connect() method was called successfully
+     */
+    private volatile long lastConnected = -1;
+    /**
+     * timestamp to keep track of validation intervals
+     */
+    private volatile long lastValidated = System.currentTimeMillis();
+    /**
+     * 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
+     * so that we don't create a new list of interceptors each time we borrow
+     * the connection
+     */
+    private volatile JdbcInterceptor handler = null;
+    
+    private AtomicBoolean released = new AtomicBoolean(false);
+    
+    private volatile boolean suspect = false;
+    
+    private java.sql.Driver driver = null;
+    
+    /**
+     * Constructor
+     * @param prop - pool properties
+     * @param parent - the parent connection pool
+     */
+    public PooledConnection(PoolConfiguration prop, ConnectionPool parent) {
+        poolProperties = prop;
+        this.parent = parent;
+    }
+
+    public boolean checkUser(String username, String password) {
+        if (!getPoolProperties().isAlternateUsernameAllowed()) return true;
+        
+        if (username==null) username = poolProperties.getUsername();
+        if (password==null) password = poolProperties.getPassword();
+        
+        String storedUsr = (String)getAttributes().get(PROP_USER);
+        String storedPwd = (String)getAttributes().get(PROP_PASSWORD);
+        
+        boolean result = (username==null && storedUsr==null);
+        result = (result || (username!=null && username.equals(storedUsr)));
+                
+        result = result && ((password==null && storedPwd==null) || (password!=null && password.equals(storedPwd)));
+        
+        if (username==null)  getAttributes().remove(PROP_USER); else getAttributes().put(PROP_USER, username);
+        if (password==null)  getAttributes().remove(PROP_PASSWORD); else getAttributes().put(PROP_PASSWORD, password);
+        
+        return result;
+    }
+    
+    /**
+     * Connects the underlying connection to the database.
+     * @throws SQLException if the method {@link #release()} has been called.
+     * @throws SQLException if driver instantiation fails
+     * @throws SQLException if a call to {@link java.sql.Driver#connect(String, java.util.Properties)} fails.
+     * @throws SQLException if default properties are configured and a call to 
+     * {@link java.sql.Connection#setAutoCommit(boolean)}, {@link java.sql.Connection#setCatalog(String)}, 
+     * {@link java.sql.Connection#setTransactionIsolation(int)} or {@link java.sql.Connection#setReadOnly(boolean)} fails.  
+     */
+    public void connect() throws SQLException {
+        if (released.get()) throw new SQLException("A connection once released, can't be reestablished.");
+        if (connection != null) {
+            try {
+                this.disconnect(false);
+            } catch (Exception x) {
+                log.debug("Unable to disconnect previous connection.", x);
+            } //catch
+        } //end if
+        if (poolProperties.getDataSource()==null && poolProperties.getDataSourceJNDI()!=null) {
+            //TODO lookup JNDI name
+        }
+        
+        if (poolProperties.getDataSource()!=null) {
+            connectUsingDataSource();
+        } else {
+            connectUsingDriver();
+        }
+        
+        //set up the default state, unless we expect the interceptor to do it
+        if (poolProperties.getJdbcInterceptors()==null || poolProperties.getJdbcInterceptors().indexOf(ConnectionState.class.getName())<0) {
+            if (poolProperties.getDefaultTransactionIsolation()!=DataSourceFactory.UNKNOWN_TRANSACTIONISOLATION) connection.setTransactionIsolation(poolProperties.getDefaultTransactionIsolation());
+            if (poolProperties.getDefaultReadOnly()!=null) connection.setReadOnly(poolProperties.getDefaultReadOnly().booleanValue());
+            if (poolProperties.getDefaultAutoCommit()!=null) connection.setAutoCommit(poolProperties.getDefaultAutoCommit().booleanValue());
+            if (poolProperties.getDefaultCatalog()!=null) connection.setCatalog(poolProperties.getDefaultCatalog());
+        }        
+        this.discarded = false;
+        this.lastConnected = System.currentTimeMillis();
+    }
+    
+    protected void connectUsingDataSource() throws SQLException {
+        String usr = null;
+        String pwd = null;
+        if (getAttributes().containsKey(PROP_USER)) {
+            usr = (String) getAttributes().get(PROP_USER);
+        } else {
+            usr = poolProperties.getUsername();
+            getAttributes().put(PROP_USER, usr);
+        }
+        if (getAttributes().containsKey(PROP_PASSWORD)) {
+            pwd = (String) getAttributes().get(PROP_PASSWORD);
+        } else {
+            pwd = poolProperties.getPassword();
+            getAttributes().put(PROP_PASSWORD, pwd);
+        }
+        if (poolProperties.getDataSource() instanceof javax.sql.XADataSource) {
+            javax.sql.XADataSource xds = (javax.sql.XADataSource)poolProperties.getDataSource();
+            if (usr!=null && pwd!=null) {
+                xaConnection = xds.getXAConnection(usr, pwd);
+                connection = xaConnection.getConnection();
+            } else {
+                xaConnection = xds.getXAConnection();
+                connection = xaConnection.getConnection();
+            }
+        } else if (poolProperties.getDataSource() instanceof javax.sql.DataSource){
+            javax.sql.DataSource ds = (javax.sql.DataSource)poolProperties.getDataSource();
+            if (usr!=null && pwd!=null) {
+                connection = ds.getConnection(usr, pwd);
+            } else {
+                connection = ds.getConnection();
+            }
+        } else if (poolProperties.getDataSource() instanceof javax.sql.ConnectionPoolDataSource){
+            javax.sql.ConnectionPoolDataSource ds = (javax.sql.ConnectionPoolDataSource)poolProperties.getDataSource();
+            if (usr!=null && pwd!=null) {
+                connection = ds.getPooledConnection(usr, pwd).getConnection();
+            } else {
+                connection = ds.getPooledConnection().getConnection();
+            }
+        } else {
+            throw new SQLException("DataSource is of unknown class:"+(poolProperties.getDataSource()!=null?poolProperties.getDataSource().getClass():"null"));
+        }
+    }
+    protected void connectUsingDriver() throws SQLException {
+        
+        try {
+            if (driver==null)
+                driver = (java.sql.Driver) Class.forName(poolProperties.getDriverClassName(),
+                                                         true, PooledConnection.class.getClassLoader()
+                                                         ).newInstance();
+        } catch (java.lang.Exception cn) {
+            if (log.isDebugEnabled()) {
+                log.debug("Unable to instantiate JDBC driver.", cn);
+            }
+            SQLException ex = new SQLException(cn.getMessage());
+            ex.initCause(cn);
+            throw ex;
+        }
+        String driverURL = poolProperties.getUrl();
+        String usr = null;
+        String pwd = null;
+        if (getAttributes().containsKey(PROP_USER)) {
+            usr = (String) getAttributes().get(PROP_USER);
+        } else {
+            usr = poolProperties.getUsername();
+            getAttributes().put(PROP_USER, usr);
+        }
+        if (getAttributes().containsKey(PROP_PASSWORD)) {
+            pwd = (String) getAttributes().get(PROP_PASSWORD);
+        } else {
+            pwd = poolProperties.getPassword();
+            getAttributes().put(PROP_PASSWORD, pwd);
+        }
+        Properties properties = PoolUtilities.clone(poolProperties.getDbProperties());
+        if (usr != null) properties.setProperty(PROP_USER, usr);
+        if (pwd != null) properties.setProperty(PROP_PASSWORD, pwd);
+
+        try {
+            connection = connection = driver.connect(driverURL, properties);
+        } catch (Exception x) {
+            if (log.isDebugEnabled()) {
+                log.debug("Unable to connect to database.", x);
+            }
+            if (parent.jmxPool!=null) {
+                parent.jmxPool.notify(org.apache.tomcat.jdbc.pool.jmx.ConnectionPool.NOTIFY_CONNECT,
+                        ConnectionPool.getStackTrace(x));
+            }
+            if (x instanceof SQLException) {
+                throw (SQLException)x;
+            } else {
+                SQLException ex = new SQLException(x.getMessage());
+                ex.initCause(x);
+                throw ex;
+            }
+        }
+        if (connection==null) {
+            throw new SQLException("Driver:"+driver+" returned null for URL:"+driverURL);
+        }
+    }
+    
+    /**
+     * 
+     * @return true if connect() was called successfully and disconnect has not yet been called
+     */
+    public boolean isInitialized() {
+        return connection!=null;
+    }
+
+    /**
+     * Issues a call to {@link #disconnect(boolean)} with the argument false followed by a call to 
+     * {@link #connect()}
+     * @throws SQLException if the call to {@link #connect()} fails.
+     */
+    public void reconnect() throws SQLException {
+        this.disconnect(false);
+        this.connect();
+    } //reconnect
+
+    /**
+     * Disconnects the connection. All exceptions are logged using debug level.
+     * @param finalize if set to true, a call to {@link ConnectionPool#finalize(PooledConnection)} is called.
+     */
+    private void disconnect(boolean finalize) {
+        if (isDiscarded()) {
+            return;
+        }
+        setDiscarded(true);
+        if (connection != null) {
+            try {
+                parent.disconnectEvent(this, finalize);
+                if (xaConnection == null) {
+                    connection.close();
+                } else {
+                    xaConnection.close();
+                }
+            }catch (Exception ignore) {
+                if (log.isDebugEnabled()) {
+                    log.debug("Unable to close underlying SQL connection",ignore);
+                }
+            }
+        }
+        connection = null;
+        xaConnection = null;
+        lastConnected = -1;
+        if (finalize) parent.finalize(this);
+    }
+
+
+//============================================================================
+//             
+//============================================================================
+
+    /**
+     * Returns abandon timeout in milliseconds
+     * @return abandon timeout in milliseconds
+     */
+    public long getAbandonTimeout() {
+        if (poolProperties.getRemoveAbandonedTimeout() <= 0) {
+            return Long.MAX_VALUE;
+        } else {
+            return poolProperties.getRemoveAbandonedTimeout()*1000;
+        } //end if
+    }
+
+    /**
+     * Returns true if the connection pool is configured 
+     * to do validation for a certain action.
+     * @param action
+     * @return
+     */
+    private boolean doValidate(int action) {
+        if (action == PooledConnection.VALIDATE_BORROW &&
+            poolProperties.isTestOnBorrow())
+            return true;
+        else if (action == PooledConnection.VALIDATE_RETURN &&
+                 poolProperties.isTestOnReturn())
+            return true;
+        else if (action == PooledConnection.VALIDATE_IDLE &&
+                 poolProperties.isTestWhileIdle())
+            return true;
+        else if (action == PooledConnection.VALIDATE_INIT &&
+                 poolProperties.isTestOnConnect())
+            return true;
+        else if (action == PooledConnection.VALIDATE_INIT &&
+                 poolProperties.getInitSQL()!=null)
+           return true;
+        else
+            return false;
+    }
+
+    /**Returns true if the object is still valid. if not
+     * the pool will call the getExpiredAction() and follow up with one
+     * of the four expired methods
+     */
+    public boolean validate(int validateAction) {
+        return validate(validateAction,null);
+    }
+
+    /**
+     * Validates a connection. 
+     * @param validateAction the action used. One of {@link #VALIDATE_BORROW}, {@link #VALIDATE_IDLE}, 
+     * {@link #VALIDATE_INIT} or {@link #VALIDATE_RETURN}
+     * @param sql the SQL to be used during validation. If the {@link PoolConfiguration#setInitSQL(String)} has been called with a non null 
+     * value and the action is {@link #VALIDATE_INIT} the init SQL will be used for validation.
+     *  
+     * @return true if the connection was validated successfully. It returns true even if validation was not performed, such as when 
+     * {@link PoolConfiguration#setValidationInterval(long)} has been called with a positive value. 
+     * <p>
+     * false if the validation failed. The caller should close the connection if false is returned since a session could have been left in 
+     * an unknown state during initialization.
+     */
+    public boolean validate(int validateAction,String sql) {
+        if (this.isDiscarded()) {
+            return false;
+        }
+        
+        if (!doValidate(validateAction)) {
+            //no validation required, no init sql and props not set
+            return true;
+        }
+
+        //Don't bother validating if already have recently enough
+        long now = System.currentTimeMillis();
+        if (validateAction!=VALIDATE_INIT &&
+            poolProperties.getValidationInterval() > 0 &&
+            (now - this.lastValidated) <
+            poolProperties.getValidationInterval()) {
+            return true;
+        }
+
+        if (poolProperties.getValidator() != null) {
+            if (poolProperties.getValidator().validate(connection, validateAction)) {
+                this.lastValidated = now;
+                return true;
+            } else {
+                return false;
+            }
+        }
+        
+        String query = sql;
+        
+        if (validateAction == VALIDATE_INIT && poolProperties.getInitSQL() != null) {
+            query = poolProperties.getInitSQL();
+        }
+
+        if (query == null) {
+            query = poolProperties.getValidationQuery();
+        }
+        
+        Statement stmt = null;
+        try {
+            stmt = connection.createStatement();
+            stmt.execute(query);
+            stmt.close();
+            this.lastValidated = now;
+            return true;
+        } catch (Exception ignore) {
+            if (log.isDebugEnabled())
+                log.debug("Unable to validate object:",ignore);
+            if (stmt!=null)
+                try { stmt.close();} catch (Exception ignore2){/*NOOP*/}
+        }
+        return false;
+    } //validate
+
+    /**
+     * The time limit for how long the object
+     * can remain unused before it is released
+     * @return {@link PoolConfiguration#getMinEvictableIdleTimeMillis()}
+     */
+    public long getReleaseTime() {
+        return this.poolProperties.getMinEvictableIdleTimeMillis();
+    }
+
+    /**
+     * This method is called if (Now - timeCheckedIn > getReleaseTime())
+     * This method disconnects the connection, logs an error in debug mode if it happens
+     * then sets the {@link #released} flag to false. Any attempts to connect this cached object again
+     * will fail per {@link #connect()}
+     * The connection pool uses the atomic return value to decrement the pool size counter.
+     * @return true if this is the first time this method has been called. false if this method has been called before.
+     */
+    public boolean release() {
+        try {
+            disconnect(true);
+        } catch (Exception x) {
+            if (log.isDebugEnabled()) {
+                log.debug("Unable to close SQL connection",x);
+            }
+        }
+        return released.compareAndSet(false, true);
+
+    }
+
+    /**
+     * The pool will set the stack trace when it is check out and
+     * checked in
+     * @param trace the stack trace for this connection
+     */
+
+    public void setStackTrace(String trace) {
+        abandonTrace = trace;
+    }
+
+    /**
+     * Returns the stack trace from when this connection was borrowed. Can return null if no stack trace was set.
+     * @return the stack trace or null of no trace was set
+     */
+    public String getStackTrace() {
+        return abandonTrace;
+    }
+
+    /**
+     * Sets a timestamp on this connection. A timestamp usually means that some operation
+     * performed successfully.
+     * @param timestamp the timestamp as defined by {@link System#currentTimeMillis()}
+     */
+    public void setTimestamp(long timestamp) {
+        this.timestamp = timestamp;
+        setSuspect(false);
+    }
+
+
+    public boolean isSuspect() {
+        return suspect;
+    }
+
+    public void setSuspect(boolean suspect) {
+        this.suspect = suspect;
+    }
+
+    /**
+     * An interceptor can call this method with the value true, and the connection will be closed when it is returned to the pool.
+     * @param discarded - only valid value is true
+     * @throws IllegalStateException if this method is called with the value false and the value true has already been set.
+     */
+    public void setDiscarded(boolean discarded) {
+        if (this.discarded && !discarded) throw new IllegalStateException("Unable to change the state once the connection has been discarded");
+        this.discarded = discarded;
+    }
+
+    /**
+     * Set the timestamp the connection was last validated.
+     * This flag is used to keep track when we are using a {@link PoolConfiguration#setValidationInterval(long) validation-interval}.
+     * @param lastValidated a timestamp as defined by {@link System#currentTimeMillis()} 
+     */
+    public void setLastValidated(long lastValidated) {
+        this.lastValidated = lastValidated;
+    }
+
+    /**
+     * Sets the pool configuration for this connection and connection pool.
+     * Object is shared with the {@link ConnectionPool}
+     * @param poolProperties
+     */
+    public void setPoolProperties(PoolConfiguration poolProperties) {
+        this.poolProperties = poolProperties;
+    }
+
+    /**
+     * Return the timestamps of last pool action. Timestamps are typically set when connections 
+     * are borrowed from the pool. It is used to keep track of {@link PoolConfiguration#setRemoveAbandonedTimeout(int) abandon-timeouts}.
+     * This timestamp can also be reset by the {@link org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer#invoke(Object, java.lang.reflect.Method, Object[])}   
+     * @return the timestamp of the last pool action as defined by {@link System#currentTimeMillis()}
+     */
+    public long getTimestamp() {
+        return timestamp;
+    }
+
+    /**
+     * Returns the discarded flag.
+     * @return the discarded flag. If the value is true, 
+     * either {@link #disconnect(boolean)} has been called or it will be called when the connection is returned to the pool.
+     */
+    public boolean isDiscarded() {
+        return discarded;
+    }
+
+    /**
+     * Returns the timestamp of the last successful validation query execution. 
+     * @return the timestamp of the last successful validation query execution as defined by {@link System#currentTimeMillis()}
+     */
+    public long getLastValidated() {
+        return lastValidated;
+    }
+
+    /**
+     * Returns the configuration for this connection and pool
+     * @return the configuration for this connection and pool
+     */
+    public PoolConfiguration getPoolProperties() {
+        return poolProperties;
+    }
+
+    /**
+     * Locks the connection only if either {@link PoolConfiguration#isPoolSweeperEnabled()} or 
+     * {@link PoolConfiguration#getUseLock()} return true. The per connection lock ensures thread safety is
+     * multiple threads are performing operations on the connection. 
+     * Otherwise this is a noop for performance
+     */
+    public void lock() {
+        if (poolProperties.getUseLock() || this.poolProperties.isPoolSweeperEnabled()) {
+            //optimized, only use a lock when there is concurrency
+            lock.writeLock().lock();
+        }
+    }
+
+    /**
+     * Unlocks the connection only if the sweeper is enabled
+     * Otherwise this is a noop for performance
+     */
+    public void unlock() {
+        if (poolProperties.getUseLock() || this.poolProperties.isPoolSweeperEnabled()) {
+          //optimized, only use a lock when there is concurrency
+            lock.writeLock().unlock();
+        }
+    }
+
+    /**
+     * Returns the underlying connection
+     * @return the underlying JDBC connection as it was returned from the JDBC driver
+     * @see javax.sql.PooledConnection#getConnection()
+     */
+    public java.sql.Connection getConnection() {
+        return this.connection;
+    }
+    
+    /**
+     * Returns the underlying XA connection
+     * @return the underlying XA connection as it was returned from the Datasource
+     */
+    public javax.sql.XAConnection getXAConnection() {
+        return this.xaConnection;
+    }
+    
+    
+    /**
+     * Returns the timestamp of when the connection was last connected to the database.
+     * ie, a successful call to {@link java.sql.Driver#connect(String, java.util.Properties)}.
+     * @return the timestamp when this connection was created as defined by {@link System#currentTimeMillis()}
+     */
+    public long getLastConnected() {
+        return lastConnected;
+    }
+
+    /**
+     * Returns the first handler in the interceptor chain
+     * @return the first interceptor for this connection
+     */
+    public JdbcInterceptor getHandler() {
+        return handler;
+    }
+
+    public void setHandler(JdbcInterceptor handler) {
+        if (this.handler!=null && this.handler!=handler) {
+            JdbcInterceptor interceptor = this.handler;
+            while (interceptor!=null) {
+                interceptor.reset(null, null);
+                interceptor = interceptor.getNext();
+            }//while 
+        }//end if
+        this.handler = handler;
+    }
+    
+    @Override
+    public String toString() {
+        return "PooledConnection["+(connection!=null?connection.toString():"null")+"]";
+    }
+    
+    /**
+     * Returns true if this connection has been released and wont be reused.
+     * @return true if the method {@link #release()} has been called
+     */
+    public boolean isReleased() {
+        return released.get();
+    }
+    
+    public HashMap<Object,Object> getAttributes() {
+        return attributes;
+    }
+
+}
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ProxyConnection.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ProxyConnection.java
new file mode 100644 (file)
index 0000000..532cb6a
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * 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.pool;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.sql.SQLException;
+
+import javax.sql.XAConnection;
+/**
+ * A ProxyConnection object is the bottom most interceptor that wraps an object of type 
+ * {@link PooledConnection}. The ProxyConnection intercepts three methods:
+ * <ul>
+ *   <li>{@link java.sql.Connection#close()} - returns the connection to the pool. May be called multiple times.</li>
+ *   <li>{@link java.lang.Object#toString()} - returns a custom string for this object</li>
+ *   <li>{@link javax.sql.PooledConnection#getConnection()} - returns the underlying connection</li>
+ * </ul>
+ * By default method comparisons is done on a String reference level, unless the {@link PoolConfiguration#setUseEquals(boolean)} has been called
+ * with a <code>true</code> argument.
+ * @author Filip Hanik
+ */
+public class ProxyConnection extends JdbcInterceptor {
+
+    protected PooledConnection connection = null;
+
+    protected ConnectionPool pool = null;
+
+    public PooledConnection getConnection() {
+        return connection;
+    }
+
+    public void setConnection(PooledConnection connection) {
+        this.connection = connection;
+    }
+
+    public ConnectionPool getPool() {
+        return pool;
+    }
+
+    public void setPool(ConnectionPool pool) {
+        this.pool = pool;
+    }
+
+    protected ProxyConnection(ConnectionPool parent, PooledConnection con, boolean useEquals) throws SQLException {
+        pool = parent;
+        connection = con;
+        setUseEquals(useEquals);
+    }
+
+    @Override
+    public void reset(ConnectionPool parent, PooledConnection con) {
+        this.pool = parent;
+        this.connection = con;
+    }
+
+    public boolean isWrapperFor(Class<?> iface) throws SQLException {
+        if (iface == XAConnection.class && connection.getXAConnection()!=null) {
+            return true;
+        } else {
+            return (iface.isInstance(connection.getConnection()));
+        }
+    }
+
+
+    public Object unwrap(Class<?> iface) throws SQLException {
+        if (iface == PooledConnection.class) {
+            return connection;
+        }else if (iface == XAConnection.class) {
+            return connection.getXAConnection();
+        } else if (isWrapperFor(iface)) {
+            return connection.getConnection();
+        } else {
+            throw new SQLException("Not a wrapper of "+iface.getName());
+        }
+    }
+
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+        if (compare(ISCLOSED_VAL,method)) {
+            return Boolean.valueOf(isClosed());
+        }
+        if (compare(CLOSE_VAL,method)) {
+            if (isClosed()) return null; //noop for already closed.
+            PooledConnection poolc = this.connection;
+            this.connection = null;
+            pool.returnConnection(poolc);
+            return null;
+        } else if (compare(TOSTRING_VAL,method)) {
+            return this.toString();
+        } else if (compare(GETCONNECTION_VAL,method) && connection!=null) {
+            return connection.getConnection();
+        } else if (method.getDeclaringClass().equals(XAConnection.class)) {
+            try {
+                return method.invoke(connection.getXAConnection(),args);
+            }catch (Throwable t) {
+                if (t instanceof InvocationTargetException) {
+                    InvocationTargetException it = (InvocationTargetException)t;
+                    throw it.getCause()!=null?it.getCause():it;
+                } else {
+                    throw t;
+                }
+            }
+        }
+        if (isClosed()) throw new SQLException("Connection has already been closed.");
+        if (compare(UNWRAP_VAL,method)) {
+            return unwrap((Class<?>)args[0]);
+        } else if (compare(ISWRAPPERFOR_VAL,method)) {
+            return this.isWrapperFor((Class<?>)args[0]);
+        }
+        try {
+            return method.invoke(connection.getConnection(),args);
+        }catch (Throwable t) {
+            if (t instanceof InvocationTargetException) {
+                InvocationTargetException it = (InvocationTargetException)t;
+                throw it.getCause()!=null?it.getCause():it;
+            } else {
+                throw t;
+            }
+        }
+    }
+    
+    public boolean isClosed() {
+        return connection==null || connection.isDiscarded();
+    }
+
+    public PooledConnection getDelegateConnection() {
+        return connection;
+    }
+
+    public ConnectionPool getParentPool() {
+        return pool;
+    }
+    
+    @Override
+    public String toString() {
+        return "ProxyConnection["+(connection!=null?connection.toString():"null")+"]";
+    }
+
+}
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/Validator.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/Validator.java
new file mode 100644 (file)
index 0000000..4f286ef
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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.pool;
+
+import java.sql.Connection;
+
+/**
+ * Interface to be implemented by custom validator classes.
+ * 
+ * @author mpassell
+ */
+public interface Validator {
+    /**
+     * Validate a connection and return a boolean to indicate if it's valid.
+     * 
+     * @param connection the Connection object to test
+     * @param validateAction the action used. One of {@link PooledConnection#VALIDATE_BORROW},
+     *   {@link PooledConnection#VALIDATE_IDLE}, {@link PooledConnection#VALIDATE_INIT} or
+     *   {@link PooledConnection#VALIDATE_RETURN}
+     * @return true if the connection is valid
+     */
+    public boolean validate(Connection connection, int validateAction);
+}
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/XADataSource.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/XADataSource.java
new file mode 100644 (file)
index 0000000..ce829d3
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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.pool;
+
+public class XADataSource extends DataSource implements javax.sql.XADataSource {
+
+    /**
+     * Constructor for reflection only. A default set of pool properties will be created.
+     */
+    public XADataSource() {
+        super();
+    }
+
+    /**
+     * Constructs a DataSource object wrapping a connection
+     * @param poolProperties
+     */
+    public XADataSource(PoolConfiguration poolProperties) {
+        super(poolProperties);
+    }
+
+}
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractCreateStatementInterceptor.java
new file mode 100644 (file)
index 0000000..19a13ed
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * 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.pool.interceptor;
+
+import java.lang.reflect.Method;
+
+import org.apache.tomcat.jdbc.pool.ConnectionPool;
+import org.apache.tomcat.jdbc.pool.JdbcInterceptor;
+import org.apache.tomcat.jdbc.pool.PooledConnection;
+
+/**
+ * Abstraction interceptor. This component intercepts all calls to create some type of SQL statement.
+ * By extending this class, one can intercept queries and update statements by overriding the {@link #createStatement(Object, Method, Object[], Object, long)}
+ * method.
+ * @author Filip Hanik
+ * @version 1.0
+ */
+public abstract class  AbstractCreateStatementInterceptor extends JdbcInterceptor {
+    protected static final String CREATE_STATEMENT      = "createStatement";
+    protected static final int    CREATE_STATEMENT_IDX  = 0;
+    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_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;
+    
+    protected static final String EXECUTE        = "execute";
+    protected static final String EXECUTE_QUERY  = "executeQuery";
+    protected static final String EXECUTE_UPDATE = "executeUpdate";
+    protected static final String EXECUTE_BATCH  = "executeBatch";
+
+    protected static final String[] EXECUTE_TYPES = {EXECUTE, EXECUTE_QUERY, EXECUTE_UPDATE, EXECUTE_BATCH};
+
+    public  AbstractCreateStatementInterceptor() {
+        super();
+    }
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+        if (compare(CLOSE_VAL,method)) {
+            closeInvoked();
+            return super.invoke(proxy, method, args);
+        } else {
+            boolean process = false;
+            process = isStatement(method, process);
+            if (process) {
+                long start = System.currentTimeMillis();
+                Object statement = super.invoke(proxy,method,args);
+                long delta = System.currentTimeMillis() - start;
+                return createStatement(proxy,method,args,statement, delta);
+            } else {
+                return super.invoke(proxy,method,args);
+            }
+        }
+    }
+    
+    /**
+     * This method will be invoked after a successful statement creation. This method can choose to return a wrapper
+     * around the statement or return the statement itself.
+     * If this method returns a wrapper then it should return a wrapper object that implements one of the following interfaces.
+     * {@link java.sql.Statement}, {@link java.sql.PreparedStatement} or {@link java.sql.CallableStatement}
+     * @param proxy the actual proxy object
+     * @param method the method that was called. It will be one of the methods defined in {@link #STATEMENT_TYPES}
+     * @param args the arguments to the method
+     * @param statement the statement that the underlying connection created
+     * @return a {@link java.sql.Statement} object
+     */
+    public abstract Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time);
+    
+    /**
+     * Method invoked when the operation {@link java.sql.Connection#close()} is invoked. 
+     */
+    public abstract void closeInvoked();
+
+    /**
+     * Returns true if the method that is being invoked matches one of the statement types.
+     * 
+     * @param method the method being invoked on the proxy
+     * @param process boolean result used for recursion
+     * @return returns true if the method name matched
+     */
+    protected boolean isStatement(Method method, boolean process){
+        return process(STATEMENT_TYPES, method, process);
+    }
+
+    /**
+     * Returns true if the method that is being invoked matches one of the execute types.
+     * 
+     * @param method the method being invoked on the proxy
+     * @param process boolean result used for recursion
+     * @return returns true if the method name matched
+     */
+    protected boolean isExecute(Method method, boolean process){
+        return process(EXECUTE_TYPES, method, process);
+    }
+
+    /*
+     * Returns true if the method that is being invoked matches one of the method names passed in
+     * @param names list of method names that we want to intercept
+     * @param method the method being invoked on the proxy
+     * @param process boolean result used for recursion
+     * @return returns true if the method name matched
+     */
+    protected boolean process(String[] names, Method method, boolean process) {
+        final String name = method.getName();
+        for (int i=0; (!process) && i<names.length; i++) {
+            process = compare(names[i],name);
+        }
+        return process;
+    }
+    
+    /**
+     * no-op for this interceptor. no state is stored.
+     */
+    @Override
+    public void reset(ConnectionPool parent, PooledConnection con) {
+        // NOOP
+    }
+}
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractQueryReport.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/AbstractQueryReport.java
new file mode 100644 (file)
index 0000000..198cc8a
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ *  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.pool.interceptor;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.jdbc.pool.JdbcInterceptor;
+/**
+ * Abstract class that wraps statements and intercepts query executions.
+ * @author fhanik
+ *
+ */
+public abstract class AbstractQueryReport extends AbstractCreateStatementInterceptor {
+    //logger
+    private static final Log log = LogFactory.getLog(AbstractQueryReport.class);
+
+    /**
+     * The threshold in milliseconds. If the query is faster than this, we don't measure it
+     */
+    protected long threshold = 1000; //don't report queries less than this
+    
+    /**
+     * the constructors that are used to create statement proxies 
+     */
+    protected static final Constructor<?>[] constructors =
+        new Constructor[AbstractCreateStatementInterceptor.STATEMENT_TYPE_COUNT];
+
+    
+    public AbstractQueryReport() {
+        super();
+    }
+    
+    /**
+     * Invoked when prepareStatement has been called and completed.
+     * @param sql - the string used to prepare the statement with
+     * @param time - the time it took to invoke prepare
+     */
+    protected abstract void prepareStatement(String sql, long time);
+    
+    /**
+     * Invoked when prepareCall has been called and completed.
+     * @param query - the string used to prepare the statement with
+     * @param time - the time it took to invoke prepare
+     */
+    protected abstract void prepareCall(String query, long time);
+
+    /**
+     * Invoked when a query execution, a call to execute/executeQuery or executeBatch failed.
+     * @param query the query that was executed and failed
+     * @param args the arguments to the execution
+     * @param name the name of the method used to execute {@link AbstractCreateStatementInterceptor#isExecute(Method, boolean)}
+     * @param start the time the query execution started
+     * @param t the exception that happened
+     * @return - the SQL that was executed or the string &quot;batch&quot; if it was a batch execution 
+     */
+    protected String reportFailedQuery(String query, Object[] args, final String name, long start, Throwable t) {
+        //extract the query string
+        String sql = (query==null && args!=null &&  args.length>0)?(String)args[0]:query;
+        //if we do batch execution, then we name the query 'batch'
+        if (sql==null && compare(EXECUTE_BATCH,name)) {
+            sql = "batch";
+        }
+        return sql;
+    }
+
+    /**
+     * Invoked when a query execution, a call to execute/executeQuery or executeBatch succeeded and was within the timing threshold
+     * @param query the query that was executed and failed
+     * @param args the arguments to the execution
+     * @param name the name of the method used to execute {@link AbstractCreateStatementInterceptor#isExecute(Method, boolean)}
+     * @param start the time the query execution started
+     * @param delta the time the execution took
+     * @return - the SQL that was executed or the string &quot;batch&quot; if it was a batch execution 
+     */
+    protected String reportQuery(String query, Object[] args, final String name, long start, long delta) {
+        //extract the query string
+        String sql = (query==null && args!=null &&  args.length>0)?(String)args[0]:query;
+        //if we do batch execution, then we name the query 'batch'
+        if (sql==null && compare(EXECUTE_BATCH,name)) {
+            sql = "batch";
+        }
+        return sql;
+    }
+
+    /**
+     * Invoked when a query execution, a call to execute/executeQuery or executeBatch succeeded and was exceeded the timing threshold
+     * @param query the query that was executed and failed
+     * @param args the arguments to the execution
+     * @param name the name of the method used to execute {@link AbstractCreateStatementInterceptor#isExecute(Method, boolean)}
+     * @param start the time the query execution started
+     * @param delta the time the execution took
+     * @return - the SQL that was executed or the string &quot;batch&quot; if it was a batch execution 
+     */
+    protected String reportSlowQuery(String query, Object[] args, final String name, long start, long delta) {
+        //extract the query string
+        String sql = (query==null && args!=null &&  args.length>0)?(String)args[0]:query;
+        //if we do batch execution, then we name the query 'batch'
+        if (sql==null && compare(EXECUTE_BATCH,name)) {
+            sql = "batch";
+        }
+        return sql;
+    }
+    
+    /**
+     * returns the query measure threshold.
+     * This value is in milliseconds. If the query is faster than this threshold than it wont be accounted for
+     * @return the threshhold in milliseconds
+     */
+    public long getThreshold() {
+        return threshold;
+    }
+
+    /**
+     * Sets the query measurement threshold. The value is in milliseconds.
+     * If the query goes faster than this threshold it will not be recorded.
+     * @param threshold set to -1 to record every query. Value is in milliseconds.
+     */
+    public void setThreshold(long threshold) {
+        this.threshold = threshold;
+    }
+
+    /**
+     * Creates a constructor for a proxy class, if one doesn't already exist
+     * @param idx - the index of the constructor
+     * @param clazz - the interface that the proxy will implement
+     * @return - returns a constructor used to create new instances
+     * @throws NoSuchMethodException
+     */
+    protected Constructor<?> getConstructor(int idx, Class<?> clazz) throws NoSuchMethodException {
+        if (constructors[idx]==null) {
+            Class<?> proxyClass = Proxy.getProxyClass(SlowQueryReport.class.getClassLoader(), new Class[] {clazz});
+            constructors[idx] = proxyClass.getConstructor(new Class[] { InvocationHandler.class });
+        }
+        return constructors[idx];
+    }
+
+    /**
+     * Creates a statement interceptor to monitor query response times
+     */
+    @Override
+    public Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time) {
+        try {
+            Object result = null;
+            String name = method.getName();
+            String sql = null;
+            Constructor<?> constructor = null;
+            if (compare(CREATE_STATEMENT,name)) {
+                //createStatement
+                constructor = getConstructor(CREATE_STATEMENT_IDX,Statement.class);
+            }else if (compare(PREPARE_STATEMENT,name)) {
+                //prepareStatement
+                sql = (String)args[0];
+                constructor = getConstructor(PREPARE_STATEMENT_IDX,PreparedStatement.class);
+                if (sql!=null) {
+                    prepareStatement(sql, time);
+                }
+            }else if (compare(PREPARE_CALL,name)) {
+                //prepareCall
+                sql = (String)args[0];
+                constructor = getConstructor(PREPARE_CALL_IDX,CallableStatement.class);
+                prepareCall(sql,time);
+            }else {
+                //do nothing, might be a future unsupported method
+                //so we better bail out and let the system continue
+                return statement;
+            }
+            result = constructor.newInstance(new Object[] { new StatementProxy(statement,sql) });
+            return result;
+        }catch (Exception x) {
+            log.warn("Unable to create statement proxy for slow query report.",x);
+        }
+        return statement;
+    }
+
+
+    /**
+     * Class to measure query execute time
+     * @author fhanik
+     *
+     */
+    protected class StatementProxy implements InvocationHandler {
+        protected boolean closed = false;
+        protected Object delegate;
+        protected final String query;
+        public StatementProxy(Object parent, String query) {
+            this.delegate = parent;
+            this.query = query;
+        }
+        
+        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.");
+            boolean process = false;
+            //check to see if we are about to execute a query
+            process = isExecute( method, process);
+            //if we are executing, get the current time
+            long start = (process)?System.currentTimeMillis():0;
+            Object result =  null;
+            try {
+                //execute the query
+                result =  method.invoke(delegate,args);
+            }catch (Throwable t) {
+                reportFailedQuery(query,args,name,start,t);
+                if (t instanceof InvocationTargetException) {
+                    InvocationTargetException it = (InvocationTargetException)t;
+                    throw it.getCause()!=null?it.getCause():it;
+                } else {
+                    throw t;
+                }
+            }
+            //measure the time
+            long delta = (process)?(System.currentTimeMillis()-start):Long.MIN_VALUE;
+            //see if we meet the requirements to measure
+            if (delta>threshold) {
+                try {
+                    //report the slow query
+                    reportSlowQuery(query, args, name, start, delta);
+                }catch (Exception t) {
+                    if (log.isWarnEnabled()) log.warn("Unable to process slow query",t);
+                }
+            } else if (process) {
+                reportQuery(query, args, name, start, delta);
+            }
+            //perform close cleanup
+            if (close) {
+                closed=true;
+                delegate = null;
+            }
+            return result;
+        }
+    }    
+
+}
\ No newline at end of file
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ConnectionState.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ConnectionState.java
new file mode 100644 (file)
index 0000000..6da8bd5
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * 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.pool.interceptor;
+
+import java.lang.reflect.Method;
+import java.sql.SQLException;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.jdbc.pool.ConnectionPool;
+import org.apache.tomcat.jdbc.pool.DataSourceFactory;
+import org.apache.tomcat.jdbc.pool.JdbcInterceptor;
+import org.apache.tomcat.jdbc.pool.PoolConfiguration;
+import org.apache.tomcat.jdbc.pool.PooledConnection;
+
+/**
+ * Interceptor that keep track of connection state to avoid roundtrips to the database.
+ * The {@link org.apache.tomcat.jdbc.pool.ConnectionPool} is optimized to do as little work as possible.
+ * The pool itself doesn't remember settings like {@link java.sql.Connection#setAutoCommit(boolean)}, 
+ * {@link java.sql.Connection#setReadOnly(boolean)}, {@link java.sql.Connection#setCatalog(String)} or
+ * {@link java.sql.Connection#setTransactionIsolation(int)}. It relies on the application to remember how and when 
+ * these settings have been applied.
+ * In the cases where the application code doesn't know or want to keep track of the state, this interceptor helps cache the 
+ * state, and it also avoids roundtrips to the database asking for it.
+ * @author fhanik
+ *
+ */
+
+public class ConnectionState extends JdbcInterceptor  {
+    private static final Log log = LogFactory.getLog(ConnectionState.class);
+    
+    protected final String[] readState = {"getAutoCommit","getTransactionIsolation","isReadOnly","getCatalog"};
+    protected final String[] writeState = {"setAutoCommit","setTransactionIsolation","setReadOnly","setCatalog"};
+
+    protected Boolean autoCommit = null;
+    protected Integer transactionIsolation = null;
+    protected Boolean readOnly = null;
+    protected String catalog = null;
+    
+    
+    @Override
+    public void reset(ConnectionPool parent, PooledConnection con) {
+        if (parent==null || con==null) {
+            //we are resetting, reset our defaults
+            autoCommit = null;
+            transactionIsolation = null;
+            readOnly = null;
+            catalog = null;
+            return;
+        }
+        PoolConfiguration poolProperties = parent.getPoolProperties();
+        if (poolProperties.getDefaultTransactionIsolation()!=DataSourceFactory.UNKNOWN_TRANSACTIONISOLATION) {
+            try {
+                if (transactionIsolation==null || transactionIsolation.intValue()!=poolProperties.getDefaultTransactionIsolation()) {
+                    con.getConnection().setTransactionIsolation(poolProperties.getDefaultTransactionIsolation());
+                    transactionIsolation = Integer.valueOf(poolProperties.getDefaultTransactionIsolation());
+                }
+            }catch (SQLException x) {
+                transactionIsolation = null;
+                log.error("Unable to reset transaction isolation state to connection.",x);
+            }
+        }
+        if (poolProperties.getDefaultReadOnly()!=null) {
+            try {
+                if (readOnly==null || readOnly.booleanValue()!=poolProperties.getDefaultReadOnly().booleanValue()) {
+                    con.getConnection().setReadOnly(poolProperties.getDefaultReadOnly().booleanValue());
+                    readOnly = poolProperties.getDefaultReadOnly();
+                }
+            }catch (SQLException x) {
+                readOnly = null;
+                log.error("Unable to reset readonly state to connection.",x);
+            }
+        }
+        if (poolProperties.getDefaultAutoCommit()!=null) {
+            try {
+                if (autoCommit==null || autoCommit.booleanValue()!=poolProperties.getDefaultAutoCommit().booleanValue()) {
+                    con.getConnection().setAutoCommit(poolProperties.getDefaultAutoCommit().booleanValue());
+                    autoCommit = poolProperties.getDefaultAutoCommit();
+                }
+            }catch (SQLException x) {
+                autoCommit = null;
+                log.error("Unable to reset autocommit state to connection.",x);
+            }
+        }
+        if (poolProperties.getDefaultCatalog()!=null) {
+            try {
+                if (catalog==null || (!catalog.equals(poolProperties.getDefaultCatalog()))) {
+                    con.getConnection().setCatalog(poolProperties.getDefaultCatalog());
+                    catalog = poolProperties.getDefaultCatalog();
+                }
+            }catch (SQLException x) {
+                catalog = null;
+                log.error("Unable to reset default catalog state to connection.",x);
+            }
+        }
+        
+    }
+
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+        String name = method.getName();
+        boolean read = false;
+        int index = -1;
+        for (int i=0; (!read) && i<readState.length; i++) {
+            read = compare(name,readState[i]);
+            if (read) index = i;
+        }
+        boolean write = false;
+        for (int i=0; (!write) && (!read) && i<writeState.length; i++) {
+            write = compare(name,writeState[i]);
+            if (write) index = i;
+        }
+        Object result = null;
+        if (read) {
+            switch (index) {
+                case 0:{result = autoCommit; break;}
+                case 1:{result = transactionIsolation; break;}
+                case 2:{result = readOnly; break;}
+                case 3:{result = catalog; break;}
+                default: result = null;
+            }
+            //return cached result, if we have it
+            if (result!=null) return result;
+        }
+
+        result = super.invoke(proxy, method, args);
+        if (read || write) {
+            switch (index) {
+                case 0:{autoCommit = (Boolean) (read?result:args[0]); break;}
+                case 1:{transactionIsolation = (Integer)(read?result:args[0]); break;}
+                case 2:{readOnly = (Boolean)(read?result:args[0]); break;}
+                case 3:{catalog = (String)(read?result:args[0]); break;}
+            }
+        }
+        return result;
+    }
+
+}
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ResetAbandonedTimer.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/ResetAbandonedTimer.java
new file mode 100644 (file)
index 0000000..328d6be
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ *  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.pool.interceptor;
+
+import java.lang.reflect.Method;
+
+import org.apache.tomcat.jdbc.pool.JdbcInterceptor;
+import org.apache.tomcat.jdbc.pool.PooledConnection;
+import org.apache.tomcat.jdbc.pool.ProxyConnection;
+
+/**
+ * Class that resets the abandoned timer on any activity on the 
+ * Connection or any successful query executions.
+ * This interceptor is useful for when you have a {@link org.apache.tomcat.jdbc.pool.PoolConfiguration#setRemoveAbandonedTimeout(int)}
+ * that is fairly low, and you want to reset the abandoned time each time any operation on the connection is performed
+ * This is useful for batch processing programs that use connections for extensive amount of times.
+ * @author fhanik
+ *
+ */
+public class ResetAbandonedTimer extends AbstractQueryReport {
+
+    public ResetAbandonedTimer() {
+        // TODO Auto-generated constructor stub
+    }
+    
+    public boolean resetTimer() {
+        boolean result = false;
+        JdbcInterceptor interceptor = this.getNext();
+        while (interceptor!=null && result==false) {
+            if (interceptor instanceof ProxyConnection) {
+                PooledConnection con = ((ProxyConnection)interceptor).getConnection();
+                if (con!=null) {
+                    con.setTimestamp(System.currentTimeMillis());
+                    result = true;
+                } else {
+                    break;
+                }
+            }
+            interceptor = interceptor.getNext();
+        }
+        return result;
+    }
+
+
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+        // TODO Auto-generated method stub
+        Object result = super.invoke(proxy, method, args);
+        resetTimer();
+        return result;
+    }
+
+    @Override
+    protected void prepareCall(String query, long time) {
+        resetTimer();
+    }
+
+    @Override
+    protected void prepareStatement(String sql, long time) {
+        resetTimer();
+
+    }
+
+    @Override
+    public void closeInvoked() {
+        resetTimer();
+    }
+
+    @Override
+    protected String reportQuery(String query, Object[] args, String name,long start, long delta) {
+        resetTimer();
+        return super.reportQuery(query, args, name, start, delta);
+    }
+
+    @Override
+    protected String reportSlowQuery(String query, Object[] args, String name,long start, long delta) {
+        resetTimer();
+        return super.reportSlowQuery(query, args, name, start, delta);
+    }
+}
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReport.java
new file mode 100644 (file)
index 0000000..85b0779
--- /dev/null
@@ -0,0 +1,405 @@
+/*
+ * 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.pool.interceptor;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.jdbc.pool.ConnectionPool;
+import org.apache.tomcat.jdbc.pool.PooledConnection;
+import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty;
+
+/**
+ * Slow query report interceptor. Tracks timing of query executions.
+ * @author Filip Hanik
+ * @version 1.0
+ */
+public class SlowQueryReport extends AbstractQueryReport  {
+    //logger
+    private static final Log log = LogFactory.getLog(SlowQueryReport.class);
+
+    /**
+     * we will be keeping track of query stats on a per pool basis
+     */
+    protected static ConcurrentHashMap<String,ConcurrentHashMap<String,QueryStats>> perPoolStats = 
+        new ConcurrentHashMap<String,ConcurrentHashMap<String,QueryStats>>();
+    /**
+     * the queries that are used for this interceptor.
+     */
+    protected ConcurrentHashMap<String,QueryStats> queries = null;
+    /**
+     * Maximum number of queries we will be storing
+     */
+    protected int  maxQueries= 1000; //don't store more than this amount of queries
+    
+    /**
+     * Returns the query stats for a given pool
+     * @param poolname - the name of the pool we want to retrieve stats for
+     * @return a hash map containing statistics for 0 to maxQueries 
+     */
+    public static ConcurrentHashMap<String,QueryStats> getPoolStats(String poolname) {
+        return perPoolStats.get(poolname);
+    }
+    
+    /**
+     * Creates a slow query report interceptor
+     */
+    public SlowQueryReport() {
+        super();
+    }
+
+    public void setMaxQueries(int maxQueries) {
+        this.maxQueries = maxQueries;
+    }
+
+
+    @Override
+    protected String reportFailedQuery(String query, Object[] args, String name, long start, Throwable t) {
+        String sql = super.reportFailedQuery(query, args, name, start, t);
+        if (this.maxQueries > 0 ) {
+            long now = System.currentTimeMillis();
+            long delta = now - start;
+            QueryStats qs = this.getQueryStats(sql);
+            qs.failure(delta, now);
+        }
+        return sql;
+    }
+
+    @Override
+    protected String reportSlowQuery(String query, Object[] args, String name, long start, long delta) {
+        String sql = super.reportSlowQuery(query, args, name, start, delta);
+        if (this.maxQueries > 0 ) {
+            QueryStats qs = this.getQueryStats(sql);
+            qs.add(delta, start);
+        }
+        return sql;
+    }
+
+    /**
+     * invoked when the connection receives the close request
+     * Not used for now.
+     */
+    @Override
+    public void closeInvoked() {
+        queries = null;
+    }
+    
+    @Override
+    public void prepareStatement(String sql, long time) {
+        QueryStats qs = getQueryStats(sql);
+        qs.prepare(time, System.currentTimeMillis());
+    }
+    
+    @Override
+    public void prepareCall(String sql, long time) {
+        QueryStats qs = getQueryStats(sql);
+        qs.prepare(time, System.currentTimeMillis());
+    }
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void poolStarted(ConnectionPool pool) {
+        super.poolStarted(pool);
+        //see if we already created a map for this pool
+        queries = SlowQueryReport.perPoolStats.get(pool.getName());
+        if (queries==null) {
+            //create the map to hold our stats
+            //however TODO we need to improve the eviction
+            //selection
+            queries = new ConcurrentHashMap<String,QueryStats>() {
+                
+            };
+            if (perPoolStats.putIfAbsent(pool.getName(), queries)!=null) {
+                //there already was one
+                queries = SlowQueryReport.perPoolStats.get(pool.getName());
+            }
+        }
+    }
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void poolClosed(ConnectionPool pool) {
+        perPoolStats.remove(pool.getName());
+        super.poolClosed(pool);
+    }
+    
+    protected QueryStats getQueryStats(String sql) {
+        ConcurrentHashMap<String,QueryStats> queries = SlowQueryReport.this.queries;
+        if (queries==null) return null;
+        QueryStats qs = queries.get(sql);
+        if (qs == null) {
+            qs = new QueryStats(sql);
+            if (queries.putIfAbsent(sql,qs)!=null) {
+                qs = queries.get(sql);
+            } else {
+                //we added a new element, see if we need to remove the oldest
+                if (queries.size() > maxQueries) {
+                    removeOldest(queries);
+                }
+            }
+        }
+        return qs;
+    }
+    
+    /**
+     * TODO - implement a better algorithm
+     * @param queries
+     */
+    protected void removeOldest(ConcurrentHashMap<String,QueryStats> queries) {
+        Iterator<String> it = queries.keySet().iterator();
+        while (queries.size()>maxQueries && it.hasNext()) {
+            String sql = it.next();
+            it.remove();
+            if (log.isDebugEnabled()) log.debug("Removing slow query, capacity reached:"+sql);
+        } 
+    }
+
+
+    @Override
+    public void reset(ConnectionPool parent, PooledConnection con) {
+        super.reset(parent, con);
+        if (parent!=null) 
+            queries = SlowQueryReport.perPoolStats.get(parent.getName());
+    }
+
+
+    @Override
+    public void setProperties(Map<String, InterceptorProperty> properties) {
+        super.setProperties(properties);
+        final String threshold = "threshold";
+        final String maxqueries= "maxQueries";
+        InterceptorProperty p1 = properties.get(threshold);
+        InterceptorProperty p2 = properties.get(maxqueries);
+        if (p1!=null) {
+            setThreshold(Long.parseLong(p1.getValue()));
+        }
+        if (p2!=null) {
+            setMaxQueries(Integer.parseInt(p2.getValue()));
+        }
+    }
+
+
+    /**
+     * 
+     * @author fhanik
+     *
+     */
+    public static class QueryStats {
+        static final String[] FIELD_NAMES = new String[] {
+            "query",
+            "nrOfInvocations",
+            "maxInvocationTime",
+            "maxInvocationDate",
+            "minInvocationTime",
+            "minInvocationDate",
+            "totalInvocationTime",
+            "failures",
+            "prepareCount",
+            "prepareTime",
+            "lastInvocation"
+        };
+        
+        static final  String[] FIELD_DESCRIPTIONS = new String[] {
+            "The SQL query",
+            "The number of query invocations, a call to executeXXX",
+            "The longest time for this query in milliseconds",
+            "The time and date for when the longest query took place",
+            "The shortest time for this query in milliseconds",
+            "The time and date for when the shortest query took place",
+            "The total amount of milliseconds spent executing this query",
+            "The number of failures for this query",
+            "The number of times this query was prepared (prepareStatement/prepareCall)",
+            "The total number of milliseconds spent preparing this query",
+            "The date and time of the last invocation"
+        };
+        
+        static final OpenType[] FIELD_TYPES = new OpenType[] { 
+            SimpleType.STRING,
+            SimpleType.INTEGER,
+            SimpleType.LONG,
+            SimpleType.LONG,
+            SimpleType.LONG,
+            SimpleType.LONG,
+            SimpleType.LONG,
+            SimpleType.LONG,
+            SimpleType.INTEGER,
+            SimpleType.LONG,
+            SimpleType.LONG 
+        };
+
+        private final String query;
+        private int nrOfInvocations;
+        private long maxInvocationTime = Long.MIN_VALUE;
+        private long maxInvocationDate;
+        private long minInvocationTime = Long.MAX_VALUE;
+        private long minInvocationDate;
+        private long totalInvocationTime;
+        private long failures;
+        private int prepareCount;
+        private long prepareTime;
+        private volatile long lastInvocation = 0;
+        
+        public static String[] getFieldNames() {
+            return FIELD_NAMES;
+        }
+        
+        public static String[] getFieldDescriptions() {
+            return FIELD_DESCRIPTIONS;
+        }
+        
+        public static OpenType[] getFieldTypes() {
+            return FIELD_TYPES;
+        }
+        
+        @Override
+        public String toString() {
+            StringBuilder buf = new StringBuilder("QueryStats[query:");
+            buf.append(query);
+            buf.append(", nrOfInvocations:");
+            buf.append(nrOfInvocations);
+            buf.append(", maxInvocationTime:");
+            buf.append(maxInvocationTime);
+            buf.append(", maxInvocationDate:");
+            buf.append(new java.util.Date(maxInvocationDate).toGMTString());
+            buf.append(", minInvocationTime:");
+            buf.append(minInvocationTime);
+            buf.append(", minInvocationDate:");
+            buf.append(new java.util.Date(minInvocationDate).toGMTString());
+            buf.append(", totalInvocationTime:");
+            buf.append(totalInvocationTime);
+            buf.append(", averageInvocationTime:");
+            buf.append((float)totalInvocationTime / (float)nrOfInvocations);
+            buf.append(", failures:");
+            buf.append(failures);
+            buf.append(", prepareCount:");
+            buf.append(prepareCount);
+            buf.append(", prepareTime:");
+            buf.append(prepareTime);
+            buf.append("]");
+            return buf.toString();
+        }
+        
+        public CompositeDataSupport getCompositeData(final CompositeType type) throws OpenDataException{
+            Object[] values = new Object[] {
+                    query,
+                    Integer.valueOf(nrOfInvocations),
+                    Long.valueOf(maxInvocationTime),
+                    Long.valueOf(maxInvocationDate),
+                    Long.valueOf(minInvocationTime),
+                    Long.valueOf(minInvocationDate),
+                    Long.valueOf(totalInvocationTime),
+                    Long.valueOf(failures),
+                    Integer.valueOf(prepareCount),
+                    Long.valueOf(prepareTime),
+                    Long.valueOf(lastInvocation)
+            };
+            return new CompositeDataSupport(type,FIELD_NAMES,values);
+        }
+        
+        public QueryStats(String query) {
+            this.query = query;
+        }
+        
+        public void prepare(long invocationTime, long now) {
+            prepareCount++;
+            prepareTime+=invocationTime;
+            
+        }
+        
+        public void add(long invocationTime, long now) {
+            //not thread safe, but don't sacrifice performance for this kind of stuff
+            maxInvocationTime = Math.max(invocationTime, maxInvocationTime);
+            if (maxInvocationTime == invocationTime) {
+                maxInvocationDate = now;
+            }
+            minInvocationTime = Math.min(invocationTime, minInvocationTime);
+            if (minInvocationTime==invocationTime) {
+                minInvocationDate = now;
+            }
+            nrOfInvocations++;
+            totalInvocationTime+=invocationTime;
+            lastInvocation = now;
+        }
+        
+        public void failure(long invocationTime, long now) {
+            add(invocationTime,now);
+            failures++;
+            
+        }
+        
+        public String getQuery() {
+            return query;
+        }
+
+        public int getNrOfInvocations() {
+            return nrOfInvocations;
+        }
+
+        public long getMaxInvocationTime() {
+            return maxInvocationTime;
+        }
+
+        public long getMaxInvocationDate() {
+            return maxInvocationDate;
+        }
+
+        public long getMinInvocationTime() {
+            return minInvocationTime;
+        }
+
+        public long getMinInvocationDate() {
+            return minInvocationDate;
+        }
+
+        public long getTotalInvocationTime() {
+            return totalInvocationTime;
+        }
+
+        @Override
+        public int hashCode() {
+            return query.hashCode();
+        }
+        
+        @Override
+        public boolean equals(Object other) {
+            if (other instanceof QueryStats) {
+                QueryStats qs = (QueryStats)other;
+                return qs.query.equals(this.query);
+            } 
+            return false;
+        }
+        
+        public boolean isOlderThan(QueryStats other) {
+            return this.lastInvocation < other.lastInvocation;
+        }
+    }
+    
+    
+}
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmx.java
new file mode 100644 (file)
index 0000000..433519c
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * 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.pool.interceptor;
+
+import java.lang.management.ManagementFactory;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanException;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanRegistrationException;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.NotificationEmitter;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.RuntimeOperationsException;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.jdbc.pool.ConnectionPool;
+import org.apache.tomcat.jdbc.pool.PooledConnection;
+import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty;
+/**
+ * Publishes data to JMX and provides notifications 
+ * when failures happen.
+ * @author fhanik
+ *
+ */
+public class SlowQueryReportJmx extends SlowQueryReport implements NotificationEmitter, SlowQueryReportJmxMBean{
+    public static final String SLOW_QUERY_NOTIFICATION = "SLOW QUERY";
+    public static final String FAILED_QUERY_NOTIFICATION = "FAILED QUERY";
+
+    protected static CompositeType SLOW_QUERY_TYPE; 
+        
+    private static final Log log = LogFactory.getLog(SlowQueryReportJmx.class);
+    
+    
+    protected static ConcurrentHashMap<String,SlowQueryReportJmxMBean> mbeans = 
+        new ConcurrentHashMap<String,SlowQueryReportJmxMBean>(); 
+    
+    
+    //==============================JMX STUFF========================
+    protected volatile NotificationBroadcasterSupport notifier = new NotificationBroadcasterSupport();
+
+    public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws IllegalArgumentException {
+        notifier.addNotificationListener(listener, filter, handback);
+    }
+
+    
+    public MBeanNotificationInfo[] getNotificationInfo() {
+        return notifier.getNotificationInfo();
+    }
+
+    public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException {
+        notifier.removeNotificationListener(listener);
+        
+    }
+
+    public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException {
+        notifier.removeNotificationListener(listener, filter, handback);
+        
+    }
+
+
+    //==============================JMX STUFF========================    
+    
+    protected String poolName = null;
+    
+    protected static AtomicLong notifySequence = new AtomicLong(0);
+    
+    protected boolean notifyPool = true;
+    
+    protected ConnectionPool pool = null;
+    
+    protected static CompositeType getCompositeType() {
+        if (SLOW_QUERY_TYPE==null) {
+            try {
+                SLOW_QUERY_TYPE = new CompositeType(
+                        SlowQueryReportJmx.class.getName(),
+                        "Composite data type for query statistics",
+                        QueryStats.getFieldNames(),
+                        QueryStats.getFieldDescriptions(),
+                        QueryStats.getFieldTypes());
+            }catch (OpenDataException x) {
+                log.warn("Unable to initialize composite data type for JMX stats and notifications.",x);
+            }
+        }
+        return SLOW_QUERY_TYPE;
+    }
+    
+    @Override
+    public void reset(ConnectionPool parent, PooledConnection con) {
+        // TODO Auto-generated method stub
+        super.reset(parent, con);
+        if (parent!=null) {
+            poolName = parent.getName();
+            pool = parent;
+            registerJmx();
+        }
+    }
+
+
+    @Override
+    public void poolClosed(ConnectionPool pool) {
+        this.poolName = pool.getName();
+        deregisterJmx();
+        super.poolClosed(pool);
+    }
+
+    @Override
+    public void poolStarted(ConnectionPool pool) {
+        this.pool = pool;
+        super.poolStarted(pool);
+        this.poolName = pool.getName();
+    }
+
+    @Override
+    protected String reportFailedQuery(String query, Object[] args, String name, long start, Throwable t) {
+        query = super.reportFailedQuery(query, args, name, start, t);
+        notifyJmx(query,FAILED_QUERY_NOTIFICATION);
+        return query;
+    }
+
+    protected void notifyJmx(String query, String type) {
+        try {
+            long sequence = notifySequence.incrementAndGet();
+            
+            if (isNotifyPool()) {
+                if (this.pool!=null && this.pool.getJmxPool()!=null) {
+                    this.pool.getJmxPool().notify(type, query);
+                }
+            } else {
+                if (notifier!=null) {
+                    Notification notification = 
+                        new Notification(type, 
+                                         this, 
+                                         sequence, 
+                                         System.currentTimeMillis(),
+                                         query);
+                    
+                    notifier.sendNotification(notification);
+                }
+            }
+        } catch (RuntimeOperationsException e) {
+            if (log.isDebugEnabled()) {
+                log.debug("Unable to send failed query notification.",e);
+            }
+        }
+    }
+
+    @Override
+    protected String reportSlowQuery(String query, Object[] args, String name, long start, long delta) {
+        query = super.reportSlowQuery(query, args, name, start, delta);
+        notifyJmx(query,SLOW_QUERY_NOTIFICATION);
+        return query;
+    }
+
+    /**
+     * JMX operation - return the names of all the pools
+     * @return - all the names of pools that we have stored data for
+     */
+    public String[] getPoolNames() {
+        Set<String> keys = perPoolStats.keySet();
+        return keys.toArray(new String[0]);
+    }
+
+    /**
+     * JMX operation - return the name of the pool
+     * @return the name of the pool, unique within the JVM
+     */
+    public String getPoolName() {
+        return poolName;
+    }
+
+
+    public boolean isNotifyPool() {
+        return notifyPool;
+    }
+
+    public void setNotifyPool(boolean notifyPool) {
+        this.notifyPool = notifyPool;
+    }
+
+    /**
+     * JMX operation - remove all stats for this connection pool
+     */
+    public void resetStats() {
+        ConcurrentHashMap<String,QueryStats> queries = perPoolStats.get(poolName);
+        if (queries!=null) {
+            Iterator<String> it = queries.keySet().iterator();
+            while (it.hasNext()) it.remove();
+        }
+    }
+    
+    /**
+     * JMX operation - returns all the queries we have collected.
+     * @return - the slow query report as composite data.
+     */
+    public CompositeData[] getSlowQueriesCD() throws OpenDataException {
+        CompositeDataSupport[] result = null;
+        ConcurrentHashMap<String,QueryStats> queries = perPoolStats.get(poolName);
+        if (queries!=null) {
+            Set<Map.Entry<String,QueryStats>> stats = queries.entrySet();
+            if (stats!=null) {
+                result = new CompositeDataSupport[stats.size()];
+                Iterator<Map.Entry<String,QueryStats>> it = stats.iterator();
+                int pos = 0;
+                while (it.hasNext()) {
+                    Map.Entry<String,QueryStats> entry = it.next();
+                    QueryStats qs = entry.getValue();
+                    result[pos++] = qs.getCompositeData(getCompositeType());
+                }
+            }
+        }
+        return result;
+    }
+    
+    protected void deregisterJmx() {
+        try {
+            if (mbeans.remove(poolName)!=null) {
+                ObjectName oname = getObjectName(getClass(),poolName);
+                ManagementFactory.getPlatformMBeanServer().unregisterMBean(oname);
+            }
+        } catch (MBeanRegistrationException e) {
+            log.debug("Jmx deregistration failed.",e);
+        } catch (InstanceNotFoundException e) {
+            log.debug("Jmx deregistration failed.",e);
+        } catch (MalformedObjectNameException e) {
+            log.warn("Jmx deregistration failed.",e);
+        } catch (RuntimeOperationsException e) {
+            log.warn("Jmx deregistration failed.",e);
+        }
+        
+    }
+
+
+    public static ObjectName getObjectName(Class<?> clazz, String poolName) throws MalformedObjectNameException {
+        ObjectName oname = new ObjectName(ConnectionPool.POOL_JMX_TYPE_PREFIX+clazz.getName()+",name=" + poolName);
+        return oname;
+    }
+    
+    protected void registerJmx() {
+        try {
+            //only if we notify the pool itself
+            if (isNotifyPool()) {
+                
+            } else if (getCompositeType()!=null) {
+                ObjectName oname = getObjectName(getClass(),poolName);
+                if (mbeans.putIfAbsent(poolName, this)==null) {
+                    ManagementFactory.getPlatformMBeanServer().registerMBean(this, oname);
+                }
+            } else {
+                log.warn(SlowQueryReport.class.getName()+ "- No JMX support, composite type was not found.");
+            }
+        } catch (MalformedObjectNameException e) {
+            log.error("Jmx registration failed, no JMX data will be exposed for the query stats.",e);
+        } catch (RuntimeOperationsException e) {
+            log.error("Jmx registration failed, no JMX data will be exposed for the query stats.",e);
+        } catch (MBeanException e) {
+            log.error("Jmx registration failed, no JMX data will be exposed for the query stats.",e);
+        } catch (InstanceAlreadyExistsException e) {
+            log.error("Jmx registration failed, no JMX data will be exposed for the query stats.",e);
+        } catch (NotCompliantMBeanException e) {
+            log.error("Jmx registration failed, no JMX data will be exposed for the query stats.",e);
+        }
+    }
+    
+    @Override
+    public void setProperties(Map<String, InterceptorProperty> properties) {
+        super.setProperties(properties);
+        final String threshold = "notifyPool";
+        InterceptorProperty p1 = properties.get(threshold);
+        if (p1!=null) {
+            this.setNotifyPool(Boolean.parseBoolean(p1.getValue()));
+        }
+    }
+
+
+}
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmxMBean.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/SlowQueryReportJmxMBean.java
new file mode 100644 (file)
index 0000000..908eb1c
--- /dev/null
@@ -0,0 +1,23 @@
+/* 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.pool.interceptor;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.OpenDataException;
+
+public interface SlowQueryReportJmxMBean {
+    public CompositeData[] getSlowQueriesCD() throws OpenDataException;
+}
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementCache.java
new file mode 100644 (file)
index 0000000..533211c
--- /dev/null
@@ -0,0 +1,261 @@
+/* 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.pool.interceptor;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.sql.Statement;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.tomcat.jdbc.pool.ConnectionPool;
+import org.apache.tomcat.jdbc.pool.PooledConnection;
+import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty;
+
+public class StatementCache extends StatementDecoratorInterceptor {
+    protected static final String[] ALL_TYPES = new String[] {PREPARE_STATEMENT,PREPARE_CALL}; 
+    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 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;
+    }
+
+    @Override
+    public void setProperties(Map<String, InterceptorProperty> properties) {
+        super.setProperties(properties);
+        InterceptorProperty p = properties.get("prepared");
+        if (p!=null) cachePrepared = p.getValueAsBoolean(cachePrepared);
+        p = properties.get("callable");
+        if (p!=null) cacheCallable = p.getValueAsBoolean(cacheCallable);
+        p = properties.get("max");
+        if (p!=null) maxCacheSize = p.getValueAsInt(maxCacheSize);
+        if (cachePrepared && cacheCallable) {
+            this.types = ALL_TYPES;
+        } else if (cachePrepared) {
+            this.types = PREPARED_TYPE;
+        } else if (cacheCallable) {
+            this.types = CALLABLE_TYPE;
+        } else {
+            this.types = NO_TYPE;
+        }
+    
+    }
+    /*end properties for the statement cache*/
+    
+    /*begin the cache size*/
+    private static ConcurrentHashMap<ConnectionPool,AtomicInteger> cacheSizeMap = 
+        new ConcurrentHashMap<ConnectionPool,AtomicInteger>();
+    
+    private AtomicInteger cacheSize;
+
+    @Override
+    public void poolStarted(ConnectionPool pool) {
+        cacheSizeMap.putIfAbsent(pool, new AtomicInteger(0));
+        super.poolStarted(pool);
+    }
+    
+    @Override
+    public void poolClosed(ConnectionPool pool) {
+        cacheSizeMap.remove(pool);
+        super.poolClosed(pool);
+    }
+    /*end the cache size*/
+    
+    /*begin the actual statement cache*/
+    @Override
+    public void reset(ConnectionPool parent, PooledConnection con) {
+        super.reset(parent, con);
+        if (parent==null) {
+            cacheSize = null;
+            this.pcon = null;
+        } else {
+            cacheSize = cacheSizeMap.get(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);
+            }
+        }
+    }
+    
+    @Override
+    public void disconnected(ConnectionPool parent, PooledConnection con, boolean finalizing) {
+        ConcurrentHashMap<String,CachedStatement> statements = 
+            (ConcurrentHashMap<String,CachedStatement>)con.getAttributes().get(STATEMENT_CACHE_ATTR);
+        
+        if (statements!=null) {
+            for (Map.Entry<String, CachedStatement> p : statements.entrySet()) {
+                closeStatement(p.getValue());
+            }
+            statements.clear();
+        }
+        
+        super.disconnected(parent, con, finalizing);
+    }
+    
+    public void closeStatement(CachedStatement st) {
+        if (st==null) return;
+        st.forceClose();
+    }
+    
+    @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);
+        }
+    }
+
+    @Override
+    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+        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 CachedStatement isCached(String sql) {
+        ConcurrentHashMap<String,CachedStatement> cache = 
+            (ConcurrentHashMap<String,CachedStatement>)pcon.getAttributes().get(STATEMENT_CACHE_ATTR);
+        return cache.get(sql);
+    }
+    
+    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())) {
+            return false;
+        } else if (cacheSize.get()>=maxCacheSize) {
+            return false;
+        } else if (cacheSize.incrementAndGet()>maxCacheSize) {
+            cacheSize.decrementAndGet();
+            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 CachedStatement extends StatementDecoratorInterceptor.StatementProxy<Statement> {
+        boolean cached = false;
+        public CachedStatement(Statement parent, String sql) {
+            super(parent, sql);
+        }
+        
+        @Override
+        public void closeInvoked() {
+            //should we cache it
+            boolean shouldClose = true;
+            if (cacheSize.get() < maxCacheSize) {
+                //cache a proxy so that we don't reuse the facade
+                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.closeInvoked();
+            }
+           
+        }
+        
+        public void forceClose() {
+            removeStatement(this);
+            super.closeInvoked();
+        }
+        
+    }
+    
+}
+
+
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementDecoratorInterceptor.java
new file mode 100644 (file)
index 0000000..922205e
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * 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.pool.interceptor;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.jdbc.pool.interceptor.AbstractCreateStatementInterceptor;
+
+/**
+ * Implementation of <b>JdbcInterceptor</b> that proxies resultSets and statements.
+ * @author Guillermo Fernandes
+ */
+public class StatementDecoratorInterceptor extends AbstractCreateStatementInterceptor {
+
+    private static final Log logger = LogFactory.getLog(StatementDecoratorInterceptor.class);
+
+    private static final String[] EXECUTE_QUERY_TYPES = { "executeQuery" };
+
+    /**
+     * the constructors that are used to create statement proxies
+     */
+    protected static final Constructor<?>[] constructors = new Constructor[AbstractCreateStatementInterceptor.STATEMENT_TYPE_COUNT];
+
+    /**
+     * the constructor to create the resultSet proxies
+     */
+    protected static Constructor<?> resultSetConstructor = null;
+
+    @Override
+    public void closeInvoked() {
+        // nothing to do
+    }
+
+    /**
+     * Creates a constructor for a proxy class, if one doesn't already exist
+     * 
+     * @param idx
+     *            - the index of the constructor
+     * @param clazz
+     *            - the interface that the proxy will implement
+     * @return - returns a constructor used to create new instances
+     * @throws NoSuchMethodException
+     */
+    protected Constructor<?> getConstructor(int idx, Class<?> clazz) throws NoSuchMethodException {
+        if (constructors[idx] == null) {
+            Class<?> proxyClass = Proxy.getProxyClass(StatementDecoratorInterceptor.class.getClassLoader(),
+                    new Class[] { clazz });
+            constructors[idx] = proxyClass.getConstructor(new Class[] { InvocationHandler.class });
+        }
+        return constructors[idx];
+    }
+
+    protected Constructor<?> getResultSetConstructor() throws NoSuchMethodException {
+        if (resultSetConstructor == null) {
+            Class<?> proxyClass = Proxy.getProxyClass(StatementDecoratorInterceptor.class.getClassLoader(),
+                    new Class[] { ResultSet.class });
+            resultSetConstructor = proxyClass.getConstructor(new Class[] { InvocationHandler.class });
+        }
+        return resultSetConstructor;
+    }
+
+    /**
+     * Creates a statement interceptor to monitor query response times
+     */
+    @Override
+    public Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time) {
+        try {
+            String name = method.getName();
+            Constructor<?> constructor = null;
+            String sql = null;
+            if (compare(CREATE_STATEMENT, name)) {
+                // createStatement
+                constructor = getConstructor(CREATE_STATEMENT_IDX, Statement.class);
+            } else if (compare(PREPARE_STATEMENT, name)) {
+                // prepareStatement
+                constructor = getConstructor(PREPARE_STATEMENT_IDX, PreparedStatement.class);
+                sql = (String)args[0];
+            } else if (compare(PREPARE_CALL, name)) {
+                // prepareCall
+                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;
+            }
+            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);
+    }
+
+    protected boolean isExecuteQuery(Method method) {
+        return isExecuteQuery(method.getName());
+    }
+
+    /**
+     * Class to measure query execute time
+     * 
+     * @author fhanik
+     * 
+     */
+    protected class StatementProxy<T extends java.sql.Statement> implements InvocationHandler {
+        
+        protected boolean closed = false;
+        protected T delegate;
+        private Object actualProxy;
+        private Object connection;
+        private String sql;
+        private Constructor constructor;
+
+        public StatementProxy(T delegate, String sql) {
+            this.delegate = delegate;
+            this.sql = sql;
+        }
+        public T getDelegate() {
+            return this.delegate;
+        }
+        
+        public String getSql() {
+            return sql;
+        }
+
+        public void setConnection(Object proxy) {
+            this.connection = proxy;            
+        }
+        public Object getConnection() {
+            return this.connection;
+        }
+
+        public void setActualProxy(Object proxy){
+            this.actualProxy = proxy;
+        }
+        public Object getActualProxy() {
+            return this.actualProxy;
+        }
+        
+        
+        public Constructor getConstructor() {
+            return constructor;
+        }
+        public void setConstructor(Constructor constructor) {
+            this.constructor = constructor;
+        }
+        public void closeInvoked() {
+            if (getDelegate()!=null) {
+                try {
+                    getDelegate().close();
+                }catch (SQLException ignore) {
+                }
+            }
+            closed = true;
+            delegate = null;
+        }
+        
+        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+            if (compare(TOSTRING_VAL,method)) {
+                return toString();
+            }
+            // was close invoked?
+            boolean close = compare(CLOSE_VAL, method);
+            // allow close to be called multiple times
+            if (close && closed)
+                return null;
+            // are we calling isClosed?
+            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 (compare(GETCONNECTION_VAL,method)){
+                return connection;
+            }
+            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 {
+                // perform close cleanup
+                if (close) {
+                    closeInvoked();
+                } 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;
+                }
+            }
+            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 {
+
+        private Object st;
+        private Object delegate;
+
+        public ResultSetProxy(Object st, Object delegate) {
+            this.st = st;
+            this.delegate = delegate;
+        }
+
+        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+            if (method.getName().equals("getStatement")) {
+                return this.st;
+            } else {
+                return method.invoke(this.delegate, args);
+            }
+        }
+    }
+}
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementFinalizer.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/StatementFinalizer.java
new file mode 100644 (file)
index 0000000..f05efde
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * 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.pool.interceptor;
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Method;
+import java.sql.Statement;
+import java.util.ArrayList;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.jdbc.pool.ConnectionPool;
+import org.apache.tomcat.jdbc.pool.PooledConnection;
+/**
+ * Keeps track of statements associated with a connection and invokes close upon {@link java.sql.Connection#close()}
+ * Useful for applications that dont close the associated statements after being done with a connection.
+ * @author fhanik
+ *
+ */
+public class StatementFinalizer extends AbstractCreateStatementInterceptor {
+    private static final Log log = LogFactory.getLog(StatementFinalizer.class);
+    
+    protected ArrayList<WeakReference<Statement>> statements = new ArrayList<WeakReference<Statement>>();
+    
+    @Override
+    public Object createStatement(Object proxy, Method method, Object[] args, Object statement, long time) {
+        // TODO Auto-generated method stub
+        try {
+            if (statement instanceof Statement)
+                statements.add(new WeakReference<Statement>((Statement)statement));
+        }catch (ClassCastException x) {
+            //ignore this one
+        }
+        return statement;
+    }
+    
+    @Override
+    public void closeInvoked() {
+        while (statements.size()>0) {
+            WeakReference<Statement> ws = statements.remove(0);
+            Statement st = ws.get();
+            if (st!=null) {
+                try {
+                    st.close();
+                } catch (Exception ignore) {
+                    if (log.isDebugEnabled()) {
+                        log.debug("Unable to closed statement upon connection close.",ignore);
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public void reset(ConnectionPool parent, PooledConnection con) {
+        statements.clear();
+        super.reset(parent, con);
+    }
+    
+    
+}
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/mbeans-descriptors.xml b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/interceptor/mbeans-descriptors.xml
new file mode 100644 (file)
index 0000000..e312d05
--- /dev/null
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<!--
+ 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.
+-->
+<mbeans-descriptors>
+
+  <mbean description="Reports " domain="tomcat.jdbc" group="jdbc-pool" name="SlowQueryReportJmx" 
+         type="org.apache.tomcat.jdbc.pool.interceptor.SlowQueryReportJmx">
+
+    <attribute description="The name of the connection pool this Jmx bean is representing" name="poolName" type="java.lang.String" writeable="false"/>
+    <attribute description="List of all registered connections pools" name="poolNames" type="[java.lang.String;" writeable="false"/>
+    <attribute description="All the recorded query stats. " name="slowQueriesCD" type="[javax.management.openmbean.CompositeData;" writeable="false"/>
+    <operation description="Clears all the query stats" impact="ACTION" name="resetStats" returnType="void"/>
+
+    <notification description="Notification sent out by the slow query report when a query exceeds the threshhold" name="slow-query">
+      <notification-type>Slow query</notification-type>
+    </notification>
+    
+    <notification description="Notification sent out by the slow query report when a query fails execution" name="failed-query">
+      <notification-type>Failed query execution</notification-type>
+    </notification>
+  </mbean>
+</mbeans-descriptors>
\ No newline at end of file
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPool.java
new file mode 100644 (file)
index 0000000..657cf0e
--- /dev/null
@@ -0,0 +1,641 @@
+/* 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.pool.jmx;
+/**
+ * @author Filip Hanik
+ */
+import java.util.Properties;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.management.MBeanNotificationInfo;
+import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.NotificationListener;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.jdbc.pool.PoolConfiguration;
+import org.apache.tomcat.jdbc.pool.PoolUtilities;
+import org.apache.tomcat.jdbc.pool.Validator;
+import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorDefinition;
+
+public class ConnectionPool extends NotificationBroadcasterSupport implements ConnectionPoolMBean  {
+    /**
+     * logger
+     */
+    private static final Log log = LogFactory.getLog(ConnectionPool.class);
+
+    /**
+     * the connection pool
+     */
+    protected org.apache.tomcat.jdbc.pool.ConnectionPool pool = null;
+    /**
+     * sequence for JMX notifications
+     */
+    protected AtomicInteger sequence = new AtomicInteger(0);
+    
+    /**
+     * Listeners that are local and interested in our notifications, no need for JMX
+     */
+    protected ConcurrentLinkedQueue<NotificationListener> listeners = new ConcurrentLinkedQueue<NotificationListener>(); 
+
+    public ConnectionPool(org.apache.tomcat.jdbc.pool.ConnectionPool pool) {
+        super();
+        this.pool = pool;
+    }
+
+    public org.apache.tomcat.jdbc.pool.ConnectionPool getPool() {
+        return pool;
+    }
+    
+    public PoolConfiguration getPoolProperties() {
+        return pool.getPoolProperties();
+    }
+    
+    //=================================================================
+    //       NOTIFICATION INFO
+    //=================================================================
+    public static final String NOTIFY_INIT = "INIT FAILED";
+    public static final String NOTIFY_CONNECT = "CONNECTION FAILED";
+    public static final String NOTIFY_ABANDON = "CONNECTION ABANDONED";
+    public static final String SLOW_QUERY_NOTIFICATION = "SLOW QUERY";
+    public static final String FAILED_QUERY_NOTIFICATION = "FAILED QUERY";
+    public static final String SUSPECT_ABANDONED_NOTIFICATION = "SUSPECT CONNETION ABANDONED";
+
+    @Override
+    public MBeanNotificationInfo[] getNotificationInfo() { 
+        MBeanNotificationInfo[] pres = super.getNotificationInfo();
+        MBeanNotificationInfo[] loc = getDefaultNotificationInfo();
+        MBeanNotificationInfo[] aug = new MBeanNotificationInfo[pres.length + loc.length];
+        if (pres.length>0) System.arraycopy(pres, 0, aug, 0, pres.length);
+        if (loc.length >0) System.arraycopy(loc, 0, aug, pres.length, loc.length);    
+        return aug; 
+    } 
+    
+    public static MBeanNotificationInfo[] getDefaultNotificationInfo() {
+        String[] types = new String[] {NOTIFY_INIT, NOTIFY_CONNECT, NOTIFY_ABANDON, SLOW_QUERY_NOTIFICATION, FAILED_QUERY_NOTIFICATION, SUSPECT_ABANDONED_NOTIFICATION}; 
+        String name = Notification.class.getName(); 
+        String description = "A connection pool error condition was met."; 
+        MBeanNotificationInfo info = new MBeanNotificationInfo(types, name, description); 
+        return new MBeanNotificationInfo[] {info};
+    }
+    
+    /**
+     * Return true if the notification was sent successfully, false otherwise.
+     * @param type
+     * @param message
+     * @return true if the notification succeeded
+     */
+    public boolean notify(final String type, String message) {
+        try {
+            Notification n = new Notification(
+                    type,
+                    this,
+                    sequence.incrementAndGet(),
+                    System.currentTimeMillis(),
+                    "["+type+"] "+message);
+            sendNotification(n);
+            for (NotificationListener listener : listeners) {
+                listener.handleNotification(n,this);
+            }
+            return true;
+        }catch (Exception x) {
+            if (log.isDebugEnabled()) {
+                log.debug("Notify failed. Type="+type+"; Message="+message,x);
+            }
+            return false;
+        }
+        
+    }
+    
+    public void addListener(NotificationListener list) {
+        listeners.add(list);
+    }
+    
+    public boolean removeListener(NotificationListener list) {
+        return listeners.remove(list);
+    }
+    
+    //=================================================================
+    //       POOL STATS
+    //=================================================================
+
+    public int getSize() {
+        return pool.getSize();
+    }
+
+    public int getIdle() {
+        return pool.getIdle();
+    }
+
+    public int getActive() {
+        return pool.getActive();
+    }
+    
+    public int getNumIdle() {
+        return getIdle();
+    }
+    
+    public int getNumActive() {
+        return getActive();
+    }
+    
+    public int getWaitCount() {
+        return pool.getWaitCount();
+    }
+
+    //=================================================================
+    //       POOL OPERATIONS
+    //=================================================================
+    public void checkIdle() {
+        pool.checkIdle();
+    }
+
+    public void checkAbandoned() {
+        pool.checkAbandoned();
+    }
+
+    public void testIdle() {
+        pool.testAllIdle();
+    }
+    //=================================================================
+    //       POOL PROPERTIES
+    //=================================================================
+    //=========================================================
+    //  PROPERTIES / CONFIGURATION
+    //=========================================================    
+
+
+    public String getConnectionProperties() {
+        return getPoolProperties().getConnectionProperties();
+    }
+
+    public Properties getDbProperties() {
+        return PoolUtilities.cloneWithoutPassword(getPoolProperties().getDbProperties());
+    }
+
+    public String getDefaultCatalog() {
+        return getPoolProperties().getDefaultCatalog();
+    }
+
+    public int getDefaultTransactionIsolation() {
+        return getPoolProperties().getDefaultTransactionIsolation();
+    }
+
+    public String getDriverClassName() {
+        return getPoolProperties().getDriverClassName();
+    }
+
+
+    public int getInitialSize() {
+        return getPoolProperties().getInitialSize();
+    }
+
+    public String getInitSQL() {
+        return getPoolProperties().getInitSQL();
+    }
+
+    public String getJdbcInterceptors() {
+        return getPoolProperties().getJdbcInterceptors();
+    }
+
+    public int getMaxActive() {
+        return getPoolProperties().getMaxActive();
+    }
+
+    public int getMaxIdle() {
+        return getPoolProperties().getMaxIdle();
+    }
+
+    public int getMaxWait() {
+        return getPoolProperties().getMaxWait();
+    }
+
+    public int getMinEvictableIdleTimeMillis() {
+        return getPoolProperties().getMinEvictableIdleTimeMillis();
+    }
+
+    public int getMinIdle() {
+        return getPoolProperties().getMinIdle();
+    }
+    
+    public long getMaxAge() {
+        return getPoolProperties().getMaxAge();
+    }    
+
+    public String getName() {
+        return this.getPoolName();
+    }
+
+    public int getNumTestsPerEvictionRun() {
+        return getPoolProperties().getNumTestsPerEvictionRun();
+    }
+
+    /**
+     * @return DOES NOT RETURN THE PASSWORD, IT WOULD SHOW UP IN JMX
+     */
+    public String getPassword() {
+        return "Password not available as DataSource/JMX operation.";
+    }
+
+    public int getRemoveAbandonedTimeout() {
+        return getPoolProperties().getRemoveAbandonedTimeout();
+    }
+
+
+    public int getTimeBetweenEvictionRunsMillis() {
+        return getPoolProperties().getTimeBetweenEvictionRunsMillis();
+    }
+
+    public String getUrl() {
+        return getPoolProperties().getUrl();
+    }
+
+    public String getUsername() {
+        return getPoolProperties().getUsername();
+    }
+
+    public long getValidationInterval() {
+        return getPoolProperties().getValidationInterval();
+    }
+
+    public String getValidationQuery() {
+        return getPoolProperties().getValidationQuery();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    
+    public String getValidatorClassName() {
+        return getPoolProperties().getValidatorClassName();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    
+    public Validator getValidator() {
+        return getPoolProperties().getValidator();
+    }
+
+    public boolean isAccessToUnderlyingConnectionAllowed() {
+        return getPoolProperties().isAccessToUnderlyingConnectionAllowed();
+    }
+
+    public Boolean isDefaultAutoCommit() {
+        return getPoolProperties().isDefaultAutoCommit();
+    }
+
+    public Boolean isDefaultReadOnly() {
+        return getPoolProperties().isDefaultReadOnly();
+    }
+
+    public boolean isLogAbandoned() {
+        return getPoolProperties().isLogAbandoned();
+    }
+
+    public boolean isPoolSweeperEnabled() {
+        return getPoolProperties().isPoolSweeperEnabled();
+    }
+
+    public boolean isRemoveAbandoned() {
+        return getPoolProperties().isRemoveAbandoned();
+    }
+
+    public int getAbandonWhenPercentageFull() {
+        return getPoolProperties().getAbandonWhenPercentageFull();
+    }
+
+    public boolean isTestOnBorrow() {
+        return getPoolProperties().isTestOnBorrow();
+    }
+
+    public boolean isTestOnConnect() {
+        return getPoolProperties().isTestOnConnect();
+    }
+
+    public boolean isTestOnReturn() {
+        return getPoolProperties().isTestOnReturn();
+    }
+
+    public boolean isTestWhileIdle() {
+        return getPoolProperties().isTestWhileIdle();
+    }
+
+
+    public Boolean getDefaultAutoCommit() {
+        return getPoolProperties().getDefaultAutoCommit();
+    }
+
+    public Boolean getDefaultReadOnly() {
+        return getPoolProperties().getDefaultReadOnly();
+    }
+
+    public InterceptorDefinition[] getJdbcInterceptorsAsArray() {
+        return getPoolProperties().getJdbcInterceptorsAsArray();
+    }
+
+    public boolean getUseLock() {
+        return getPoolProperties().getUseLock();
+    }
+
+    public boolean isFairQueue() {
+        return getPoolProperties().isFairQueue();
+    }
+
+    public boolean isJmxEnabled() {
+        return getPoolProperties().isJmxEnabled();
+    }
+
+    public boolean isUseEquals() {
+        return getPoolProperties().isUseEquals();
+    }
+
+    public void setAbandonWhenPercentageFull(int percentage) {
+        getPoolProperties().setAbandonWhenPercentageFull(percentage);
+    }
+
+    public void setAccessToUnderlyingConnectionAllowed(boolean accessToUnderlyingConnectionAllowed) {
+        getPoolProperties().setAccessToUnderlyingConnectionAllowed(accessToUnderlyingConnectionAllowed);
+    }
+
+    public void setDbProperties(Properties dbProperties) {
+        getPoolProperties().setDbProperties(dbProperties);
+    }
+
+    public void setDefaultReadOnly(Boolean defaultReadOnly) {
+        getPoolProperties().setDefaultReadOnly(defaultReadOnly);
+    }
+
+    public void setMaxAge(long maxAge) {
+        getPoolProperties().setMaxAge(maxAge);
+    }
+
+    public void setName(String name) {
+        getPoolProperties().setName(name);
+    }
+
+    public String getPoolName() {
+        return getPoolProperties().getName();
+    }
+    
+
+    public void setConnectionProperties(String connectionProperties) {
+        getPoolProperties().setConnectionProperties(connectionProperties);
+        
+    }
+
+    public void setDefaultAutoCommit(Boolean defaultAutoCommit) {
+        getPoolProperties().setDefaultAutoCommit(defaultAutoCommit);
+    }
+
+    public void setDefaultCatalog(String defaultCatalog) {
+        getPoolProperties().setDefaultCatalog(defaultCatalog);
+    }
+
+    public void setDefaultTransactionIsolation(int defaultTransactionIsolation) {
+        getPoolProperties().setDefaultTransactionIsolation(defaultTransactionIsolation);
+    }
+
+    public void setDriverClassName(String driverClassName) {
+        getPoolProperties().setDriverClassName(driverClassName);
+    }
+    
+    
+    public void setFairQueue(boolean fairQueue) {
+        getPoolProperties().setFairQueue(fairQueue);
+    }
+
+    
+    public void setInitialSize(int initialSize) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    
+    public void setInitSQL(String initSQL) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    
+    public void setJdbcInterceptors(String jdbcInterceptors) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    
+    public void setJmxEnabled(boolean jmxEnabled) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    
+    public void setLogAbandoned(boolean logAbandoned) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    
+    public void setMaxActive(int maxActive) {
+        // TODO Auto-generated method stub
+        
+    }
+
+     
+    public void setMaxIdle(int maxIdle) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    
+    public void setMaxWait(int maxWait) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    
+    public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    
+    public void setMinIdle(int minIdle) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    
+    public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    
+    public void setPassword(String password) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    
+    public void setRemoveAbandoned(boolean removeAbandoned) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    
+    public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    
+    public void setTestOnBorrow(boolean testOnBorrow) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    
+    public void setTestOnConnect(boolean testOnConnect) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    
+    public void setTestOnReturn(boolean testOnReturn) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    
+    public void setTestWhileIdle(boolean testWhileIdle) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    
+    public void setTimeBetweenEvictionRunsMillis(int timeBetweenEvictionRunsMillis) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    
+    public void setUrl(String url) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    
+    public void setUseEquals(boolean useEquals) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    
+    public void setUseLock(boolean useLock) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    
+    public void setUsername(String username) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    
+    public void setValidationInterval(long validationInterval) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    
+    public void setValidationQuery(String validationQuery) {
+        // TODO Auto-generated method stub
+        
+    }
+    
+    /**
+     * {@inheritDoc}
+     */
+    
+    public void setValidatorClassName(String className) {
+        getPoolProperties().setValidatorClassName(className);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    
+    public int getSuspectTimeout() {
+        return getPoolProperties().getSuspectTimeout(); 
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    
+    public void setSuspectTimeout(int seconds) {
+        //no op
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    public void setDataSource(Object ds) {
+        getPoolProperties().setDataSource(ds);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    public Object getDataSource() {
+        return getPoolProperties().getDataSource();
+    }
+
+
+    /** 
+     * {@inheritDoc}
+     */
+    public void setDataSourceJNDI(String jndiDS) {
+        //noop
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    public String getDataSourceJNDI() {
+        return getPoolProperties().getDataSourceJNDI();
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public boolean isAlternateUsernameAllowed() {
+        return getPoolProperties().isAlternateUsernameAllowed();
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public void setAlternateUsernameAllowed(boolean alternateUsernameAllowed) {
+        //noop
+    }
+
+}
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPoolMBean.java b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/jmx/ConnectionPoolMBean.java
new file mode 100644 (file)
index 0000000..7632d37
--- /dev/null
@@ -0,0 +1,54 @@
+/* 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.pool.jmx;
+
+import org.apache.tomcat.jdbc.pool.PoolConfiguration;
+
+public interface ConnectionPoolMBean extends PoolConfiguration  {
+
+    //=================================================================
+    //       POOL STATS
+    //=================================================================
+
+    public int getSize();
+
+    public int getIdle();
+
+    public int getActive();
+    
+    public boolean isPoolSweeperEnabled();
+    
+    public int getNumIdle();
+    
+    public int getNumActive();
+    
+    public int getWaitCount();
+    
+    //=================================================================
+    //       POOL OPERATIONS
+    //=================================================================
+    public void checkIdle();
+
+    public void checkAbandoned();
+
+    public void testIdle();
+
+    //=================================================================
+    //       POOL NOTIFICATIONS
+    //=================================================================
+
+    
+}
diff --git a/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/mbeans-descriptors.xml b/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/mbeans-descriptors.xml
new file mode 100644 (file)
index 0000000..897782b
--- /dev/null
@@ -0,0 +1,241 @@
+<?xml version="1.0"?>
+<!--
+  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.
+-->
+<mbeans-descriptors>
+
+    <mbean        name="TomcatJDBCPool"
+           description="Provides per diagnostic metrics and notifications for JDBC operations"
+                domain="tomcat"
+                 group="jdbc"
+                  type="org.apache.tomcat.jdbc.pool.DataSource">
+
+    <attribute    name="className"
+           description="Fully qualified class name of the managed object"
+                  type="java.lang.String"
+             writeable="false"/>
+             
+    <attribute    name="size"
+           description="The number of established connections in the pool, idle and in use"
+                  type="java.lang.Integer"
+             writeable="false"/>
+
+    <attribute    name="idle"
+           description="The number of established connections in the pool that are idle"
+                  type="java.lang.Integer"
+             writeable="false"/>
+
+    <attribute    name="numIdle"
+           description="Same as the idle attribute"
+                  type="java.lang.Integer"
+             writeable="false"/>
+
+    <attribute    name="active"
+           description="The number of established connections in the pool that are in use"
+                  type="java.lang.Integer"
+             writeable="false"/>
+    
+    <attribute    name="numActive"
+           description="Same as the active attribute"
+                  type="java.lang.Integer"
+             writeable="false"/>
+
+    <attribute    name="poolSweeperEnabled"
+           description="Returns true if the pool has a background thread running"
+                  type="java.lang.Boolean"
+                    is="true"
+             writeable="false"/>
+
+    <attribute    name="url"
+           description="The JDBC url for this connection pool"
+                  type="java.lang.String"
+             writeable="false"/>
+
+    <attribute    name="driverClassName"
+           description="The JDBC driver class for this connection pool"
+                  type="java.lang.String"
+             writeable="false"/>
+
+    <attribute    name="defaultAutoCommit"
+           description="The JDBC auto commit setting for new connections"
+                  type="java.lang.Boolean"
+                    is="true"
+             writeable="false"/>
+
+    <attribute    name="defaultReadOnly"
+           description="The JDBC read only setting for new connections"
+                  type="java.lang.Boolean"
+                    is="true"
+             writeable="false"/>
+
+    <attribute    name="defaultTransactionIsolation"
+           description="The JDBC transaction isolation setting for new connections"
+                  type="java.lang.Integer"
+             writeable="false"/>
+
+    <attribute    name="connectionProperties"
+           description="The connection properties that will be set for new connections. Format of the string will be [propertyName=property;]*"
+                  type="java.lang.String"
+             writeable="false"/>
+
+    <attribute    name="defaultCatalog"
+           description="The JDBC transaction isolation setting for new connections"
+                  type="java.lang.String"
+             writeable="false"/>
+
+    <attribute    name="initialSize"
+           description="The number of connections opened at pool startup"
+                  type="java.lang.Integer"
+             writeable="false"/>
+
+    <attribute    name="maxActive"
+           description="The maximum number of open connections"
+                  type="java.lang.Integer"
+             writeable="false"/>
+
+    <attribute    name="maxIdle"
+           description="The max number of idle connections"
+                  type="java.lang.Integer"
+             writeable="false"/>
+    
+    <attribute    name="minIdle"
+           description="The minimum number of open connections"
+                  type="java.lang.Integer"
+             writeable="false"/>
+    
+    <attribute    name="maxWait"
+           description="The time to wait in milliseconds before a SQLException is thrown when a connection is requested"
+                  type="java.lang.Integer"
+             writeable="false"/>
+
+    <attribute    name="validationQuery"
+           description="The query to run during validation"
+                  type="java.lang.String"
+             writeable="false"/>
+
+    <attribute    name="testOnBorrow"
+           description="True if validation happens when a connection is requested"
+                  type="java.lang.Boolean"
+                    is="true"
+             writeable="false"/>
+
+    <attribute    name="testOnReturn"
+           description="True if validation happens when a connection is returned"
+                  type="java.lang.Boolean"
+                    is="true"
+             writeable="false"/>
+
+    <attribute    name="testWhileIdle"
+           description="True if validation happens when a connection is not in use (idle)"
+                  type="java.lang.Boolean"
+                    is="true"
+             writeable="false"/>
+
+    <attribute    name="timeBetweenEvictionRunsMillis"
+           description="Sleep time for background thread in between pool checks"
+                  type="java.lang.Integer"
+             writeable="false"/>
+
+    <attribute    name="numTestsPerEvictionRun"
+           description="Not in use"
+                  type="java.lang.Integer"
+             writeable="false"/>
+
+    <attribute    name="minEvictableIdleTimeMillis"
+           description="Minimum amount of time a connection stays idle before it is evicted"
+                  type="java.lang.Integer"
+             writeable="false"/>
+
+    <attribute    name="accessToUnderlyingConnectionAllowed"
+           description="Returns true if one can retrieve the actual JDBC connection"
+                  type="java.lang.Boolean"
+                    is="true"
+             writeable="false"/>
+
+    <attribute    name="removeAbandoned"
+           description="Returns true if connection in use can be timed out"
+                  type="java.lang.Boolean"
+                    is="true"
+             writeable="false"/>
+
+    <attribute    name="removeAbandonedTimeout"
+           description="Timeout in seconds for connections in use"
+                  type="java.lang.Integer"
+             writeable="false"/>
+
+    <attribute    name="logAbandoned"
+           description="If true, stack trace will be recorded and printed out for timed out connection"
+                  type="java.lang.Boolean"
+                    is="true"
+             writeable="false"/>
+
+    <attribute    name="loginTimeout"
+           description="Not in use"
+                  type="java.lang.Integer"
+             writeable="false"/>
+
+
+    <attribute    name="name"
+           description="The name of the connection pool, will be used in the ObjectName of the actual pool"
+                  type="java.lang.String"
+             writeable="false"/>
+    
+    <attribute    name="password"
+           description="For security purposes,this doesn't return anything"
+                  type="java.lang.String"
+             writeable="false"/>
+    
+    <attribute    name="username"
+           description="The username used to open connections"
+                  type="java.lang.String"
+             writeable="false"/>
+
+    <attribute    name="validationInterval"
+           description="If larger than zero than validation will only occur after the interval milliseconds has passed"
+                  type="java.lang.Long"
+             writeable="false"/>
+
+    <attribute    name="initSQL"
+           description="A SQL executed once per connection, when it is established"
+                  type="java.lang.String"
+             writeable="false"/>
+
+    <attribute    name="testOnConnect"
+           description="Validate connection after connection has been established"
+                  type="java.lang.Boolean"
+                    is="true"
+             writeable="false"/>
+
+    <attribute    name="jdbcInterceptors"
+           description="The interceptors configured for this pool"
+                  type="java.lang.String"
+             writeable="false"/>
+
+    <operation    name="checkIdle" 
+                  description="forces a check of idle connections" 
+                  impact="ACTION" 
+                  returnType="void" />
+                  
+    <operation    name="checkAbandoned" 
+                  description="forces a check of abandoned connections" 
+                  impact="ACTION" 
+                  returnType="void" />
+    
+    <operation    name="testIdle" 
+                  description="forces a validation of abandoned connections" 
+                  impact="ACTION" 
+                  returnType="void" />
+  </mbean>
+
+</mbeans-descriptors>
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestInterceptor.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/pool/interceptor/TestInterceptor.java
new file mode 100644 (file)
index 0000000..739347c
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ *  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.pool.interceptor;
+
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.tomcat.jdbc.pool.ConnectionPool;
+import org.apache.tomcat.jdbc.pool.JdbcInterceptor;
+import org.apache.tomcat.jdbc.pool.PooledConnection;
+import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty;
+
+public class TestInterceptor extends JdbcInterceptor {
+    public static boolean poolstarted = false;
+    public static boolean poolclosed = false;
+    public static AtomicInteger instancecount = new AtomicInteger(0);
+
+    @Override
+    public void poolClosed(ConnectionPool pool) {
+        // TODO Auto-generated method stub
+        super.poolClosed(pool);
+        poolclosed = true;
+    }
+
+    @Override
+    public void poolStarted(ConnectionPool pool) {
+        super.poolStarted(pool);
+        poolstarted = true;
+    }
+
+    @Override
+    public void reset(ConnectionPool parent, PooledConnection con) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    @Override
+    public void setProperties(Map<String, InterceptorProperty> properties) {
+        instancecount.incrementAndGet();
+        super.setProperties(properties);
+    }
+
+
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/AbandonPercentageTest.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/AbandonPercentageTest.java
new file mode 100644 (file)
index 0000000..a86e6e9
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ *  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 org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer;
+
+public class AbandonPercentageTest extends DefaultTestCase {
+
+    public AbandonPercentageTest(String name) {
+        super(name);
+    }
+    
+    public void testDefaultAbandon() throws Exception {
+        this.init();
+        this.datasource.setMaxActive(100);
+        this.datasource.setMaxIdle(100);
+        this.datasource.setInitialSize(0);
+        this.datasource.getPoolProperties().setAbandonWhenPercentageFull(0);
+        this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(100);
+        this.datasource.getPoolProperties().setRemoveAbandoned(true);
+        this.datasource.getPoolProperties().setRemoveAbandonedTimeout(1);
+        Connection con = datasource.getConnection();
+        assertEquals("Number of connections active/busy should be 1",1,datasource.getPool().getActive());
+        Thread.sleep(2000);
+        assertEquals("Number of connections active/busy should be 0",0,datasource.getPool().getActive());
+        con.close();
+    }
+    
+    public void testMaxedOutAbandon() throws Exception {
+        int size = 100;
+        this.init();
+        this.datasource.setMaxActive(size);
+        this.datasource.setMaxIdle(size);
+        this.datasource.setInitialSize(0);
+        this.datasource.getPoolProperties().setAbandonWhenPercentageFull(100);
+        this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(100);
+        this.datasource.getPoolProperties().setRemoveAbandoned(true);
+        this.datasource.getPoolProperties().setRemoveAbandonedTimeout(1);
+        Connection con = datasource.getConnection();
+        assertEquals("Number of connections active/busy should be 1",1,datasource.getPool().getActive());
+        Thread.sleep(2000);
+        assertEquals("Number of connections active/busy should be 1",1,datasource.getPool().getActive());
+        con.close();
+    }
+
+    public void testResetConnection() throws Exception {
+        int size = 1;
+        this.init();
+        this.datasource.setMaxActive(size);
+        this.datasource.setMaxIdle(size);
+        this.datasource.setInitialSize(0);
+        this.datasource.getPoolProperties().setAbandonWhenPercentageFull(100);
+        this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(100);
+        this.datasource.getPoolProperties().setRemoveAbandoned(true);
+        this.datasource.getPoolProperties().setRemoveAbandonedTimeout(1);
+        this.datasource.getPoolProperties().setJdbcInterceptors(ResetAbandonedTimer.class.getName());
+        Connection con = datasource.getConnection();
+        assertEquals("Number of connections active/busy should be 1",1,datasource.getPool().getActive());
+        for (int i=0; i<20; i++) {
+            Thread.sleep(200);
+            con.isClosed();
+        }
+        assertEquals("Number of connections active/busy should be 1",1,datasource.getPool().getActive());
+        con.close();
+    }
+
+    public void testHalfway() throws Exception {
+        int size = 100;
+        this.init();
+        this.datasource.setMaxActive(size);
+        this.datasource.setMaxIdle(size);
+        this.datasource.setInitialSize(0);
+        this.datasource.getPoolProperties().setAbandonWhenPercentageFull(50);
+        this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(500);
+        this.datasource.getPoolProperties().setRemoveAbandoned(true);
+        this.datasource.getPoolProperties().setRemoveAbandonedTimeout(1);
+        Connection[] con = new Connection[size];
+        con[0] = datasource.getConnection();
+        assertEquals("Number of connections active/busy should be 1",1,datasource.getPool().getActive());
+        for (int i=1; i<25; i++) {
+            con[i] = datasource.getConnection();
+        }
+        assertEquals("Number of connections active/busy should be 25",25,datasource.getPool().getActive());
+        Thread.sleep(2500);
+        assertEquals("Number of connections active/busy should be 25",25,datasource.getPool().getActive());
+        this.datasource.getPoolProperties().setRemoveAbandonedTimeout(100);
+        for (int i=25; i<con.length; i++) {
+            con[i] = datasource.getConnection();
+        }
+        int active = datasource.getPool().getActive();
+        System.out.println("Active:"+active);
+        assertEquals("Number of connections active/busy should be "+con.length,con.length,datasource.getPool().getActive());
+        this.datasource.getPoolProperties().setRemoveAbandonedTimeout(1);
+        Thread.sleep(2500);
+        this.assertTrue("Number of connections should be less than 50.", (datasource.getPool().getActive()<50));
+        this.datasource.getPoolProperties().setAbandonWhenPercentageFull(0);
+        Thread.sleep(2500);
+        assertEquals("Number of connections active/busy should be "+0,0,datasource.getPool().getActive());
+    }
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/AlternateUsernameTest.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/AlternateUsernameTest.java
new file mode 100644 (file)
index 0000000..0ea3e2a
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ *  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.SQLException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import javax.sql.PooledConnection;
+
+import org.apache.tomcat.jdbc.test.driver.Connection;
+import org.apache.tomcat.jdbc.test.driver.Driver;
+
+
+public class AlternateUsernameTest extends DefaultTestCase {
+
+    private static final int iterations = 500000; //(new Random(System.currentTimeMillis())).nextInt(1000000)+100000;
+    public AlternateUsernameTest(String name) {
+        super(name);
+    }
+    public void testUsernameCompare() throws Exception {
+        testUsername(true);
+    }
+    
+    private void testUsername(boolean allowUsernameChange) throws Exception {
+        long start = System.currentTimeMillis();
+        int withoutuser =10;
+        int withuser = withoutuser;
+        this.init();
+        this.datasource.setMaxActive(withuser+withoutuser);
+        this.datasource.setDriverClassName(Driver.class.getName());
+        this.datasource.setUrl("jdbc:tomcat:test");
+        this.datasource.setAlternateUsernameAllowed(allowUsernameChange);
+        this.datasource.getConnection().close();
+        
+        TestRunner[] runners = new TestRunner[withuser+withoutuser];
+        for (int i=0; i<withuser; i++) {
+            TestRunner with = new TestRunner("foo","bar",datasource.getPoolProperties().getUsername(),datasource.getPoolProperties().getPassword());
+            TestRunner without = new TestRunner(null,null,datasource.getPoolProperties().getUsername(),datasource.getPoolProperties().getPassword());
+            runners[i] = allowUsernameChange?with:without;
+            runners[i+withuser] = without;
+        }
+        ExecutorService svc = Executors.newFixedThreadPool(withuser+withoutuser);
+        List<Future<TestResult>> results =  svc.invokeAll(Arrays.asList(runners));
+        int failures = 0;
+        int total = 0;
+        for (int i=0; i<withuser; i++) {
+            failures += results.get(i).get().failures;
+            total+=results.get(i).get().iterations;
+            failures += results.get(i+withuser).get().failures;
+            total+=results.get(i+withuser).get().iterations;
+        }
+        long stop = System.currentTimeMillis();
+        assertEquals("Nr of failures was:"+failures,0, failures);
+        svc.shutdownNow();
+        this.datasource.close();
+        System.out.println("Nr of connect() calls:"+Driver.connectCount.get());
+        System.out.println("Nr of disconnect() calls:"+Driver.disconnectCount.get());
+        System.out.println("Nr of iterations:"+total+" over "+(stop-start)+ " ms.");
+
+    }
+    
+    public void testUsernameCompareAgain() throws Exception {
+        testUsernameCompare();
+    }
+    
+    public void testUsernameCompareNotAllowed() throws Exception {
+        testUsername(false);
+    }
+    
+    public static class TestResult {
+        public int iterations;
+        public int failures;
+        public String lastMessage;
+    }
+    
+    public class TestRunner implements Callable<TestResult> {
+        String username;
+        String password;
+        volatile boolean done = false;
+        TestResult result = null;
+        boolean useuser = true;
+        
+        public TestRunner(String user, String pass, String guser, String gpass) {
+            username = user==null?guser : user;
+            password = pass==null?gpass : pass;
+            useuser = user!=null;
+        }
+        
+        public TestResult call() {
+            TestResult test = new TestResult();
+            PooledConnection pcon = null;
+            for (int i=0; (!done) && (i<iterations); i++) {
+                test.iterations = i+1;
+                try {
+                    
+                    
+                    pcon = useuser ? (PooledConnection)AlternateUsernameTest.this.datasource.getConnection(username, password) :
+                                     (PooledConnection)AlternateUsernameTest.this.datasource.getConnection();
+                    
+                    Connection con = (Connection)pcon.getConnection();
+                    
+                    assertTrue("Username mismatch: Requested User:"+username+" Actual user:"+con.getUsername(), con.getUsername().equals(username));
+                    assertTrue("Password mismatch: Requested Password:"+password+" Actual password:"+con.getPassword(), con.getPassword().equals(password));
+                }catch (SQLException x) {
+                    test.failures++;
+                    test.lastMessage = x.getMessage();
+                    done = true;
+                    x.printStackTrace();
+                }catch (Exception x) {
+                    test.failures++;
+                    test.lastMessage = x.getMessage();
+                    x.printStackTrace();
+                } finally {
+                    if (pcon!=null) {
+                        try {pcon.close(); }catch (Exception ignore) {}
+                        pcon = null;
+                    }
+                }
+            }
+            done = true;
+            result = test;
+            return result;
+        }
+    }
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/Async0IdleTestBug50477.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/Async0IdleTestBug50477.java
new file mode 100644 (file)
index 0000000..cfc9210
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.tomcat.jdbc.pool.DataSourceProxy;
+
+/**
+ * @author Filip Hanik
+ * @version 1.0
+ */
+public class Async0IdleTestBug50477 extends DefaultTestCase {
+    public Async0IdleTestBug50477(String name) {
+        super(name);
+    }
+    
+    public void testAsync0Idle0Size() throws Exception {
+        System.out.println("[testPoolThreads20Connections10FairAsync] Starting fairness - Tomcat JDBC - Fair - Async");
+        init();
+        this.datasource.getPoolProperties().setMaxActive(10);
+        this.datasource.getPoolProperties().setFairQueue(true);
+        this.datasource.getPoolProperties().setInitialSize(0);
+        try {
+            Future<Connection> cf = ((DataSourceProxy)datasource).getConnectionAsync();
+            Connection con  = cf.get(5, TimeUnit.SECONDS);
+        }finally {
+            tearDown();
+        }
+    }
+}
+
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/BorrowWaitTest.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/BorrowWaitTest.java
new file mode 100644 (file)
index 0000000..1244140
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ *  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.SQLException;
+
+public class BorrowWaitTest extends DefaultTestCase {
+
+    public BorrowWaitTest(String name) {
+        super(name);
+    }
+    
+    public void testWaitTime() throws Exception {
+        int wait = 10000;
+        this.init();
+        this.datasource.setMaxActive(1);
+        this.datasource.setMaxWait(wait);
+        Connection con = datasource.getConnection();
+        try {
+            Connection con2 = datasource.getConnection();
+            assertFalse("This should not happen, connection should be unavailable.",true);
+            con2.close();
+        }catch (SQLException x) {
+            long delta = System.currentTimeMillis();
+            boolean inrange = Math.abs(wait-delta) < 1000;
+            assertTrue("Connection should have been acquired within +/- 1 second.",true);
+        }
+        con.close();
+    }
+    
+    public void testWaitTimeInfinite() throws Exception {
+        if(true){
+            System.err.println("testWaitTimeInfinite() test is disabled.");
+            return;//this would lock up the test suite
+        }
+        int wait = -1;
+        this.init();
+        this.datasource.setMaxActive(1);
+        this.datasource.setMaxWait(wait);
+        Connection con = datasource.getConnection();
+        long start = System.currentTimeMillis();
+        try {
+            Connection con2 = datasource.getConnection();
+            assertFalse("This should not happen, connection should be unavailable.",true);
+        }catch (SQLException x) {
+            long delta = System.currentTimeMillis();
+            boolean inrange = Math.abs(wait-delta) < 1000;
+            assertTrue("Connection should have been acquired within +/- 1 second.",true);
+        }
+        con.close();
+    }
+
+
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/Bug50571.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/Bug50571.java
new file mode 100644 (file)
index 0000000..8a5650c
--- /dev/null
@@ -0,0 +1,39 @@
+/*\r
+ * Licensed to the Apache Software Foundation (ASF) under one or more\r
+ * contributor license agreements.  See the NOTICE file distributed with\r
+ * this work for additional information regarding copyright ownership.\r
+ * The ASF licenses this file to You under the Apache License, Version 2.0\r
+ * (the "License"); you may not use this file except in compliance with\r
+ * the License.  You may obtain a copy of the License at\r
+ *\r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.apache.tomcat.jdbc.test;\r
+\r
+import org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;\r
+\r
+public class Bug50571 extends DefaultTestCase{\r
+    \r
+    public Bug50571(String name) {\r
+        super(name);\r
+    }\r
+    \r
+    @Override\r
+    public void setUp() throws Exception {\r
+        super.setUp();\r
+        this.datasource.setUrl("jdbc:h2:~/.h2/test;QUERY_TIMEOUT=0;DB_CLOSE_ON_EXIT=FALSE");\r
+        this.datasource.setJdbcInterceptors(ConnectionState.class.getName());\r
+        this.datasource.setDefaultTransactionIsolation(-55);\r
+        this.datasource.setInitialSize(1);\r
+    }\r
+    \r
+    public void testBug50571() throws Exception {\r
+        this.datasource.getConnection().close();\r
+    }\r
+}\r
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/Bug50805.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/Bug50805.java
new file mode 100644 (file)
index 0000000..80fc23e
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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.util.concurrent.Future;
+
+public class Bug50805 extends DefaultTestCase {
+    public Bug50805(String name) {
+        super(name);
+    }
+    
+    public void test50805() throws Exception {
+        init();
+        this.datasource.setInitialSize(0);
+        this.datasource.setMaxActive(10);
+        this.datasource.setMinIdle(1);
+        
+        assertEquals("Current size should be 0.", 0, this.datasource.getSize());
+        
+        this.datasource.getConnection().close();
+        
+        assertEquals("Current size should be 1.", 1, this.datasource.getSize());
+        assertEquals("Idle size should be 1.", 1, this.datasource.getIdle());
+        assertEquals("Busy size should be 0.", 0, this.datasource.getActive());
+        
+        Future<Connection> fc = this.datasource.getConnectionAsync();
+        
+        Connection con = fc.get();
+        
+        assertEquals("Current size should be 1.", 1, this.datasource.getSize());
+        assertEquals("Idle size should be 0.", 0, this.datasource.getIdle());
+        assertEquals("Busy size should be 1.", 1, this.datasource.getActive());
+        
+        con.close();
+        assertEquals("Current size should be 1.", 1, this.datasource.getSize());
+        assertEquals("Idle size should be 1.", 1, this.datasource.getIdle());
+        assertEquals("Busy size should be 0.", 0, this.datasource.getActive());
+    }
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/CheckOutThreadTest.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/CheckOutThreadTest.java
new file mode 100644 (file)
index 0000000..2c5fa5e
--- /dev/null
@@ -0,0 +1,426 @@
+/*
+ * 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.util.concurrent.CountDownLatch;
+import java.sql.Connection;
+import java.sql.Statement;
+import java.sql.ResultSet;
+
+import javax.sql.DataSource;
+
+
+/**
+ * @author Filip Hanik
+ * @version 1.0
+ */
+public class CheckOutThreadTest extends DefaultTestCase {
+    public CheckOutThreadTest(String name) {
+        super(name);
+    }
+
+    CountDownLatch latch = null;
+
+    public void testDBCPThreads10Connections10() throws Exception {
+        init();
+        this.datasource.getPoolProperties().setMaxActive(10);
+        this.threadcount = 10;
+        this.transferProperties();
+        this.tDatasource.getConnection().close();
+        latch = new CountDownLatch(threadcount);
+        long start = System.currentTimeMillis();
+        for (int i=0; i<threadcount; i++) {
+            TestThread t = new TestThread();
+            t.setName("tomcat-dbcp-"+i);
+            t.d = this.tDatasource;
+            t.start();
+        }
+        latch.await();
+        long delta = System.currentTimeMillis() - start;
+        System.out.println("[testDBCPThreads10Connections10]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
+        tearDown();
+    }
+
+    public void testPoolThreads10Connections10() throws Exception {
+        init();
+        this.datasource.getPoolProperties().setMaxActive(10);
+        this.datasource.getPoolProperties().setFairQueue(false);
+        this.threadcount = 10;
+        this.transferProperties();
+        this.datasource.getConnection().close();
+        latch = new CountDownLatch(threadcount);
+        long start = System.currentTimeMillis();
+        for (int i=0; i<threadcount; i++) {
+            TestThread t = new TestThread();
+            t.setName("tomcat-pool-"+i);
+            t.d = this.datasource;
+            t.start();
+        }
+        latch.await();
+        long delta = System.currentTimeMillis() - start;
+        System.out.println("[testPoolThreads10Connections10]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
+        tearDown();
+    }
+
+    public void testPoolThreads10Connections10Fair() throws Exception {
+        init();
+        this.datasource.getPoolProperties().setMaxActive(10);
+        this.datasource.getPoolProperties().setFairQueue(true);
+        this.threadcount = 10;
+        this.transferProperties();
+        this.datasource.getConnection().close();
+        latch = new CountDownLatch(threadcount);
+        long start = System.currentTimeMillis();
+        for (int i=0; i<threadcount; i++) {
+            TestThread t = new TestThread();
+            t.setName("tomcat-pool-"+i);
+            t.d = this.datasource;
+            t.start();
+        }
+        latch.await();
+        long delta = System.currentTimeMillis() - start;
+        System.out.println("[testPoolThreads10Connections10Fair]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
+        tearDown();
+    }
+
+//    public void testC3P0Threads10Connections10() throws Exception {
+//        init();
+//        this.datasource.getPoolProperties().setMaxActive(10);
+//        this.threadcount = 10;
+//        this.transferPropertiesToC3P0();
+//        this.c3p0Datasource.getConnection().close();
+//        latch = new CountDownLatch(threadcount);
+//        long start = System.currentTimeMillis();
+//        for (int i=0; i<threadcount; i++) {
+//            TestThread t = new TestThread();
+//            t.setName("tomcat-pool-"+i);
+//            t.d = this.c3p0Datasource;
+//            t.start();
+//        }
+//        latch.await();
+//        long delta = System.currentTimeMillis() - start;
+//        System.out.println("[testC3P0Threads10Connections10]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
+//        tearDown();
+//    }
+
+    public void testDBCPThreads20Connections10() throws Exception {
+        init();
+        this.datasource.getPoolProperties().setMaxActive(10);
+        this.threadcount = 20;
+        this.transferProperties();
+        this.tDatasource.getConnection().close();
+        latch = new CountDownLatch(threadcount);
+        long start = System.currentTimeMillis();
+        for (int i=0; i<threadcount; i++) {
+            TestThread t = new TestThread();
+            t.setName("tomcat-dbcp-"+i);
+            t.d = this.tDatasource;
+            t.start();
+        }
+        latch.await();
+        long delta = System.currentTimeMillis() - start;
+        System.out.println("[testDBCPThreads20Connections10]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
+        tearDown();
+    }
+
+    public void testPoolThreads20Connections10() throws Exception {
+        init();
+        this.datasource.getPoolProperties().setMaxActive(10);
+        this.datasource.getPoolProperties().setFairQueue(false);
+        this.threadcount = 20;
+        this.transferProperties();
+        this.datasource.getConnection().close();
+        latch = new CountDownLatch(threadcount);
+        long start = System.currentTimeMillis();
+        for (int i=0; i<threadcount; i++) {
+            TestThread t = new TestThread();
+            t.setName("tomcat-pool-"+i);
+            t.d = this.datasource;
+            t.start();
+        }
+        latch.await();
+        long delta = System.currentTimeMillis() - start;
+        System.out.println("[testPoolThreads20Connections10]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
+        tearDown();
+    }
+
+    public void testPoolThreads20Connections10Fair() throws Exception {
+        init();
+        this.datasource.getPoolProperties().setMaxActive(10);
+        this.datasource.getPoolProperties().setFairQueue(true);
+        this.threadcount = 20;
+        this.transferProperties();
+        this.datasource.getConnection().close();
+        latch = new CountDownLatch(threadcount);
+        long start = System.currentTimeMillis();
+        for (int i=0; i<threadcount; i++) {
+            TestThread t = new TestThread();
+            t.setName("tomcat-pool-"+i);
+            t.d = this.datasource;
+            t.start();
+        }
+        latch.await();
+        long delta = System.currentTimeMillis() - start;
+        System.out.println("[testPoolThreads20Connections10Fair]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
+        tearDown();
+    }
+
+//    public void testC3P0Threads20Connections10() throws Exception {
+//        init();
+//        this.datasource.getPoolProperties().setMaxActive(10);
+//        this.threadcount = 20;
+//        this.transferPropertiesToC3P0();
+//        this.c3p0Datasource.getConnection().close();
+//        latch = new CountDownLatch(threadcount);
+//        long start = System.currentTimeMillis();
+//        for (int i=0; i<threadcount; i++) {
+//            TestThread t = new TestThread();
+//            t.setName("tomcat-pool-"+i);
+//            t.d = this.c3p0Datasource;
+//            t.start();
+//        }
+//        latch.await();
+//        long delta = System.currentTimeMillis() - start;
+//        System.out.println("[testC3P0Threads20Connections10]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
+//        tearDown();
+//    }
+    
+    public void testDBCPThreads10Connections10Validate() throws Exception {
+        init();
+        this.datasource.getPoolProperties().setMaxActive(10);
+        this.datasource.getPoolProperties().setTestOnBorrow(true);
+        this.threadcount = 10;
+        this.transferProperties();
+        this.tDatasource.getConnection().close();
+        latch = new CountDownLatch(threadcount);
+        long start = System.currentTimeMillis();
+        for (int i=0; i<threadcount; i++) {
+            TestThread t = new TestThread();
+            t.setName("tomcat-dbcp-validate-"+i);
+            t.d = this.tDatasource;
+            t.start();
+        }
+        latch.await();
+        long delta = System.currentTimeMillis() - start;
+        System.out.println("[testDBCPThreads10Connections10Validate]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
+        tearDown();
+    }
+
+    public void testPoolThreads10Connections10Validate() throws Exception {
+        init();
+        this.datasource.getPoolProperties().setMaxActive(10);
+        this.datasource.getPoolProperties().setTestOnBorrow(true);
+        this.datasource.getPoolProperties().setFairQueue(false);
+        this.threadcount = 10;
+        this.transferProperties();
+        this.datasource.getConnection().close();
+        latch = new CountDownLatch(threadcount);
+        long start = System.currentTimeMillis();
+        for (int i=0; i<threadcount; i++) {
+            TestThread t = new TestThread();
+            t.setName("tomcat-pool-validate-"+i);
+            t.d = this.datasource;
+            t.start();
+        }
+        latch.await();
+        long delta = System.currentTimeMillis() - start;
+        System.out.println("[testPoolThreads10Connections10Validate]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
+        tearDown();
+    }
+    
+    public void testPoolThreads10Connections10ValidateFair() throws Exception {
+        init();
+        this.datasource.getPoolProperties().setMaxActive(10);
+        this.datasource.getPoolProperties().setTestOnBorrow(true);
+        this.datasource.getPoolProperties().setFairQueue(true);
+        this.threadcount = 10;
+        this.transferProperties();
+        this.datasource.getConnection().close();
+        latch = new CountDownLatch(threadcount);
+        long start = System.currentTimeMillis();
+        for (int i=0; i<threadcount; i++) {
+            TestThread t = new TestThread();
+            t.setName("tomcat-pool-validate-"+i);
+            t.d = this.datasource;
+            t.start();
+        }
+        latch.await();
+        long delta = System.currentTimeMillis() - start;
+        System.out.println("[testPoolThreads10Connections10ValidateFair]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
+        tearDown();
+    }
+
+//    public void testC3P0Threads10Connections10Validate() throws Exception {
+//        init();
+//        this.datasource.getPoolProperties().setMaxActive(10);
+//        this.datasource.getPoolProperties().setTestOnBorrow(true);
+//        this.threadcount = 10;
+//        this.transferPropertiesToC3P0();
+//        this.c3p0Datasource.getConnection().close();
+//        latch = new CountDownLatch(threadcount);
+//        long start = System.currentTimeMillis();
+//        for (int i=0; i<threadcount; i++) {
+//            TestThread t = new TestThread();
+//            t.setName("tomcat-pool-validate-"+i);
+//            t.d = this.c3p0Datasource;
+//            t.start();
+//        }
+//        latch.await();
+//        long delta = System.currentTimeMillis() - start;
+//        System.out.println("[testC3P0Threads10Connections10Validate]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
+//        tearDown();
+//    }
+
+    public void testDBCPThreads20Connections10Validate() throws Exception {
+        init();
+        this.datasource.getPoolProperties().setMaxActive(10);
+        this.datasource.getPoolProperties().setTestOnBorrow(true);
+        this.threadcount = 20;
+        this.transferProperties();
+        this.tDatasource.getConnection().close();
+        latch = new CountDownLatch(threadcount);
+        long start = System.currentTimeMillis();
+        for (int i=0; i<threadcount; i++) {
+            TestThread t = new TestThread();
+            t.setName("tomcat-dbcp-validate-"+i);
+            t.d = this.tDatasource;
+            t.start();
+        }
+        latch.await();
+        long delta = System.currentTimeMillis() - start;
+        System.out.println("[testDBCPThreads20Connections10Validate]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
+        tearDown();
+    }
+
+    public void testPoolThreads10Connections20Validate() throws Exception {
+        init();
+        this.datasource.getPoolProperties().setMaxActive(10);
+        this.datasource.getPoolProperties().setTestOnBorrow(true);
+        this.datasource.getPoolProperties().setFairQueue(false);
+        this.threadcount = 20;
+        this.transferProperties();
+        this.datasource.getConnection().close();
+        latch = new CountDownLatch(threadcount);
+        long start = System.currentTimeMillis();
+        for (int i=0; i<threadcount; i++) {
+            TestThread t = new TestThread();
+            t.setName("tomcat-pool-validate-"+i);
+            t.d = this.datasource;
+            t.start();
+        }
+        latch.await();
+        long delta = System.currentTimeMillis() - start;
+        System.out.println("[testPoolThreads20Connections10Validate]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
+        tearDown();
+    }
+    
+    public void testPoolThreads10Connections20ValidateFair() throws Exception {
+        init();
+        this.datasource.getPoolProperties().setMaxActive(10);
+        this.datasource.getPoolProperties().setTestOnBorrow(true);
+        this.datasource.getPoolProperties().setFairQueue(true);
+        this.threadcount = 20;
+        this.transferProperties();
+        this.datasource.getConnection().close();
+        latch = new CountDownLatch(threadcount);
+        long start = System.currentTimeMillis();
+        for (int i=0; i<threadcount; i++) {
+            TestThread t = new TestThread();
+            t.setName("tomcat-pool-validate-"+i);
+            t.d = this.datasource;
+            t.start();
+        }
+        latch.await();
+        long delta = System.currentTimeMillis() - start;
+        System.out.println("[testPoolThreads20Connections10ValidateFair]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
+        tearDown();
+    }
+    
+//    public void testC3P0Threads10Connections20Validate() throws Exception {
+//        init();
+//        this.datasource.getPoolProperties().setMaxActive(10);
+//        this.datasource.getPoolProperties().setTestOnBorrow(true);
+//        this.threadcount = 20;
+//        this.transferPropertiesToC3P0();
+//        this.c3p0Datasource.getConnection().close();
+//        latch = new CountDownLatch(threadcount);
+//        long start = System.currentTimeMillis();
+//        for (int i=0; i<threadcount; i++) {
+//            TestThread t = new TestThread();
+//            t.setName("tomcat-pool-validate-"+i);
+//            t.d = this.c3p0Datasource;
+//            t.start();
+//        }
+//        latch.await();
+//        long delta = System.currentTimeMillis() - start;
+//        System.out.println("[testC3P0Threads10Connections20Validate]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
+//        tearDown();
+//    }
+
+    public class TestThread extends Thread {
+        protected DataSource d;
+        protected String query = null;
+        @Override
+        public void run() {
+            long max = -1, totalmax=0, totalcmax=0, cmax = -1, nroffetch = 0, totalruntime = 0;
+            try {
+                for (int i = 0; i < CheckOutThreadTest.this.iterations; i++) {
+                    long start = System.nanoTime();
+                    Connection con = null;
+                    try {
+                        con = d.getConnection();
+                        long delta = System.nanoTime() - start;
+                        totalmax += delta;
+                        max = Math.max(delta, max);
+                        nroffetch++;
+                        if (query!=null) {
+                            Statement st = con.createStatement();
+                            ResultSet rs = st.executeQuery(query);
+                            while (rs.next()) {
+                            }
+                            rs.close();
+                            st.close();
+                        }
+                    } finally {
+                        long cstart = System.nanoTime();
+                        if (con!=null) try {con.close();}catch(Exception x) {x.printStackTrace();}
+                        long cdelta = System.nanoTime() - cstart;
+                        totalcmax += cdelta;
+                        cmax = Math.max(cdelta, cmax);
+                    }
+                    totalruntime+=(System.nanoTime()-start);
+                }
+
+            } catch (Exception x) {
+                x.printStackTrace();
+            } finally {
+                CheckOutThreadTest.this.latch.countDown();
+            }
+            if (System.getProperty("print-thread-stats")!=null) {
+                System.out.println("["+getName()+"] "+
+                    "\n\tMax time to retrieve connection:"+(max/1000f/1000f)+" ms."+
+                    "\n\tTotal time to retrieve connection:"+(totalmax/1000f/1000f)+" ms."+
+                    "\n\tAverage time to retrieve connection:"+(totalmax/1000f/1000f)/nroffetch+" ms."+
+                    "\n\tMax time to close connection:"+(cmax/1000f/1000f)+" ms."+
+                    "\n\tTotal time to close connection:"+(totalcmax/1000f/1000f)+" ms."+
+                    "\n\tAverage time to close connection:"+(totalcmax/1000f/1000f)/nroffetch+" ms."+
+                    "\n\tRun time:"+(totalruntime/1000f/1000f)+" ms."+
+                    "\n\tNr of fetch:"+nroffetch);
+            }
+        }
+    }
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/ConnectCountTest.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/ConnectCountTest.java
new file mode 100644 (file)
index 0000000..339e1aa
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * 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.util.concurrent.CountDownLatch;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.sql.Connection;
+import java.sql.Statement;
+import java.sql.ResultSet;
+
+import javax.sql.DataSource;
+
+import org.apache.tomcat.jdbc.pool.DataSourceProxy;
+import org.apache.tomcat.jdbc.test.driver.Driver;
+
+/**
+ * @author Filip Hanik
+ * @version 1.0
+ */
+public class ConnectCountTest extends DefaultTestCase {
+    public ConnectCountTest(String name) {
+        super(name);
+    }
+    
+    protected boolean run = true;
+    protected long sleep = Long.getLong("sleep", 10);
+    protected long complete = Long.getLong("complete",20000);
+    protected boolean printthread = Boolean.getBoolean("printthread");
+    CountDownLatch latch = null;
+
+
+    @Override
+    public org.apache.tomcat.jdbc.pool.DataSource createDefaultDataSource() {
+        // TODO Auto-generated method stub
+        org.apache.tomcat.jdbc.pool.DataSource ds = super.createDefaultDataSource();
+        ds.getPoolProperties().setDriverClassName(Driver.class.getName());
+        ds.getPoolProperties().setUrl(Driver.url);
+        ds.getPoolProperties().setInitialSize(0);
+        ds.getPoolProperties().setMaxIdle(10);
+        ds.getPoolProperties().setMinIdle(10);
+        ds.getPoolProperties().setMaxActive(10);
+        return ds;
+    }
+
+
+    @Override
+    protected void tearDown() throws Exception {
+        Driver.reset();
+        super.tearDown();
+    }
+
+
+    protected void printThreadResults(TestThread[] threads, String name, int active, int expected) {
+        long minfetch = Long.MAX_VALUE, maxfetch = Long.MIN_VALUE, totalfetch = 0;
+        long maxwait = 0, minwait = Long.MAX_VALUE, averagewait = 0, totalwait = 0;
+        float avgfetch = 0;
+        for (int i=0; i<threads.length; i++) {
+            TestThread t = threads[i];
+            totalfetch += t.nroffetch;
+            totalwait  += t.totalwait;
+            maxwait = Math.max(maxwait,t.maxwait);
+            minwait = Math.min(minwait, t.minwait);
+            minfetch = Math.min(minfetch, t.nroffetch);
+            maxfetch = Math.max(maxfetch, t.nroffetch);
+            if (ConnectCountTest.this.printthread)
+                System.out.println(t.getName()+" : Nr-of-fetch:"+t.nroffetch+ " Max fetch Time:"+(((float)t.maxwait)/1000000f)+"ms. :Max close time:"+(((float)t.cmax)/1000000f)+"ms.");
+        }
+        System.out.println("["+name+"] Max fetch:"+(maxfetch)+" Min fetch:"+(minfetch)+" Average fetch:"+
+                           (((float)totalfetch))/(float)threads.length);
+        System.out.println("["+name+"] Max wait:"+(((float)maxwait)/1000000f)+"ms. Min wait:"+(((float)minwait)/1000000f)+"ms. Average wait:"+(((((float)totalwait))/(float)totalfetch)/1000000f)+" ms.");
+        System.out.println("["+name+"] Max active:"+active+" Expected Active:"+expected);
+        
+        
+    }
+    
+    public void testDBCPThreads20Connections10() throws Exception {
+        System.out.println("[testDBCPThreads20Connections10] Starting fairness - DBCP");
+        this.threadcount = 20;
+        init();
+        this.transferProperties();
+        this.tDatasource.getConnection().close();
+        latch = new CountDownLatch(threadcount);
+        long start = System.currentTimeMillis();
+        TestThread[] threads = new TestThread[threadcount];
+        for (int i=0; i<threadcount; i++) {
+            threads[i] = new TestThread();
+            threads[i].setName("tomcat-dbcp-"+i);
+            threads[i].d = this.tDatasource;
+            
+        }
+        for (int i=0; i<threadcount; i++) {
+            threads[i].start();
+        }
+        if (!latch.await(complete+1000,TimeUnit.MILLISECONDS)) {
+            System.out.println("Latch timed out.");
+        }
+        this.run = false;
+        long delta = System.currentTimeMillis() - start;
+        printThreadResults(threads,"testDBCPThreads20Connections10",Driver.connectCount.get(),10);
+        tearDown();
+    }
+
+    public void testPoolThreads20Connections10() throws Exception {
+        System.out.println("[testPoolThreads20Connections10] Starting fairness - Tomcat JDBC - Non Fair");
+        init();
+        this.threadcount = 20;
+        this.transferProperties();
+        this.datasource.getConnection().close();
+        latch = new CountDownLatch(threadcount);
+        long start = System.currentTimeMillis();
+        TestThread[] threads = new TestThread[threadcount];
+        for (int i=0; i<threadcount; i++) {
+            threads[i] = new TestThread();
+            threads[i].setName("tomcat-pool-"+i);
+            threads[i].d = this.datasource;
+            
+        }
+        for (int i=0; i<threadcount; i++) {
+            threads[i].start();
+        }
+        if (!latch.await(complete+1000,TimeUnit.MILLISECONDS)) {
+            System.out.println("Latch timed out.");
+        }
+        this.run = false;
+        long delta = System.currentTimeMillis() - start;
+        printThreadResults(threads,"testPoolThreads20Connections10",Driver.connectCount.get(),10);
+        tearDown();
+
+    }
+
+    public void testPoolThreads20Connections10Fair() throws Exception {
+        System.out.println("[testPoolThreads20Connections10Fair] Starting fairness - Tomcat JDBC - Fair");
+        init();
+        this.threadcount = 20;
+        this.datasource.getPoolProperties().setFairQueue(true);
+        this.transferProperties();
+        this.datasource.getConnection().close();
+        latch = new CountDownLatch(threadcount);
+        long start = System.currentTimeMillis();
+        TestThread[] threads = new TestThread[threadcount];
+        for (int i=0; i<threadcount; i++) {
+            threads[i] = new TestThread();
+            threads[i].setName("tomcat-pool-"+i);
+            threads[i].d = this.datasource;
+            
+        }
+        for (int i=0; i<threadcount; i++) {
+            threads[i].start();
+        }
+        if (!latch.await(complete+1000,TimeUnit.MILLISECONDS)) {
+            System.out.println("Latch timed out.");
+        }
+        this.run = false;
+        long delta = System.currentTimeMillis() - start;
+        printThreadResults(threads,"testPoolThreads20Connections10Fair",Driver.connectCount.get(),10);
+        tearDown();
+    }
+    public void testPoolThreads20Connections10FairAsync() throws Exception {
+        System.out.println("[testPoolThreads20Connections10FairAsync] Starting fairness - Tomcat JDBC - Fair - Async");
+        init();
+        this.threadcount = 20;
+        this.datasource.getPoolProperties().setFairQueue(true);
+        this.datasource.getPoolProperties().setInitialSize(this.datasource.getPoolProperties().getMaxActive());
+        this.transferProperties();
+        this.datasource.getConnection().close();
+        latch = new CountDownLatch(threadcount);
+        long start = System.currentTimeMillis();
+        TestThread[] threads = new TestThread[threadcount];
+        for (int i=0; i<threadcount; i++) {
+            threads[i] = new TestThread();
+            threads[i].setName("tomcat-pool-"+i);
+            threads[i].async = true;
+            threads[i].d = this.datasource;
+            
+        }
+        for (int i=0; i<threadcount; i++) {
+            threads[i].start();
+        }
+        if (!latch.await(complete+1000,TimeUnit.MILLISECONDS)) {
+            System.out.println("Latch timed out.");
+        }
+        this.run = false;
+        long delta = System.currentTimeMillis() - start;
+        printThreadResults(threads,"testPoolThreads20Connections10FairAsync",Driver.connectCount.get(),10);
+        tearDown();
+    }
+    
+//    public void testC3P0Threads20Connections10() throws Exception {
+//        System.out.println("[testC3P0Threads20Connections10] Starting fairness - C3P0");
+//        init();
+//        this.threadcount = 20;
+//        this.transferPropertiesToC3P0();
+//        this.datasource.getConnection().close();
+//        latch = new CountDownLatch(threadcount);
+//        long start = System.currentTimeMillis();
+//        TestThread[] threads = new TestThread[threadcount];
+//        for (int i=0; i<threadcount; i++) {
+//            threads[i] = new TestThread();
+//            threads[i].setName("tomcat-pool-"+i);
+//            threads[i].d = this.c3p0Datasource;
+//            
+//        }
+//        for (int i=0; i<threadcount; i++) {
+//            threads[i].start();
+//        }
+//        if (!latch.await(complete+1000,TimeUnit.MILLISECONDS)) {
+//            System.out.println("Latch timed out.");
+//        }
+//        this.run = false;
+//        long delta = System.currentTimeMillis() - start;
+//        printThreadResults(threads,"testC3P0Threads20Connections10",Driver.connectCount.get(),10);
+//        tearDown();
+//
+//    }
+
+    
+    public class TestThread extends Thread {
+        protected DataSource d;
+        protected String query = null;
+        protected long sleep = 10;
+        protected boolean async = false;
+        long minwait = Long.MAX_VALUE, maxwait = -1, totalwait=0, totalcmax=0, cmax = -1, nroffetch = 0, totalruntime = 0;
+        @Override
+        public void run() {
+            try {
+                long now = System.currentTimeMillis();
+                while (ConnectCountTest.this.run) {
+                    if ((System.currentTimeMillis()-now)>=ConnectCountTest.this.complete) break;
+                    long start = System.nanoTime();
+                    Connection con = null;
+                    try {
+                        if (async) {
+                            Future<Connection> cf = ((DataSourceProxy)d).getConnectionAsync();
+                            con  = cf.get();
+                        } else {
+                            con = d.getConnection();
+                        }
+                        long delta = System.nanoTime() - start;
+                        totalwait += delta;
+                        maxwait = Math.max(delta, maxwait);
+                        minwait = Math.min(delta, minwait);
+                        nroffetch++;
+                        if (query!=null) {
+                            Statement st = con.createStatement();
+                            ResultSet rs = st.executeQuery(query);
+                            while (rs.next()) {
+                            }
+                            rs.close();
+                            st.close();
+                        }
+                        try { 
+                            if (ConnectCountTest.this.sleep>0) sleep(ConnectCountTest.this.sleep); 
+                        } catch (InterruptedException x) {
+                            interrupted();
+                        }
+                    } finally {
+                        long cstart = System.nanoTime();
+                        if (con!=null) try {con.close();}catch(Exception x) {x.printStackTrace();}
+                        long cdelta = System.nanoTime() - cstart;
+                        totalcmax += cdelta;
+                        cmax = Math.max(cdelta, cmax);
+                    }
+                    totalruntime+=(System.nanoTime()-start);
+                }
+
+            } catch (Exception x) {
+                x.printStackTrace();
+            } finally {
+                ConnectCountTest.this.latch.countDown();
+            }
+            if (System.getProperty("print-thread-stats")!=null) {
+                System.out.println("["+getName()+"] "+
+                    "\n\tMax time to retrieve connection:"+(((float)maxwait)/1000f/1000f)+" ms."+
+                    "\n\tTotal time to retrieve connection:"+(((float)totalwait)/1000f/1000f)+" ms."+
+                    "\n\tAverage time to retrieve connection:"+(((float)totalwait)/1000f/1000f)/(float)nroffetch+" ms."+
+                    "\n\tMax time to close connection:"+(((float)cmax)/1000f/1000f)+" ms."+
+                    "\n\tTotal time to close connection:"+(((float)totalcmax)/1000f/1000f)+" ms."+
+                    "\n\tAverage time to close connection:"+(((float)totalcmax)/1000f/1000f)/(float)nroffetch+" ms."+
+                    "\n\tRun time:"+(((float)totalruntime)/1000f/1000f)+" ms."+
+                    "\n\tNr of fetch:"+nroffetch);
+            }
+        }
+    }
+}
+
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/CreateTestTable.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/CreateTestTable.java
new file mode 100644 (file)
index 0000000..825cb00
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ *  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 java.sql.Statement;
+import java.util.Random;
+import java.sql.ResultSet;
+
+import org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer;
+
+public class CreateTestTable extends DefaultTestCase {
+    
+    public static volatile boolean recreate = Boolean.getBoolean("recreate");
+    
+    public CreateTestTable(String name) {
+        super(name);
+    }
+
+    public void testCreateTestTable() throws Exception {
+        this.init();
+        Connection con = datasource.getConnection();
+        Statement st = con.createStatement();
+        try {
+            st.execute("create table test(id int not null, val1 varchar(255), val2 varchar(255), val3 varchar(255), val4 varchar(255))");
+        }catch (Exception ignore) {}
+        st.close();
+        con.close();
+    }
+    
+    public int testCheckData() throws Exception {
+        int count = 0;
+        String check = "select count (*) from test";
+        this.init();
+        Connection con = datasource.getConnection();
+        Statement st = con.createStatement();
+        try {
+            ResultSet rs = st.executeQuery(check);
+            
+            if (rs.next())
+                count = rs.getInt(1);
+            rs.close();
+            st.close();
+            System.out.println("Count:"+count);
+        }catch (Exception ignore) {}
+        con.close();
+        return count;
+    }
+    
+    public void testPopulateData() throws Exception {
+        int count = 100000;
+        int actual = testCheckData();
+        if (actual>=count) {
+            System.out.println("Test tables has "+actual+" rows of data. No need to populate.");
+            return;
+        }
+        
+        datasource.setJdbcInterceptors(ResetAbandonedTimer.class.getName());
+        String insert = "insert into test values (?,?,?,?,?)";
+        this.init();
+        this.datasource.setRemoveAbandoned(false);
+        Connection con = datasource.getConnection();
+        
+        boolean commit = con.getAutoCommit();
+        con.setAutoCommit(false);
+        if (recreate) {
+            Statement st = con.createStatement();
+            try {
+                st.execute("drop table test");
+            }catch (Exception ignore) {}
+            st.execute("create table test(id int not null, val1 varchar(255), val2 varchar(255), val3 varchar(255), val4 varchar(255))");
+            st.close();
+        }
+        
+        
+        PreparedStatement ps = con.prepareStatement(insert);
+        ps.setQueryTimeout(0);
+        for (int i=actual; i<count; i++) {
+            ps.setInt(1,i);
+            String s = getRandom();
+            ps.setString(2, s);
+            ps.setString(3, s);
+            ps.setString(4, s);
+            ps.setString(5, s);
+            ps.addBatch();
+            ps.clearParameters();
+            if ((i+1) % 1000 == 0) {
+                System.out.print(".");
+            }
+            if ((i+1) % 10000 == 0) {
+                System.out.print("\n"+(i+1));
+                ps.executeBatch();
+                ps.close();
+                con.commit();
+                ps = con.prepareStatement(insert);
+                ps.setQueryTimeout(0);
+            }
+
+        }
+        ps.close();
+        con.setAutoCommit(commit);
+        con.close();
+    }
+    
+    public static Random random = new Random(System.currentTimeMillis());
+    public static String getRandom() {
+        StringBuilder s = new StringBuilder(256);
+        for (int i=0;i<254; i++) {
+            int b = Math.abs(random.nextInt() % 29);
+            char c = (char)(b+65);
+            s.append(c);
+        }
+        return s.toString();
+    }
+    
+    public static void main(String[] args) throws Exception {
+        recreate = true;
+        CreateTestTable test = new CreateTestTable("CreateTestTable");
+        test.testPopulateData();
+    }
+
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/DefaultProperties.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/DefaultProperties.java
new file mode 100644 (file)
index 0000000..235b555
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 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.util.Properties;
+
+import org.apache.tomcat.jdbc.pool.DataSourceFactory;
+import org.apache.tomcat.jdbc.pool.PoolProperties;
+
+/**
+ * @author Filip Hanik
+ * @version 1.0
+ */
+public class DefaultProperties extends PoolProperties {
+    public DefaultProperties() {
+        dbProperties = new Properties();
+        
+        //mysql
+        //url = System.getProperty("url","jdbc:mysql://localhost:3306/mysql?autoReconnect=true"); 
+        //driverClassName = System.getProperty("driverClassName","com.mysql.jdbc.Driver");
+        
+        //derby
+        //url = System.getProperty("url","jdbc:derby:derbyDB;create=true");
+        //driverClassName = System.getProperty("driverClassName","org.apache.derby.jdbc.EmbeddedDriver");
+        
+        url = System.getProperty("url","jdbc:h2:~/.h2/test;QUERY_TIMEOUT=0;DB_CLOSE_ON_EXIT=FALSE");
+        driverClassName = System.getProperty("driverClassName","org.h2.Driver");
+        System.setProperty("h2.serverCachedObjects", "10000");
+        
+        password = System.getProperty("password","password");
+        username = System.getProperty("username","root");
+        
+        validationQuery = System.getProperty("validationQuery","SELECT 1");
+        defaultAutoCommit = true;
+        defaultReadOnly = false;
+        defaultTransactionIsolation = DataSourceFactory.UNKNOWN_TRANSACTIONISOLATION;
+        connectionProperties = null;
+        defaultCatalog = null;
+        initialSize = 10;
+        maxActive = 100;
+        maxIdle = initialSize;
+        minIdle = initialSize;
+        maxWait = 10000;
+        
+        testOnBorrow = true;
+        testOnReturn = false;
+        testWhileIdle = true;
+        timeBetweenEvictionRunsMillis = 5000;
+        numTestsPerEvictionRun = 0;
+        minEvictableIdleTimeMillis = 1000;
+        removeAbandoned = true;
+        removeAbandonedTimeout = 5000;
+        logAbandoned = true;
+        validationInterval = 0; //always validate
+        initSQL = null;
+        testOnConnect = false;;
+        dbProperties.setProperty("user",username);
+        dbProperties.setProperty("password",password);
+    }
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/DefaultTestCase.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/DefaultTestCase.java
new file mode 100644 (file)
index 0000000..401c380
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * 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.lang.reflect.Method;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+
+import org.apache.tomcat.dbcp.dbcp.BasicDataSource;
+import org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory;
+import org.apache.tomcat.jdbc.pool.PoolConfiguration;
+import org.apache.tomcat.jdbc.pool.PoolProperties;
+
+//import com.mchange.v2.c3p0.ComboPooledDataSource;
+//import com.mchange.v2.log.MLevel;
+//import com.mchange.v2.log.MLog;
+
+/**
+ * @author Filip Hanik
+ * @version 1.0
+ */
+public class DefaultTestCase extends TestCase {
+    protected org.apache.tomcat.jdbc.pool.DataSource datasource;
+    protected BasicDataSource tDatasource;
+//    protected ComboPooledDataSource c3p0Datasource;
+    protected int threadcount = 10;
+    protected int iterations = 100000;
+    public DefaultTestCase(String name) {
+        super(name);
+    }
+    
+    @Override
+    public void setUp() throws Exception {
+        init();
+    }
+
+    public org.apache.tomcat.jdbc.pool.DataSource createDefaultDataSource() {
+        org.apache.tomcat.jdbc.pool.DataSource datasource = null;
+        PoolConfiguration p = new DefaultProperties();
+        p.setFairQueue(false);
+        p.setJmxEnabled(false);
+        p.setTestWhileIdle(false);
+        p.setTestOnBorrow(false);
+        p.setTestOnReturn(false);
+        p.setValidationInterval(30000);
+        p.setTimeBetweenEvictionRunsMillis(30000);
+        p.setMaxActive(threadcount);
+        p.setInitialSize(threadcount);
+        p.setMaxWait(10000);
+        p.setRemoveAbandonedTimeout(10);
+        p.setMinEvictableIdleTimeMillis(10000);
+        p.setMinIdle(threadcount);
+        p.setLogAbandoned(false);
+        p.setRemoveAbandoned(false);
+        datasource = new org.apache.tomcat.jdbc.pool.DataSource();
+        datasource.setPoolProperties(p);
+        return datasource;
+    }
+    
+    protected void init() throws Exception {
+        this.datasource = createDefaultDataSource();
+    }
+
+    protected void transferProperties() {
+        try {
+            Properties p = new Properties();
+            for (int i=0; i< ALL_PROPERTIES.length; i++) {
+                String name = "get" + Character.toUpperCase(ALL_PROPERTIES[i].charAt(0)) + ALL_PROPERTIES[i].substring(1);
+                String bname = "is" + name.substring(3);
+                Method get = null;
+                try {
+                    get = PoolProperties.class.getMethod(name, new Class[0]);
+                }catch (NoSuchMethodException x) {
+                    try {
+                    get = PoolProperties.class.getMethod(bname, new Class[0]);
+                    }catch (NoSuchMethodException x2) {
+                        System.err.println(x2.getMessage());
+                    }
+                }
+                   if (get!=null) {
+                       Object value = get.invoke(datasource.getPoolProperties(), new Object[0]);
+                       if (value!=null) {
+                           p.setProperty(ALL_PROPERTIES[i], value.toString());
+                       }
+                }
+            }
+            tDatasource = (BasicDataSource) BasicDataSourceFactory.createDataSource(p);
+        }catch (Exception x) {
+            x.printStackTrace();
+        }
+    }
+    
+    protected void transferPropertiesToC3P0() throws Exception {
+//        System.setProperty("com.mchange.v2.log.FallbackMLog.DEFAULT_CUTOFF_LEVEL", "WARNING");
+//        MLog.getLogger().setLevel(MLevel.WARNING);
+//        MLog.getLogger("com").setLevel(MLevel.WARNING);
+//        //http://www.mchange.com/projects/c3p0/index.html#automaticTestTable
+//        ComboPooledDataSource c3p0 = new ComboPooledDataSource();  
+//        c3p0.setAcquireIncrement(1);
+//        c3p0.setAcquireRetryAttempts(2);
+//        c3p0.setAcquireRetryDelay(datasource.getPoolProperties().getMaxWait());
+//        c3p0.setCheckoutTimeout(datasource.getPoolProperties().getMaxWait());
+//        c3p0.setDebugUnreturnedConnectionStackTraces(datasource.getPoolProperties().isLogAbandoned());
+//        c3p0.setIdleConnectionTestPeriod(datasource.getPoolProperties().getTimeBetweenEvictionRunsMillis()/1000);
+//        c3p0.setInitialPoolSize(datasource.getPoolProperties().getInitialSize());
+//        c3p0.setMaxIdleTime(datasource.getPoolProperties().getMinEvictableIdleTimeMillis()/1000);
+//        c3p0.setMaxIdleTimeExcessConnections(datasource.getPoolProperties().getMaxIdle());
+//        c3p0.setMaxPoolSize(datasource.getPoolProperties().getMaxActive());
+//        c3p0.setMinPoolSize(datasource.getPoolProperties().getMinIdle());
+//        c3p0.setPassword(datasource.getPoolProperties().getPassword());
+//        c3p0.setPreferredTestQuery(datasource.getPoolProperties().getValidationQuery());
+//        c3p0.setTestConnectionOnCheckin(datasource.getPoolProperties().isTestOnReturn());
+//        c3p0.setTestConnectionOnCheckout(datasource.getPoolProperties().isTestOnBorrow());
+//        c3p0.setUnreturnedConnectionTimeout(datasource.getPoolProperties().getRemoveAbandonedTimeout());
+//        c3p0.setUser(datasource.getPoolProperties().getUsername());
+//        c3p0.setUsesTraditionalReflectiveProxies(true);
+//        c3p0.setJdbcUrl(datasource.getPoolProperties().getUrl());
+//        c3p0.setDriverClass(datasource.getPoolProperties().getDriverClassName());
+//        this.c3p0Datasource = c3p0;
+        
+      /**
+        acquireIncrement
+        acquireRetryAttempts
+        acquireRetryDelay
+        autoCommitOnClose
+        automaticTestTable
+        breakAfterAcquireFailure
+        checkoutTimeout
+        connectionCustomizerClassName
+        connectionTesterClassName
+        debugUnreturnedConnectionStackTraces
+        factoryClassLocation
+        forceIgnoreUnresolvedTransactions
+        idleConnectionTestPeriod
+        initialPoolSize
+        maxAdministrativeTaskTime
+        maxConnectionAge
+        maxIdleTime
+        maxIdleTimeExcessConnections
+        maxPoolSize
+        maxStatements
+        maxStatementsPerConnection
+        minPoolSize
+        numHelperThreads
+        overrideDefaultUser
+        overrideDefaultPassword
+        password
+        preferredTestQuery
+        propertyCycle
+        testConnectionOnCheckin
+        testConnectionOnCheckout
+        unreturnedConnectionTimeout
+        user
+        usesTraditionalReflectiveProxies
+        */
+    }
+
+
+    @Override
+    protected void tearDown() throws Exception {
+        try {datasource.close();}catch(Exception ignore){}
+        try {tDatasource.close();}catch(Exception ignore){}
+        //try {((ComboPooledDataSource)c3p0Datasource).close(true);}catch(Exception ignore){}
+        datasource = null;
+        tDatasource = null;
+        //c3p0Datasource = null;
+        System.gc();
+        org.apache.tomcat.jdbc.test.driver.Driver.reset();
+    }
+
+    private final static String PROP_DEFAULTAUTOCOMMIT = "defaultAutoCommit";
+    private final static String PROP_DEFAULTREADONLY = "defaultReadOnly";
+    private final static String PROP_DEFAULTTRANSACTIONISOLATION = "defaultTransactionIsolation";
+    private final static String PROP_DEFAULTCATALOG = "defaultCatalog";
+    private final static String PROP_DRIVERCLASSNAME = "driverClassName";
+    private final static String PROP_MAXACTIVE = "maxActive";
+    private final static String PROP_MAXIDLE = "maxIdle";
+    private final static String PROP_MINIDLE = "minIdle";
+    private final static String PROP_INITIALSIZE = "initialSize";
+    private final static String PROP_MAXWAIT = "maxWait";
+    private final static String PROP_TESTONBORROW = "testOnBorrow";
+    private final static String PROP_TESTONRETURN = "testOnReturn";
+    private final static String PROP_TIMEBETWEENEVICTIONRUNSMILLIS = "timeBetweenEvictionRunsMillis";
+    private final static String PROP_NUMTESTSPEREVICTIONRUN = "numTestsPerEvictionRun";
+    private final static String PROP_MINEVICTABLEIDLETIMEMILLIS = "minEvictableIdleTimeMillis";
+    private final static String PROP_TESTWHILEIDLE = "testWhileIdle";
+    private final static String PROP_PASSWORD = "password";
+    private final static String PROP_URL = "url";
+    private final static String PROP_USERNAME = "username";
+    private final static String PROP_VALIDATIONQUERY = "validationQuery";
+    private final static String PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED = "accessToUnderlyingConnectionAllowed";
+    private final static String PROP_REMOVEABANDONED = "removeAbandoned";
+    private final static String PROP_REMOVEABANDONEDTIMEOUT = "removeAbandonedTimeout";
+    private final static String PROP_LOGABANDONED = "logAbandoned";
+    private final static String PROP_POOLPREPAREDSTATEMENTS = "poolPreparedStatements";
+    private final static String PROP_MAXOPENPREPAREDSTATEMENTS = "maxOpenPreparedStatements";
+    private final static String PROP_CONNECTIONPROPERTIES = "connectionProperties";
+
+    private final static String[] ALL_PROPERTIES = {
+        PROP_DEFAULTAUTOCOMMIT,
+        PROP_DEFAULTREADONLY,
+        PROP_DEFAULTTRANSACTIONISOLATION,
+        PROP_DEFAULTCATALOG,
+        PROP_DRIVERCLASSNAME,
+        PROP_MAXACTIVE,
+        PROP_MAXIDLE,
+        PROP_MINIDLE,
+        PROP_INITIALSIZE,
+        PROP_MAXWAIT,
+        PROP_TESTONBORROW,
+        PROP_TESTONRETURN,
+        PROP_TIMEBETWEENEVICTIONRUNSMILLIS,
+        PROP_NUMTESTSPEREVICTIONRUN,
+        PROP_MINEVICTABLEIDLETIMEMILLIS,
+        PROP_TESTWHILEIDLE,
+        PROP_PASSWORD,
+        PROP_URL,
+        PROP_USERNAME,
+        PROP_VALIDATIONQUERY,
+        PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED,
+        PROP_REMOVEABANDONED,
+        PROP_REMOVEABANDONEDTIMEOUT,
+        PROP_LOGABANDONED,
+        PROP_CONNECTIONPROPERTIES
+    };
+
+
+
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/FairnessTest.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/FairnessTest.java
new file mode 100644 (file)
index 0000000..b296eee
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * 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.util.concurrent.CountDownLatch;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.sql.Connection;
+import java.sql.Statement;
+import java.sql.ResultSet;
+
+import javax.sql.DataSource;
+
+import org.apache.tomcat.jdbc.pool.DataSourceProxy;
+
+/**
+ * @author Filip Hanik
+ * @version 1.0
+ */
+public class FairnessTest extends DefaultTestCase {
+    public FairnessTest(String name) {
+        super(name);
+    }
+    
+    protected boolean run = true;
+    protected long sleep = Long.getLong("sleep", 10);
+    protected long complete = Long.getLong("complete",20000);
+    protected boolean printthread = Boolean.getBoolean("printthread");
+    CountDownLatch latch = null;
+    protected void printThreadResults(TestThread[] threads, String name, int active, int expected) {
+        long minfetch = Long.MAX_VALUE, maxfetch = Long.MIN_VALUE, totalfetch = 0;
+        long maxwait = 0, minwait = Long.MAX_VALUE, averagewait = 0, totalwait = 0;
+        float avgfetch = 0;
+        for (int i=0; i<threads.length; i++) {
+            TestThread t = threads[i];
+            totalfetch += t.nroffetch;
+            totalwait  += t.totalwait;
+            maxwait = Math.max(maxwait,t.maxwait);
+            minwait = Math.min(minwait, t.minwait);
+            minfetch = Math.min(minfetch, t.nroffetch);
+            maxfetch = Math.max(maxfetch, t.nroffetch);
+            if (FairnessTest.this.printthread)
+                System.out.println(t.getName()+" : Nr-of-fetch:"+t.nroffetch+ " Max fetch Time:"+(((float)t.maxwait)/1000000f)+"ms. :Max close time:"+(((float)t.cmax)/1000000f)+"ms.");
+        }
+        System.out.println("["+name+"] Max fetch:"+(maxfetch)+" Min fetch:"+(minfetch)+" Average fetch:"+
+                           (((float)totalfetch))/(float)threads.length);
+        System.out.println("["+name+"] Max wait:"+(((float)maxwait)/1000000f)+"ms. Min wait:"+(((float)minwait)/1000000f)+"ms. Average wait:"+(((((float)totalwait))/(float)totalfetch)/1000000f)+" ms.");
+        System.out.println("["+name+"] Max active:"+active+" Expected Active:"+expected);
+        
+        
+    }
+    
+    public void testDBCPThreads20Connections10() throws Exception {
+        System.out.println("[testDBCPThreads20Connections10] Starting fairness - DBCP");
+        init();
+        this.datasource.getPoolProperties().setMaxActive(10);
+        this.threadcount = 20;
+        this.transferProperties();
+        this.tDatasource.getConnection().close();
+        latch = new CountDownLatch(threadcount);
+        long start = System.currentTimeMillis();
+        TestThread[] threads = new TestThread[threadcount];
+        for (int i=0; i<threadcount; i++) {
+            threads[i] = new TestThread();
+            threads[i].setName("tomcat-dbcp-"+i);
+            threads[i].d = this.tDatasource;
+            
+        }
+        for (int i=0; i<threadcount; i++) {
+            threads[i].start();
+        }
+        if (!latch.await(complete+1000,TimeUnit.MILLISECONDS)) {
+            System.out.println("Latch timed out.");
+        }
+        this.run = false;
+        long delta = System.currentTimeMillis() - start;
+        printThreadResults(threads,"testDBCPThreads20Connections10",this.tDatasource.getNumActive(),10);
+        tearDown();
+    }
+
+    public void testPoolThreads20Connections10() throws Exception {
+        System.out.println("[testPoolThreads20Connections10] Starting fairness - Tomcat JDBC - Non Fair");
+        init();
+        this.datasource.getPoolProperties().setMaxActive(10);
+        this.datasource.getPoolProperties().setFairQueue(false);
+        this.threadcount = 20;
+        this.transferProperties();
+        this.datasource.getConnection().close();
+        latch = new CountDownLatch(threadcount);
+        long start = System.currentTimeMillis();
+        TestThread[] threads = new TestThread[threadcount];
+        for (int i=0; i<threadcount; i++) {
+            threads[i] = new TestThread();
+            threads[i].setName("tomcat-pool-"+i);
+            threads[i].d = this.datasource;
+            
+        }
+        for (int i=0; i<threadcount; i++) {
+            threads[i].start();
+        }
+        if (!latch.await(complete+1000,TimeUnit.MILLISECONDS)) {
+            System.out.println("Latch timed out.");
+        }
+        this.run = false;
+        long delta = System.currentTimeMillis() - start;
+        printThreadResults(threads,"testPoolThreads20Connections10",this.datasource.getSize(),10);
+        tearDown();
+
+    }
+
+    public void testPoolThreads20Connections10Fair() throws Exception {
+        System.out.println("[testPoolThreads20Connections10Fair] Starting fairness - Tomcat JDBC - Fair");
+        init();
+        this.datasource.getPoolProperties().setMaxActive(10);
+        this.datasource.getPoolProperties().setFairQueue(true);
+        this.threadcount = 20;
+        this.transferProperties();
+        this.datasource.getConnection().close();
+        latch = new CountDownLatch(threadcount);
+        long start = System.currentTimeMillis();
+        TestThread[] threads = new TestThread[threadcount];
+        for (int i=0; i<threadcount; i++) {
+            threads[i] = new TestThread();
+            threads[i].setName("tomcat-pool-"+i);
+            threads[i].d = this.datasource;
+            
+        }
+        for (int i=0; i<threadcount; i++) {
+            threads[i].start();
+        }
+        if (!latch.await(complete+1000,TimeUnit.MILLISECONDS)) {
+            System.out.println("Latch timed out.");
+        }
+        this.run = false;
+        long delta = System.currentTimeMillis() - start;
+        printThreadResults(threads,"testPoolThreads20Connections10Fair",this.datasource.getSize(),10);
+        tearDown();
+    }
+    public void testPoolThreads20Connections10FairAsync() throws Exception {
+        System.out.println("[testPoolThreads20Connections10FairAsync] Starting fairness - Tomcat JDBC - Fair - Async");
+        init();
+        this.datasource.getPoolProperties().setMaxActive(10);
+        this.datasource.getPoolProperties().setFairQueue(true);
+        this.threadcount = 20;
+        this.transferProperties();
+        this.datasource.getConnection().close();
+        latch = new CountDownLatch(threadcount);
+        long start = System.currentTimeMillis();
+        TestThread[] threads = new TestThread[threadcount];
+        for (int i=0; i<threadcount; i++) {
+            threads[i] = new TestThread();
+            threads[i].setName("tomcat-pool-"+i);
+            threads[i].async = true;
+            threads[i].d = this.datasource;
+            
+        }
+        for (int i=0; i<threadcount; i++) {
+            threads[i].start();
+        }
+        if (!latch.await(complete+1000,TimeUnit.MILLISECONDS)) {
+            System.out.println("Latch timed out.");
+        }
+        this.run = false;
+        long delta = System.currentTimeMillis() - start;
+        printThreadResults(threads,"testPoolThreads20Connections10FairAsync",this.datasource.getSize(),10);
+        tearDown();
+    }
+    
+//    public void testC3P0Threads20Connections10() throws Exception {
+//        System.out.println("[testC3P0Threads20Connections10] Starting fairness - C3P0");
+//        init();
+//        this.datasource.getPoolProperties().setMaxActive(10);
+//        this.datasource.getPoolProperties().setFairQueue(false);
+//        this.threadcount = 20;
+//        this.transferPropertiesToC3P0();
+//        this.datasource.getConnection().close();
+//        latch = new CountDownLatch(threadcount);
+//        long start = System.currentTimeMillis();
+//        TestThread[] threads = new TestThread[threadcount];
+//        for (int i=0; i<threadcount; i++) {
+//            threads[i] = new TestThread();
+//            threads[i].setName("tomcat-pool-"+i);
+//            threads[i].d = this.c3p0Datasource;
+//            
+//        }
+//        for (int i=0; i<threadcount; i++) {
+//            threads[i].start();
+//        }
+//        if (!latch.await(complete+1000,TimeUnit.MILLISECONDS)) {
+//            System.out.println("Latch timed out.");
+//        }
+//        this.run = false;
+//        long delta = System.currentTimeMillis() - start;
+//        printThreadResults(threads,"testC3P0Threads20Connections10",c3p0Datasource.getNumConnectionsAllUsers(),10);
+//        tearDown();
+//
+//    }
+
+    
+    public class TestThread extends Thread {
+        protected DataSource d;
+        protected String query = null;
+        protected long sleep = 10;
+        protected boolean async = false;
+        long minwait = Long.MAX_VALUE, maxwait = -1, totalwait=0, totalcmax=0, cmax = -1, nroffetch = 0, totalruntime = 0;
+        @Override
+        public void run() {
+            try {
+                long now = System.currentTimeMillis();
+                while (FairnessTest.this.run) {
+                    if ((System.currentTimeMillis()-now)>=FairnessTest.this.complete) break;
+                    long start = System.nanoTime();
+                    Connection con = null;
+                    try {
+                        if (async) {
+                            Future<Connection> cf = ((DataSourceProxy)d).getConnectionAsync();
+                            con  = cf.get();
+                        } else {
+                            con = d.getConnection();
+                        }
+                        long delta = System.nanoTime() - start;
+                        totalwait += delta;
+                        maxwait = Math.max(delta, maxwait);
+                        minwait = Math.min(delta, minwait);
+                        nroffetch++;
+                        if (query!=null) {
+                            Statement st = con.createStatement();
+                            ResultSet rs = st.executeQuery(query);
+                            while (rs.next()) {
+                            }
+                            rs.close();
+                            st.close();
+                        }
+                        try { 
+                            if (FairnessTest.this.sleep>0) sleep(FairnessTest.this.sleep); 
+                        } catch (InterruptedException x) {
+                            interrupted();
+                        }
+                    } finally {
+                        long cstart = System.nanoTime();
+                        if (con!=null) try {con.close();}catch(Exception x) {x.printStackTrace();}
+                        long cdelta = System.nanoTime() - cstart;
+                        totalcmax += cdelta;
+                        cmax = Math.max(cdelta, cmax);
+                    }
+                    totalruntime+=(System.nanoTime()-start);
+                }
+
+            } catch (Exception x) {
+                x.printStackTrace();
+            } finally {
+                FairnessTest.this.latch.countDown();
+            }
+            if (System.getProperty("print-thread-stats")!=null) {
+                System.out.println("["+getName()+"] "+
+                    "\n\tMax time to retrieve connection:"+(((float)maxwait)/1000f/1000f)+" ms."+
+                    "\n\tTotal time to retrieve connection:"+(((float)totalwait)/1000f/1000f)+" ms."+
+                    "\n\tAverage time to retrieve connection:"+(((float)totalwait)/1000f/1000f)/(float)nroffetch+" ms."+
+                    "\n\tMax time to close connection:"+(((float)cmax)/1000f/1000f)+" ms."+
+                    "\n\tTotal time to close connection:"+(((float)totalcmax)/1000f/1000f)+" ms."+
+                    "\n\tAverage time to close connection:"+(((float)totalcmax)/1000f/1000f)/(float)nroffetch+" ms."+
+                    "\n\tRun time:"+(((float)totalruntime)/1000f/1000f)+" ms."+
+                    "\n\tNr of fetch:"+nroffetch);
+            }
+        }
+    }
+}
+
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/JmxPasswordTest.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/JmxPasswordTest.java
new file mode 100644 (file)
index 0000000..5c63f70
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * 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.lang.management.ManagementFactory;
+import java.util.Hashtable;
+import java.util.Properties;
+
+import javax.management.JMX;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.apache.tomcat.jdbc.pool.ConnectionPool;
+import org.apache.tomcat.jdbc.pool.PoolUtilities;
+import org.apache.tomcat.jdbc.pool.jmx.ConnectionPoolMBean;
+import org.apache.tomcat.jdbc.test.driver.Driver;
+
+public class JmxPasswordTest extends DefaultTestCase{
+    public static final String password = "password";
+    public static final String username = "username";
+    public static ObjectName oname = null;
+    
+    public JmxPasswordTest(String s) {
+        super(s);
+    }
+    
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        this.datasource.setDriverClassName(Driver.class.getName());
+        this.datasource.setUrl("jdbc:tomcat:test");
+        this.datasource.setPassword(password);
+        this.datasource.setUsername(username);
+        this.datasource.getConnection().close();
+        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+        String domain = "tomcat.jdbc";
+        Hashtable<String,String> properties = new Hashtable<String,String>();
+        properties.put("type", "ConnectionPool");
+        properties.put("class", this.getClass().getName());
+        oname = new ObjectName(domain,properties);
+        ConnectionPool pool = datasource.createPool();
+        org.apache.tomcat.jdbc.pool.jmx.ConnectionPool jmxPool = new org.apache.tomcat.jdbc.pool.jmx.ConnectionPool(pool);
+        mbs.registerMBean(jmxPool, oname);
+        
+    }
+    
+    public void testPassword() throws Exception {
+        assertEquals("Passwords should match when not using JMX.",password,datasource.getPoolProperties().getPassword());
+        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+        ConnectionPoolMBean mbean = JMX.newMBeanProxy(mbs, oname, ConnectionPoolMBean.class);
+        String jmxPassword = mbean.getPassword();
+        Properties jmxProperties = mbean.getDbProperties();
+        assertFalse("Passwords should not match.", password.equals(jmxPassword));
+        assertFalse("Password property should be missing", jmxProperties.containsKey(PoolUtilities.PROP_PASSWORD));
+    }
+    
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/SimplePOJOAsyncExample.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/SimplePOJOAsyncExample.java
new file mode 100644 (file)
index 0000000..c3cd071
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * 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.ResultSet;
+import java.sql.Statement;
+import java.util.concurrent.Future;
+
+import org.apache.tomcat.jdbc.pool.DataSource;
+import org.apache.tomcat.jdbc.pool.PoolConfiguration;
+import org.apache.tomcat.jdbc.pool.PoolProperties;
+
+public class SimplePOJOAsyncExample {
+
+    public static void main(String[] args) throws Exception {
+        PoolConfiguration p = new PoolProperties();
+        p.setFairQueue(true);
+        p.setUrl("jdbc:mysql://localhost:3306/mysql?autoReconnect=true");
+        p.setDriverClassName("com.mysql.jdbc.Driver");
+        p.setUsername("root");
+        p.setPassword("password");
+        p.setJmxEnabled(true);
+        p.setTestWhileIdle(false);
+        p.setTestOnBorrow(true);
+        p.setValidationQuery("SELECT 1");
+        p.setTestOnReturn(false);
+        p.setValidationInterval(30000);
+        p.setTimeBetweenEvictionRunsMillis(30000);
+        p.setMaxActive(100);
+        p.setInitialSize(10);
+        p.setMaxWait(10000);
+        p.setRemoveAbandonedTimeout(60);
+        p.setMinEvictableIdleTimeMillis(30000);
+        p.setMinIdle(10);
+        p.setLogAbandoned(true);
+        p.setRemoveAbandoned(true);
+        p.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");
+        DataSource datasource = new DataSource();
+        datasource.setPoolProperties(p); 
+        
+        Connection con = null;
+        try {            
+          Future<Connection> future = datasource.getConnectionAsync();
+          while (!future.isDone()) {
+              System.out.println("Connection is not yet available. Do some background work");
+              try {
+                  Thread.sleep(100); //simulate work
+              }catch (InterruptedException x) {
+                  Thread.interrupted();
+              }
+          }
+          con = future.get(); //should return instantly 
+          Statement st = con.createStatement();
+          ResultSet rs = st.executeQuery("select * from user");
+          int cnt = 1;
+          while (rs.next()) {
+              System.out.println((cnt++)+". Host:" +rs.getString("Host")+" User:"+rs.getString("User")+" Password:"+rs.getString("Password"));
+          }
+          rs.close();
+          st.close();
+        } finally {
+          if (con!=null) try {con.close();}catch (Exception ignore) {}
+        }  
+    }
+
+}
\ No newline at end of file
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/SimplePOJOExample.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/SimplePOJOExample.java
new file mode 100644 (file)
index 0000000..5036857
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * 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.ResultSet;
+import java.sql.Statement;
+
+import org.apache.tomcat.jdbc.pool.DataSource;
+import org.apache.tomcat.jdbc.pool.PoolConfiguration;
+import org.apache.tomcat.jdbc.pool.PoolProperties;
+
+public class SimplePOJOExample {
+
+    public static void main(String[] args) throws Exception {
+        PoolConfiguration p = new PoolProperties();
+        p.setUrl("jdbc:mysql://localhost:3306/mysql?autoReconnect=true");
+        p.setDriverClassName("com.mysql.jdbc.Driver");
+        p.setUsername("root");
+        p.setPassword("password");
+        p.setJmxEnabled(true);
+        p.setTestWhileIdle(false);
+        p.setTestOnBorrow(true);
+        p.setValidationQuery("SELECT 1");
+        p.setTestOnReturn(false);
+        p.setValidationInterval(30000);
+        p.setTimeBetweenEvictionRunsMillis(30000);
+        p.setMaxActive(100);
+        p.setInitialSize(10);
+        p.setMaxWait(10000);
+        p.setRemoveAbandonedTimeout(60);
+        p.setMinEvictableIdleTimeMillis(30000);
+        p.setMinIdle(10);
+        p.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");
+        p.setLogAbandoned(true);
+        p.setRemoveAbandoned(true);
+        DataSource datasource = new DataSource();
+        datasource.setPoolProperties(p); 
+        
+        Connection con = null;
+        try {            
+          con = datasource.getConnection();
+          Statement st = con.createStatement();
+          ResultSet rs = st.executeQuery("select * from user");
+          int cnt = 1;
+          while (rs.next()) {
+              System.out.println((cnt++)+". Host:" +rs.getString("Host")+" User:"+rs.getString("User")+" Password:"+rs.getString("Password"));
+          }
+          rs.close();
+          st.close();
+        } finally {
+          if (con!=null) try {con.close();}catch (Exception ignore) {}
+        }  
+    }
+
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/StarvationTest.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/StarvationTest.java
new file mode 100644 (file)
index 0000000..8013ba5
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * 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.SQLException;
+
+/**
+ * If a connection is abandoned and closed, 
+ * then that should free up a spot in the pool, and other threads 
+ * that are waiting should not time out and throw an error but be 
+ * able to acquire a connection, since one was just released.
+ * @author fhanik
+ *
+ */
+public class StarvationTest extends DefaultTestCase {
+
+    public StarvationTest(String name) {
+        super(name);
+    }
+    
+    private void config() {
+        datasource.getPoolProperties().setMaxActive(1);
+        datasource.getPoolProperties().setMaxIdle(1);
+        datasource.getPoolProperties().setInitialSize(1);
+        datasource.getPoolProperties().setRemoveAbandoned(true);
+        datasource.getPoolProperties().setRemoveAbandonedTimeout(5);
+        datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(500);
+        datasource.getPoolProperties().setMaxWait(10000);
+        datasource.getPoolProperties().setLogAbandoned(true);
+    }
+    
+//    public void testDBCPConnectionStarvation() throws Exception {
+//        init();
+//        config();
+//        this.transferProperties();
+//        this.tDatasource.getConnection().close();
+//        javax.sql.DataSource datasource = this.tDatasource;
+//        Connection con1 = datasource.getConnection(); 
+//        Connection con2 = null;
+//        try {
+//            con2 = datasource.getConnection();
+//            try {
+//                con2.setCatalog("mysql");//make sure connection is valid
+//            }catch (SQLException x) {
+//                assertFalse("2nd Connection is not valid:"+x.getMessage(),true);
+//            }
+//            assertTrue("Connection 1 should be closed.",con1.isClosed()); //first connection should be closed
+//        }catch (Exception x) {
+//            assertFalse("Connection got starved:"+x.getMessage(),true);
+//        }finally {
+//            if (con2!=null) con2.close();
+//        }
+//
+//    }
+    
+    public void testConnectionStarvation() throws Exception {
+        init();
+        config();
+        Connection con1 = datasource.getConnection(); 
+        Connection con2 = null;
+        try {
+            con2 = datasource.getConnection();
+            try {
+                con2.setCatalog("mysql");//make sure connection is valid
+            }catch (SQLException x) {
+                assertFalse("2nd Connection is not valid:"+x.getMessage(),true);
+            }
+            assertTrue("Connection 1 should be closed.",con1.isClosed()); //first connection should be closed
+        }catch (Exception x) {
+            assertFalse("Connection got starved:"+x.getMessage(),true);
+        }finally {
+            if (con2!=null) con2.close();
+        }
+    }
+
+    public void testFairConnectionStarvation() throws Exception {
+        init();
+        config();
+        datasource.getPoolProperties().setFairQueue(true);
+        Connection con1 = datasource.getConnection(); 
+        Connection con2 = null;
+        try {
+            con2 = datasource.getConnection();
+            try {
+                con2.setCatalog("mysql");//make sure connection is valid
+            }catch (SQLException x) {
+                assertFalse("2nd Connection is not valid:"+x.getMessage(),true);
+            }
+            assertTrue("Connection 1 should be closed.",con1.isClosed()); //first connection should be closed
+        }catch (Exception x) {
+            assertFalse("Connection got starved:"+x.getMessage(),true);
+        }finally {
+            if (con2!=null) con2.close();
+        }
+    }
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/StatementFinalizerTest.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/StatementFinalizerTest.java
new file mode 100644 (file)
index 0000000..b2570a5
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ *  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.Statement;
+
+import org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;
+
+public class StatementFinalizerTest extends DefaultTestCase {
+
+    public StatementFinalizerTest(String name) {
+        super(name);
+    }
+    
+    public void testStatementFinalization() throws Exception {
+        this.init();
+        datasource.setJdbcInterceptors(StatementFinalizer.class.getName());
+        Connection con = datasource.getConnection();
+        Statement st = con.createStatement();
+        assertFalse("Statement should not be closed.",st.isClosed());
+        con.close();
+        assertTrue("Statement should be closed.",st.isClosed());
+    }
+
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestAsyncQueue.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestAsyncQueue.java
new file mode 100644 (file)
index 0000000..7f21c52
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ *  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.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.tomcat.jdbc.pool.FairBlockingQueue;
+
+import junit.framework.TestCase;
+
+public class TestAsyncQueue extends TestCase {
+    protected FairBlockingQueue<Object> queue = null;
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        this.queue = new FairBlockingQueue<Object>();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        this.queue = null;
+        super.tearDown();
+    }
+    
+    
+    public void testAsyncPoll1() throws Exception {
+        Object item = new Object();
+        queue.offer(item);
+        Future<Object> future = queue.pollAsync();
+        assertEquals(future.get(),item);
+    }
+
+    public void testAsyncPoll2() throws Exception {
+        Object item = new Object();
+        OfferThread thread = new OfferThread(item,5000);
+        thread.start();
+        Future<Object> future = queue.pollAsync();
+        try {
+            future.get(2000, TimeUnit.MILLISECONDS);
+            assertFalse("Request should have timed out",true);
+        }catch (TimeoutException x) {
+            assertTrue("Request timed out properly",true);
+        }catch (Exception x) {
+            assertTrue("Request threw an error",false);
+            x.printStackTrace();
+        }
+        assertEquals(future.get(),item);
+    }
+
+    protected class OfferThread extends Thread {
+        Object item = null;
+        long delay = 5000;
+        volatile boolean offered = false;
+        public OfferThread(Object i, long d) {
+            this.item = i;
+            this.delay = d;
+            this.setDaemon(false);
+            this.setName(TestAsyncQueue.class.getName()+"-OfferThread");
+        }
+        @Override
+        public void run() {
+            try {
+                sleep(delay);
+            }catch (Exception ignore){}
+            offered = true;
+            TestAsyncQueue.this.queue.offer(item);
+        }
+    }
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestConcurrency.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestConcurrency.java
new file mode 100644 (file)
index 0000000..6a22d0a
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ *  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.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.tomcat.jdbc.pool.DataSource;
+import org.apache.tomcat.jdbc.test.driver.Driver;
+
+public class TestConcurrency extends DefaultTestCase {
+
+    public static final  boolean debug = Boolean.getBoolean("jdbc.debug");
+    
+    protected volatile DataSource ds = null;
+    
+    public TestConcurrency(String name) {
+        super(name);
+    }
+    
+    @Override
+    public void setUp() {
+        // TODO Auto-generated method stub
+        ds = createDefaultDataSource();
+        ds.getPoolProperties().setDriverClassName(Driver.class.getName());
+        ds.getPoolProperties().setUrl(Driver.url);
+        ds.getPoolProperties().setInitialSize(0);
+        ds.getPoolProperties().setMaxIdle(0);
+        ds.getPoolProperties().setMinIdle(0);
+        ds.getPoolProperties().setMaxActive(10);
+        ds.getPoolProperties().setRemoveAbandoned(true);
+        ds.getPoolProperties().setLogAbandoned(true);
+        ds.getPoolProperties().setTestWhileIdle(true);
+        ds.getPoolProperties().setMinEvictableIdleTimeMillis(750);
+        ds.getPoolProperties().setTimeBetweenEvictionRunsMillis(25);
+        ds.setFairQueue(true);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        ds.close(true);
+        Driver.reset();
+        super.tearDown();
+    }
+    
+    public void testSimple() throws Exception {
+        ds.getConnection().close();
+        final int iter = 1000 * 10;
+        final AtomicInteger loopcount = new AtomicInteger(0);
+        final Runnable run = new Runnable() {
+            public void run() {
+                try {
+                    while (loopcount.incrementAndGet() < iter) {
+                        Connection con = ds.getConnection();
+                        Thread.sleep(10);
+                        con.close();
+                    }
+                }catch (Exception x) {
+                    loopcount.set(iter); //stops the test
+                    x.printStackTrace();
+                }
+            }
+        };
+        Thread[] threads = new Thread[20];
+        for (int i=0; i<threads.length; i++) {
+            threads[i] = new Thread(run);
+        }
+        for (int i=0; i<threads.length; i++) {
+            threads[i].start();
+        }
+        try {
+            while (loopcount.get()<iter) {
+                assertTrue("Size comparison(less than 11):",ds.getPool().getSize()<=10);
+                if (debug) {
+                    System.out.println("Size: "+ds.getPool().getSize());
+                    System.out.println("Used: "+ds.getPool().getActive());
+                    System.out.println("Idle: "+ds.getPool().getIdle());
+                    System.out.println("Wait: "+ds.getPool().getWaitCount());
+                }
+                Thread.sleep(250);
+            }
+        }catch (Exception x) {
+            loopcount.set(iter); //stops the test
+            x.printStackTrace();
+        }
+        for (int i=0; i<threads.length; i++) {
+            threads[i].join();
+        }
+        assertEquals("Size comparison:",10, ds.getPool().getSize());
+        assertEquals("Idle comparison:",10, ds.getPool().getIdle());
+        assertEquals("Used comparison:",0, ds.getPool().getActive());
+        assertEquals("Connect count",10,Driver.connectCount.get());
+            
+    }
+    
+    public void testBrutal() throws Exception {
+        ds.getPoolProperties().setRemoveAbandoned(false);
+        ds.getPoolProperties().setRemoveAbandonedTimeout(1);
+        ds.getPoolProperties().setMinEvictableIdleTimeMillis(100);
+        ds.getPoolProperties().setTimeBetweenEvictionRunsMillis(10);
+        ds.getConnection().close();
+        final int iter = 100000 * 10;
+        final AtomicInteger loopcount = new AtomicInteger(0);
+        final Runnable run = new Runnable() {
+            public void run() {
+                try {
+                    while (loopcount.incrementAndGet() < iter) {
+                        Connection con = ds.getConnection();
+                        con.close();
+                    }
+                }catch (Exception x) {
+                    loopcount.set(iter); //stops the test
+                    x.printStackTrace();
+                }
+            }
+        };
+        Thread[] threads = new Thread[20];
+        for (int i=0; i<threads.length; i++) {
+            threads[i] = new Thread(run);
+        }
+        for (int i=0; i<threads.length; i++) {
+            threads[i].start();
+        }
+        try {
+            while (loopcount.get()<iter) {
+                assertTrue("Size comparison(less than 11):",ds.getPool().getSize()<=10);
+                ds.getPool().testAllIdle();
+                ds.getPool().checkAbandoned();
+                ds.getPool().checkIdle();
+            }
+        }catch (Exception x) {
+            loopcount.set(iter); //stops the test
+            x.printStackTrace();
+        }
+        for (int i=0; i<threads.length; i++) {
+            threads[i].join();
+        }
+        System.out.println("Connect count:"+Driver.connectCount.get());
+        System.out.println("DisConnect count:"+Driver.disconnectCount.get());
+        assertEquals("Size comparison:",10, ds.getPool().getSize());
+        assertEquals("Idle comparison:",10, ds.getPool().getIdle());
+        assertEquals("Used comparison:",0, ds.getPool().getActive());
+        assertEquals("Connect count",10,Driver.connectCount.get());
+    }
+
+    public void testBrutalNonFair() throws Exception {
+        ds.getPoolProperties().setRemoveAbandoned(false);
+        ds.getPoolProperties().setRemoveAbandonedTimeout(1);
+        ds.getPoolProperties().setMinEvictableIdleTimeMillis(100);
+        ds.getPoolProperties().setTimeBetweenEvictionRunsMillis(10);
+        ds.getConnection().close();
+        final int iter = 100000 * 10;
+        final AtomicInteger loopcount = new AtomicInteger(0);
+        final Runnable run = new Runnable() {
+            public void run() {
+                try {
+                    while (loopcount.incrementAndGet() < iter) {
+                        Connection con = ds.getConnection();
+                        con.close();
+                    }
+                }catch (Exception x) {
+                    loopcount.set(iter); //stops the test
+                    x.printStackTrace();
+                }
+            }
+        };
+        Thread[] threads = new Thread[20];
+        for (int i=0; i<threads.length; i++) {
+            threads[i] = new Thread(run);
+        }
+        for (int i=0; i<threads.length; i++) {
+            threads[i].start();
+        }
+        try {
+            while (loopcount.get()<iter) {
+                assertTrue("Size comparison(less than 11):",ds.getPool().getSize()<=10);
+                ds.getPool().testAllIdle();
+                ds.getPool().checkAbandoned();
+                ds.getPool().checkIdle();
+            }
+        }catch (Exception x) {
+            loopcount.set(iter); //stops the test
+            x.printStackTrace();
+        }
+        for (int i=0; i<threads.length; i++) {
+            threads[i].join();
+        }
+        System.out.println("Connect count:"+Driver.connectCount.get());
+        System.out.println("DisConnect count:"+Driver.disconnectCount.get());
+        assertEquals("Size comparison:",10, ds.getPool().getSize());
+        assertEquals("Idle comparison:",10, ds.getPool().getIdle());
+        assertEquals("Used comparison:",0, ds.getPool().getActive());
+        assertEquals("Connect count",10,Driver.connectCount.get());
+    }
+    
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestConnectionState.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestConnectionState.java
new file mode 100644 (file)
index 0000000..8ed9bb2
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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 org.apache.tomcat.jdbc.pool.DataSourceProxy;
+import org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;
+
+public class TestConnectionState extends DefaultTestCase {
+
+    public TestConnectionState(String name) {
+        super(name);
+    }
+
+    public void testAutoCommitFalse() throws Exception {
+        DataSourceProxy d1 = this.createDefaultDataSource();
+        d1.setMaxActive(1);
+        d1.setMinIdle(1);
+        d1.setMaxIdle(1);
+        d1.setJdbcInterceptors(ConnectionState.class.getName());
+        d1.setDefaultAutoCommit(Boolean.FALSE);
+        Connection c1 = d1.getConnection();
+        assertFalse("Auto commit should be false",c1.getAutoCommit());
+        c1.setAutoCommit(true);
+        assertTrue("Auto commit should be true",c1.getAutoCommit());
+        c1.close();
+        c1 = d1.getConnection();
+        assertFalse("Auto commit should be false for a reused connection",c1.getAutoCommit());
+        d1.close(true);
+        assertTrue("Connection should be closed",c1.isClosed());
+    }
+    
+    public void testAutoCommitTrue() throws Exception {
+        DataSourceProxy d1 = this.createDefaultDataSource();
+        d1.setMaxActive(1);
+        d1.setJdbcInterceptors(ConnectionState.class.getName());
+        d1.setDefaultAutoCommit(Boolean.TRUE);
+        d1.setMinIdle(1);
+        Connection c1 = d1.getConnection();
+        assertTrue("Auto commit should be true",c1.getAutoCommit());
+        c1.setAutoCommit(false);
+        assertFalse("Auto commit should be false",c1.getAutoCommit());
+        c1.close();
+        c1 = d1.getConnection();
+        assertTrue("Auto commit should be true for a reused connection",c1.getAutoCommit());
+    }
+    
+    public void testDefaultCatalog() throws Exception {
+        DataSourceProxy d1 = this.createDefaultDataSource();
+        d1.setMaxActive(1);
+        d1.setJdbcInterceptors(ConnectionState.class.getName());
+        d1.setDefaultCatalog("information_schema");
+        d1.setMinIdle(1);
+        Connection c1 = d1.getConnection();
+        assertEquals("Catalog should be information_schema",c1.getCatalog(),"information_schema");
+        c1.close();
+        c1 = d1.getConnection();
+        assertEquals("Catalog should be information_schema",c1.getCatalog(),"information_schema");
+        c1.setCatalog("mysql");
+        assertEquals("Catalog should be information_schema",c1.getCatalog(),"mysql");
+        c1.close();
+        c1 = d1.getConnection();
+        assertEquals("Catalog should be information_schema",c1.getCatalog(),"information_schema");
+    }
+
+
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestException.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestException.java
new file mode 100644 (file)
index 0000000..0a8df77
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ *  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 org.apache.tomcat.jdbc.pool.ConnectionPool;
+import org.apache.tomcat.jdbc.pool.JdbcInterceptor;
+import org.apache.tomcat.jdbc.pool.PooledConnection;
+
+public class TestException extends DefaultTestCase {
+
+    public TestException(String name) {
+        super(name);
+    }
+    
+    public void testException() throws Exception {
+        init();
+        datasource.getPoolProperties().setJdbcInterceptors(TestInterceptor.class.getName());
+        Connection con = datasource.getConnection();
+        try {
+            con.createStatement();
+        }catch (Exception x) {
+            
+        }
+    }
+    
+    
+    public static class TestInterceptor extends JdbcInterceptor {
+
+        @Override
+        public void reset(ConnectionPool parent, PooledConnection con) {
+            // TODO Auto-generated method stub
+            
+        }
+
+    
+    }
+
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestGCClose.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestGCClose.java
new file mode 100644 (file)
index 0000000..7bb8157
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 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;
+
+/**
+ * @author Filip Hanik
+ * @version 1.0
+ */
+public class TestGCClose extends DefaultTestCase {
+    public TestGCClose(String name) {
+        super(name);
+    }
+    
+    public void testGCStop() throws Exception {
+        init();
+        datasource.getConnection();
+        System.out.println("Got a connection, but didn't return it");
+        tearDown();
+        Thread.sleep(20000);
+    }
+    
+    public void testClose() throws Exception {
+        init();
+        datasource.getConnection();
+        System.out.println("Got a connection, but didn't return it");
+        datasource.close(true);
+        Thread.sleep(20000);
+    }
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestGetConnection.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestGetConnection.java
new file mode 100644 (file)
index 0000000..1d890b4
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *  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 javax.sql.PooledConnection;
+
+public class TestGetConnection extends DefaultTestCase {
+
+    public TestGetConnection(String name) {
+        super(name);
+    }
+    
+    public void testGetConnection() throws Exception {
+        this.init();
+        Connection con = this.datasource.getConnection();
+        assertTrue("Connection should implement javax.sql.PooledConnection",con instanceof PooledConnection);
+        Connection actual = ((PooledConnection)con).getConnection();
+        assertNotNull("Connection delegate should not be null.",actual);
+        System.out.println("Actual connection:"+actual.getClass().getName());
+        
+    }
+
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestInterceptorShortName.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestInterceptorShortName.java
new file mode 100644 (file)
index 0000000..1641bb8
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ *  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 org.apache.tomcat.jdbc.pool.interceptor.TestInterceptor;
+
+public class TestInterceptorShortName extends DefaultTestCase {
+
+    public TestInterceptorShortName(String name) {
+        super(name);
+    }
+    
+    public void testShortInterceptor() throws Exception {
+        this.datasource = this.createDefaultDataSource();
+        this.datasource.setJdbcInterceptors("TestInterceptor");
+        this.datasource.setMaxActive(1);
+        Connection con = this.datasource.getConnection();
+        assertTrue("Pool should have been started.",TestInterceptor.poolstarted);
+        assertEquals("Only one interceptor should have been called setProperties",1,TestInterceptor.instancecount.get());
+        con.close();
+        this.datasource.close();
+        assertTrue("Pool should have been closed.",TestInterceptor.poolclosed);
+    }
+
+
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestSizePreservation.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestSizePreservation.java
new file mode 100644 (file)
index 0000000..183532e
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ *  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.util.concurrent.atomic.AtomicInteger;
+
+import junit.framework.TestCase;
+
+import org.apache.tomcat.jdbc.pool.DataSource;
+import org.apache.tomcat.jdbc.pool.PoolConfiguration;
+import org.apache.tomcat.jdbc.test.driver.Driver;
+/**
+ * 
+ * @author Jeremy Norris
+ * https://issues.apache.org/bugzilla/show_bug.cgi?id=50613
+ *
+ */
+public class TestSizePreservation extends TestCase {
+
+    protected volatile DataSource ds = null;
+
+    public TestSizePreservation() {
+    }
+
+    private void initSimplePoolProperties() {
+        PoolConfiguration p = new DefaultProperties();
+        ds = new org.apache.tomcat.jdbc.pool.DataSource();
+        ds.setPoolProperties(p);
+
+        ds.getPoolProperties().setDriverClassName(Driver.class.getName());
+        ds.getPoolProperties().setUrl(Driver.url);
+        ds.getPoolProperties().setFairQueue(true);
+        ds.getPoolProperties().setJmxEnabled(false);
+        ds.getPoolProperties().setTestWhileIdle(true);
+        ds.getPoolProperties().setTestOnBorrow(false);
+        ds.getPoolProperties().setTestOnReturn(false);
+        ds.getPoolProperties().setValidationInterval(30000);
+        ds.getPoolProperties().setTimeBetweenEvictionRunsMillis(30000);
+        ds.getPoolProperties().setInitialSize(100);
+        ds.getPoolProperties().setMaxActive(100);
+        ds.getPoolProperties().setMinIdle(0);
+        ds.getPoolProperties().setMaxIdle(0);
+        ds.getPoolProperties().setMaxWait(10000);
+        ds.getPoolProperties().setRemoveAbandonedTimeout(10);
+        ds.getPoolProperties().setMinEvictableIdleTimeMillis(10000);
+        ds.getPoolProperties().setLogAbandoned(false);
+        ds.getPoolProperties().setRemoveAbandoned(false);
+        ds.getPoolProperties().setUseLock(true);
+    }
+
+    private void initEvictingPool() {
+        initSimplePoolProperties();
+        ds.getPoolProperties().setTimeBetweenEvictionRunsMillis(25);
+        ds.getPoolProperties().setMinEvictableIdleTimeMillis(750);
+        ds.getPoolProperties().setRemoveAbandoned(true);
+        ds.getPoolProperties().setRemoveAbandonedTimeout(1);
+    }
+
+    public void testSimple() throws Exception {
+        initSimplePoolProperties();
+        common();
+        ds.close(true);
+        Driver.reset();
+    }
+
+    public void testEvicting() throws Exception {
+        initEvictingPool();
+        common();
+        ds.close(true);
+        Driver.reset();
+    }
+
+    private void common() throws Exception {
+        ds.getConnection().close();
+        final int iterations = 1000;
+        final AtomicInteger loopcount = new AtomicInteger(0);
+        final Runnable run = new Runnable() {
+            public void run() {
+                try {
+                    while (loopcount.incrementAndGet() < iterations) {
+                        Connection c = ds.getConnection();
+                        Thread.sleep(1000);
+                        c.close();
+                    }
+                } catch (Exception x) {
+                    x.printStackTrace();
+                }
+            }
+        };
+        Thread[] threads = new Thread[200];
+        for (int i = 0; i < threads.length; i++) {
+            threads[i] = new Thread(run);
+        }
+        for (int i = 0; i < threads.length; i++) {
+            threads[i].start();
+        }
+        try {
+            while (loopcount.get() < iterations) {
+                Thread.sleep(250);
+            }
+        } catch (Exception x) {
+            loopcount.set(iterations); // stops the test
+            x.printStackTrace();
+        }
+        for (int i = 0; i < threads.length; i++) {
+            threads[i].join();
+        }
+        System.out.println("Pool size:"+ds.getPool().getSize());
+        assertTrue("Size validity check: ", ds.getPool().getSize() >= 0);
+    }
+
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestSlowQueryReport.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestSlowQueryReport.java
new file mode 100644 (file)
index 0000000..33dbec6
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * 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.lang.management.ManagementFactory;
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.util.Map;
+
+import javax.management.AttributeChangeNotification;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+
+import org.apache.tomcat.jdbc.pool.ConnectionPool;
+import org.apache.tomcat.jdbc.pool.interceptor.SlowQueryReport;
+import org.apache.tomcat.jdbc.pool.interceptor.SlowQueryReportJmx;
+
+public class TestSlowQueryReport extends DefaultTestCase {
+
+    public TestSlowQueryReport(String name) {
+        super(name);
+    }
+    
+    public void testSlowSql() throws Exception {
+        int count = 3;
+        this.init();
+        this.datasource.setMaxActive(1);
+        this.datasource.setJdbcInterceptors(SlowQueryReport.class.getName()+"(threshold=50)");
+        Connection con = this.datasource.getConnection();
+        String slowSql = "select count(1) from test where val1 like 'ewq%eq' and val2 = 'ew%rre' and val3 = 'sda%da' and val4 = 'dad%ada'";
+        for (int i=0; i<count; i++) {
+            Statement st = con.createStatement();
+            ResultSet rs = st.executeQuery(slowSql);
+            rs.close();
+            st.close();
+        }
+        Map<String,SlowQueryReport.QueryStats> map = SlowQueryReport.getPoolStats(datasource.getPool().getName());
+        assertNotNull(map);
+        assertEquals(1,map.size());
+        String key = map.keySet().iterator().next();
+        SlowQueryReport.QueryStats stats = map.get(key);
+        System.out.println("Stats:"+stats);
+        
+        for (int i=0; i<count; i++) {
+            PreparedStatement st = con.prepareStatement(slowSql);
+            ResultSet rs = st.executeQuery();
+            rs.close();
+            st.close();
+        }
+        System.out.println("Stats:"+stats);
+        
+        for (int i=0; i<count; i++) {
+            CallableStatement st = con.prepareCall(slowSql);
+            ResultSet rs = st.executeQuery();
+            rs.close();
+            st.close();
+        }
+        System.out.println("Stats:"+stats);
+        ConnectionPool pool = datasource.getPool();
+        con.close();
+        tearDown();
+        //make sure we actually did clean up when the pool closed
+        assertNull(SlowQueryReport.getPoolStats(pool.getName()));
+    }
+
+    public void testSlowSqlJmx() throws Exception {
+        int count = 1;
+        this.init();
+        this.datasource.setMaxActive(1);
+        this.datasource.setJdbcInterceptors(SlowQueryReportJmx.class.getName()+"(threshold=50,notifyPool=false)");
+        Connection con = this.datasource.getConnection();
+        String slowSql = "select count(1) from test where val1 like 'ewq%eq'";
+        for (int i=0; i<count; i++) {
+            Statement st = con.createStatement();
+            ResultSet rs = st.executeQuery(slowSql);
+            rs.close();
+            st.close();
+        }
+        Map<String,SlowQueryReport.QueryStats> map = SlowQueryReport.getPoolStats(datasource.getPool().getName());
+        assertNotNull(map);
+        assertEquals(1,map.size());
+        String key = map.keySet().iterator().next();
+        SlowQueryReport.QueryStats stats = map.get(key);
+        System.out.println("Stats:"+stats);
+        ClientListener listener = new ClientListener();
+        ConnectionPool pool = datasource.getPool();
+        ManagementFactory.getPlatformMBeanServer().addNotificationListener(
+                SlowQueryReportJmx.getObjectName(SlowQueryReportJmx.class, pool.getName()), 
+                listener,
+                null,
+                null);
+        
+        for (int i=0; i<count; i++) {
+            PreparedStatement st = con.prepareStatement(slowSql);
+            ResultSet rs = st.executeQuery();
+            rs.close();
+            st.close();
+        }
+        System.out.println("Stats:"+stats);
+        
+        for (int i=0; i<count; i++) {
+            CallableStatement st = con.prepareCall(slowSql);
+            ResultSet rs = st.executeQuery();
+            rs.close();
+            st.close();
+        }
+        System.out.println("Stats:"+stats);
+        assertEquals("Expecting to have received "+(2*count)+" notifications.",2*count, listener.notificationCount);
+        con.close();
+        tearDown();
+        //make sure we actually did clean up when the pool closed
+        assertNull(SlowQueryReport.getPoolStats(pool.getName()));
+    }
+
+    
+    public void testFastSql() throws Exception {
+        int count = 3;
+        this.init();
+        this.datasource.setMaxActive(1);
+        this.datasource.setJdbcInterceptors(SlowQueryReport.class.getName());
+        Connection con = this.datasource.getConnection();
+        String fastSql = this.datasource.getValidationQuery();
+        for (int i=0; i<count; i++) {
+            Statement st = con.createStatement();
+            ResultSet rs = st.executeQuery(fastSql);
+            rs.close();
+            st.close();
+        }
+        Map<String,SlowQueryReport.QueryStats> map = SlowQueryReport.getPoolStats(datasource.getPool().getName());
+        assertNotNull(map);
+        assertEquals(0,map.size());
+        ConnectionPool pool = datasource.getPool();
+        con.close();
+        tearDown();
+        assertNull(SlowQueryReport.getPoolStats(pool.getName()));
+    }    
+    
+    public void testFailedSql() throws Exception {
+        int count = 3;
+        this.init();
+        this.datasource.setMaxActive(1);
+        this.datasource.setJdbcInterceptors(SlowQueryReport.class.getName());
+        Connection con = this.datasource.getConnection();
+        String slowSql = "select 1 from non_existent";
+        int exceptionCount = 0;
+        for (int i=0; i<count; i++) {
+            Statement st = con.createStatement();
+            try {
+                ResultSet rs = st.executeQuery(slowSql);
+                rs.close();
+            }catch (Exception x) {
+                exceptionCount++;
+            }
+            st.close();
+            
+        }
+        Map<String,SlowQueryReport.QueryStats> map = SlowQueryReport.getPoolStats(datasource.getPool().getName());
+        assertNotNull(map);
+        assertEquals(1,map.size());
+        ConnectionPool pool = datasource.getPool();
+        String key = map.keySet().iterator().next();
+        SlowQueryReport.QueryStats stats = map.get(key);
+        System.out.println("Stats:"+stats);
+        con.close();
+        tearDown();
+        assertNull(SlowQueryReport.getPoolStats(pool.getName()));
+    }   
+    
+    
+    public class ClientListener implements NotificationListener {
+        volatile int notificationCount = 0;
+        public void handleNotification(Notification notification,
+                                       Object handback) {
+            notificationCount++;
+            System.out.println("\nReceived notification:");
+            System.out.println("\tClassName: " + notification.getClass().getName());
+            System.out.println("\tSource: " + notification.getSource());
+            System.out.println("\tType: " + notification.getType());
+            System.out.println("\tMessage: " + notification.getMessage());
+            if (notification instanceof AttributeChangeNotification) {
+                AttributeChangeNotification acn =
+                    (AttributeChangeNotification) notification;
+                System.out.println("\tAttributeName: " + acn.getAttributeName());
+                System.out.println("\tAttributeType: " + acn.getAttributeType());
+                System.out.println("\tNewValue: " + acn.getNewValue());
+                System.out.println("\tOldValue: " + acn.getOldValue());
+            }
+        }
+    }
+
+
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestStatementCache.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestStatementCache.java
new file mode 100644 (file)
index 0000000..d3d5740
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * 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;
+        }
+    }
+
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestSuspectTimeout.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestSuspectTimeout.java
new file mode 100644 (file)
index 0000000..b4b18d9
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ *  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 org.apache.tomcat.jdbc.pool.PooledConnection;
+
+
+public class TestSuspectTimeout extends DefaultTestCase {
+
+    public TestSuspectTimeout(String name) {
+        super(name);
+    }
+    
+    public void testSuspect() throws Exception {
+        this.init();
+        this.datasource.setMaxActive(100);
+        this.datasource.setMaxIdle(100);
+        this.datasource.setInitialSize(0);
+        this.datasource.getPoolProperties().setAbandonWhenPercentageFull(0);
+        this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(100);
+        this.datasource.getPoolProperties().setRemoveAbandoned(true);
+        this.datasource.getPoolProperties().setRemoveAbandonedTimeout(100);
+        this.datasource.getPoolProperties().setSuspectTimeout(1);
+        this.datasource.getPoolProperties().setLogAbandoned(true);
+        Connection con = datasource.getConnection();
+        assertEquals("Number of connections active/busy should be 1",1,datasource.getPool().getActive());
+        Thread.sleep(3000);
+        PooledConnection pcon = con.unwrap(PooledConnection.class);
+        assertTrue("Connection should be marked suspect",pcon.isSuspect());
+        con.close();
+    }
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestTimeout.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TestTimeout.java
new file mode 100644 (file)
index 0000000..6697e9a
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * 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.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @author Filip Hanik
+ * @version 1.0
+ */
+public class TestTimeout extends DefaultTestCase {
+    public TestTimeout(String name) {
+        super(name);
+    }
+
+    AtomicInteger counter = new AtomicInteger(0);
+
+    public void testCheckoutTimeout() throws Exception {
+        try {
+            init();
+            this.datasource.getPoolProperties().setTestWhileIdle(true);
+            this.datasource.getPoolProperties().setTestOnBorrow(false);
+            this.datasource.getPoolProperties().setTestOnReturn(false);
+            this.datasource.getPoolProperties().setValidationInterval(30000);
+            this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(1000);
+            this.datasource.getPoolProperties().setMaxActive(20);
+            this.datasource.getPoolProperties().setMaxWait(3000);
+            this.datasource.getPoolProperties().setRemoveAbandonedTimeout(5);
+            this.datasource.getPoolProperties().setMinEvictableIdleTimeMillis(5000);
+            this.datasource.getPoolProperties().setMinIdle(5);
+            this.datasource.getPoolProperties().setLogAbandoned(true);
+            System.out.println("About to test connection pool:"+datasource);
+            for (int i = 0; i < 21; i++) {
+                long now = System.currentTimeMillis();
+                this.datasource.getConnection();
+                long delta = System.currentTimeMillis()-now;
+                System.out.println("Got connection #"+i+" in "+delta+" ms.");
+            }
+            assertTrue(false);
+        } catch ( Exception x ) {
+            assertTrue(true);
+        }finally {
+            Thread.sleep(2000);
+            tearDown();
+        }
+    }
+
+    public void testCheckoutTimeoutFair() throws Exception {
+        try {
+            init();
+            this.datasource.getPoolProperties().setFairQueue(true);
+            this.datasource.getPoolProperties().setTestWhileIdle(true);
+            this.datasource.getPoolProperties().setTestOnBorrow(false);
+            this.datasource.getPoolProperties().setTestOnReturn(false);
+            this.datasource.getPoolProperties().setValidationInterval(30000);
+            this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(1000);
+            this.datasource.getPoolProperties().setMaxActive(20);
+            this.datasource.getPoolProperties().setMaxWait(3000);
+            this.datasource.getPoolProperties().setRemoveAbandonedTimeout(5);
+            this.datasource.getPoolProperties().setMinEvictableIdleTimeMillis(5000);
+            this.datasource.getPoolProperties().setMinIdle(5);
+            this.datasource.getPoolProperties().setLogAbandoned(true);
+            System.out.println("About to test connection pool:"+datasource);
+            for (int i = 0; i < 21; i++) {
+                long now = System.currentTimeMillis();
+                this.datasource.getConnection();
+                long delta = System.currentTimeMillis()-now;
+                System.out.println("Got connection #"+i+" in "+delta+" ms.");
+            }
+            assertTrue(false);
+        } catch ( Exception x ) {
+            assertTrue(true);
+        }finally {
+            Thread.sleep(2000);
+            tearDown();
+        }
+    }
+
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TwoDataSources.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/TwoDataSources.java
new file mode 100644 (file)
index 0000000..2a500e7
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ *  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;
+
+public class TwoDataSources extends DefaultTestCase {
+
+    public TwoDataSources(String name) {
+        super(name);
+    }
+    
+    public void testTwoDataSources() throws Exception {
+        org.apache.tomcat.jdbc.pool.DataSource d1 = this.createDefaultDataSource();
+        org.apache.tomcat.jdbc.pool.DataSource d2 = this.createDefaultDataSource();
+        d1.setRemoveAbandoned(true);
+        d1.setRemoveAbandonedTimeout(10);
+        d1.setTimeBetweenEvictionRunsMillis(1000);
+        d2.setRemoveAbandoned(false);
+        Connection c1 = d1.getConnection();
+        Connection c2 = d2.getConnection();
+        Thread.sleep(5000);
+        try {
+            c1.createStatement();
+            assertTrue("Connection should have been abandoned.",false);
+        }catch (Exception x) {
+            assertTrue("This is correct, c1 is abandoned",true);
+        }
+
+        try {
+            c2.createStatement();
+            assertTrue("Connection should not have been abandoned.",true);
+        }catch (Exception x) {
+            assertTrue("Connection c2 should be working",false);
+        }
+        try {
+            assertTrue("Connection should have been closed.",c1.isClosed());
+        }catch (Exception x) {
+            assertTrue("This is correct, c1 is closed",true);
+        }
+        try {
+            assertFalse("Connection c2 should not have been closed.",c2.isClosed());
+        }catch (Exception x) {
+            assertTrue("Connection c2 should be working",false);
+        }
+
+
+    }
+
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/driver/Connection.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/driver/Connection.java
new file mode 100644 (file)
index 0000000..8fc3888
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ *  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.driver;
+
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.CallableStatement;
+import java.sql.Clob;
+import java.sql.DatabaseMetaData;
+import java.sql.NClob;
+import java.sql.PreparedStatement;
+import java.sql.SQLClientInfoException;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Savepoint;
+import java.sql.Statement;
+import java.sql.Struct;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.tomcat.jdbc.pool.PooledConnection;
+
+public class Connection implements java.sql.Connection {
+    Properties info;
+    
+    public Connection(Properties info) {
+        this.info = info;
+    }
+    
+    public String getUsername() {
+        return info.getProperty(PooledConnection.PROP_USER);
+    }
+    
+    public String getPassword() {
+        return info.getProperty(PooledConnection.PROP_PASSWORD);
+    }
+    
+    public void clearWarnings() throws SQLException {
+    }
+
+    public void close() throws SQLException {
+        Driver.disconnectCount.incrementAndGet();
+    }
+
+    public void commit() throws SQLException {
+    }
+
+    public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
+        return null;
+    }
+
+    public Blob createBlob() throws SQLException {
+        return null;
+    }
+
+    public Clob createClob() throws SQLException {
+        return null;
+    }
+
+    public NClob createNClob() throws SQLException {
+        return null;
+    }
+
+    public SQLXML createSQLXML() throws SQLException {
+        return null;
+    }
+
+    public Statement createStatement() throws SQLException {
+        return new org.apache.tomcat.jdbc.test.driver.Statement();
+    }
+
+    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
+        return new org.apache.tomcat.jdbc.test.driver.Statement();
+    }
+
+    public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+        return new org.apache.tomcat.jdbc.test.driver.Statement();
+    }
+
+    public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
+        return null;
+    }
+
+    public boolean getAutoCommit() throws SQLException {
+        return false;
+    }
+
+    public String getCatalog() throws SQLException {
+        return null;
+    }
+
+    public Properties getClientInfo() throws SQLException {
+        return null;
+    }
+
+    public String getClientInfo(String name) throws SQLException {
+        return null;
+    }
+
+    public int getHoldability() throws SQLException {
+        return 0;
+    }
+
+    public DatabaseMetaData getMetaData() throws SQLException {
+        return null;
+    }
+
+    public int getTransactionIsolation() throws SQLException {
+        return 0;
+    }
+
+    public Map<String, Class<?>> getTypeMap() throws SQLException {
+        return null;
+    }
+
+    public SQLWarning getWarnings() throws SQLException {
+        return null;
+    }
+
+    public boolean isClosed() throws SQLException {
+        return false;
+    }
+
+    public boolean isReadOnly() throws SQLException {
+        return false;
+    }
+
+    public boolean isValid(int timeout) throws SQLException {
+        return false;
+    }
+
+    public String nativeSQL(String sql) throws SQLException {
+        return null;
+    }
+
+    public CallableStatement prepareCall(String sql) throws SQLException {
+        return new org.apache.tomcat.jdbc.test.driver.Statement();
+    }
+
+    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
+        return new org.apache.tomcat.jdbc.test.driver.Statement();
+    }
+
+    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+        return new org.apache.tomcat.jdbc.test.driver.Statement();
+    }
+
+    public PreparedStatement prepareStatement(String sql) throws SQLException {
+        return new org.apache.tomcat.jdbc.test.driver.Statement();
+    }
+
+    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
+        return new org.apache.tomcat.jdbc.test.driver.Statement();
+    }
+
+    
+    public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
+        return new org.apache.tomcat.jdbc.test.driver.Statement();
+    }
+
+    public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
+        return new org.apache.tomcat.jdbc.test.driver.Statement();
+    }
+
+    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
+        return new org.apache.tomcat.jdbc.test.driver.Statement();
+    }
+
+    
+    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+        return new org.apache.tomcat.jdbc.test.driver.Statement();
+    }
+
+    public void releaseSavepoint(Savepoint savepoint) throws SQLException {
+    }
+
+    public void rollback() throws SQLException {
+    }
+
+    public void rollback(Savepoint savepoint) throws SQLException {
+    }
+
+    public void setAutoCommit(boolean autoCommit) throws SQLException {
+    }
+
+    public void setCatalog(String catalog) throws SQLException {
+    }
+
+    public void setClientInfo(Properties properties) throws SQLClientInfoException {
+    }
+
+    public void setClientInfo(String name, String value) throws SQLClientInfoException {
+    }
+
+    public void setHoldability(int holdability) throws SQLException {
+    }
+
+    public void setReadOnly(boolean readOnly) throws SQLException {
+    }
+
+    public Savepoint setSavepoint() throws SQLException {
+        return null;
+    }
+
+    public Savepoint setSavepoint(String name) throws SQLException {
+        return null;
+    }
+
+    public void setTransactionIsolation(int level) throws SQLException {
+    }
+
+    public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
+    }
+
+    public boolean isWrapperFor(Class<?> iface) throws SQLException {
+        return false;
+    }
+
+    public <T> T unwrap(Class<T> iface) throws SQLException {
+        return null;
+    }
+
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/driver/Driver.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/driver/Driver.java
new file mode 100644 (file)
index 0000000..0b3d8cd
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ *  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.driver;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.DriverPropertyInfo;
+import java.sql.SQLException;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class Driver implements java.sql.Driver {
+    public static final String url = "jdbc:tomcat:test";
+    public static final AtomicInteger connectCount = new AtomicInteger(0);
+    public static final AtomicInteger disconnectCount = new AtomicInteger(0);
+
+    public static void reset() {
+        connectCount.set(0);
+        disconnectCount.set(0);
+    }
+    
+    static {
+        try {
+            DriverManager.registerDriver(new Driver());
+        }catch (Exception x) {
+            x.printStackTrace();
+            throw new RuntimeException(x);
+        }
+    }
+    
+    public Driver() {
+    }
+    
+    public boolean acceptsURL(String url) throws SQLException {
+        return url!=null && url.equals(Driver.url);
+    }
+
+    public Connection connect(String url, Properties info) throws SQLException {
+        connectCount.addAndGet(1);
+        return new org.apache.tomcat.jdbc.test.driver.Connection(info);
+    }
+
+    public int getMajorVersion() {
+        return 0;
+    }
+
+    public int getMinorVersion() {
+        return 0;
+    }
+
+    public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
+        return null;
+    }
+
+    public boolean jdbcCompliant() {
+        return false;
+    }
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/driver/ResultSet.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/driver/ResultSet.java
new file mode 100644 (file)
index 0000000..9986c48
--- /dev/null
@@ -0,0 +1,1200 @@
+/*
+ *  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.driver;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+import java.sql.NClob;
+import java.sql.Ref;
+import java.sql.ResultSetMetaData;
+import java.sql.RowId;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Statement;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.Map;
+
+public class ResultSet implements java.sql.ResultSet {
+    boolean hasNext = true;
+    
+    public boolean absolute(int row) throws SQLException {
+        return false;
+    }
+
+    public void afterLast() throws SQLException {
+    }
+
+    public void beforeFirst() throws SQLException {
+    }
+
+    public void cancelRowUpdates() throws SQLException {
+    }
+
+    public void clearWarnings() throws SQLException {
+    }
+    public void close() throws SQLException {
+    }
+
+    public void deleteRow() throws SQLException {
+    }
+
+    public int findColumn(String columnLabel) throws SQLException {
+        return 0;
+    }
+
+    public boolean first() throws SQLException {
+        return hasNext;
+    }
+
+    public Array getArray(int columnIndex) throws SQLException {
+        return null;
+    }
+
+    public Array getArray(String columnLabel) throws SQLException {
+        return null;
+    }
+
+    @Override
+    public InputStream getAsciiStream(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public InputStream getAsciiStream(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public BigDecimal getBigDecimal(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public BigDecimal getBigDecimal(int columnIndex, int scale)
+            throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public BigDecimal getBigDecimal(String columnLabel, int scale)
+            throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public InputStream getBinaryStream(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public InputStream getBinaryStream(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Blob getBlob(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Blob getBlob(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public boolean getBoolean(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean getBoolean(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public byte getByte(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public byte getByte(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public byte[] getBytes(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public byte[] getBytes(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Reader getCharacterStream(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Reader getCharacterStream(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Clob getClob(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Clob getClob(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public int getConcurrency() throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public String getCursorName() throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Date getDate(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Date getDate(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Date getDate(int columnIndex, Calendar cal) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Date getDate(String columnLabel, Calendar cal) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public double getDouble(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public double getDouble(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public int getFetchDirection() throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public int getFetchSize() throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public float getFloat(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public float getFloat(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public int getHoldability() throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public int getInt(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public int getInt(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public long getLong(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public long getLong(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public ResultSetMetaData getMetaData() throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Reader getNCharacterStream(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Reader getNCharacterStream(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public NClob getNClob(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public NClob getNClob(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public String getNString(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public String getNString(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Object getObject(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Object getObject(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Object getObject(int columnIndex, Map<String, Class<?>> map)
+            throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Object getObject(String columnLabel, Map<String, Class<?>> map)
+            throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Ref getRef(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Ref getRef(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public int getRow() throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public RowId getRowId(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public RowId getRowId(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public SQLXML getSQLXML(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public SQLXML getSQLXML(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public short getShort(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public short getShort(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public Statement getStatement() throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public String getString(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public String getString(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Time getTime(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Time getTime(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Time getTime(int columnIndex, Calendar cal) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Time getTime(String columnLabel, Calendar cal) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Timestamp getTimestamp(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Timestamp getTimestamp(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Timestamp getTimestamp(int columnIndex, Calendar cal)
+            throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Timestamp getTimestamp(String columnLabel, Calendar cal)
+            throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public int getType() throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public URL getURL(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public URL getURL(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public InputStream getUnicodeStream(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public InputStream getUnicodeStream(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public SQLWarning getWarnings() throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void insertRow() throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public boolean isAfterLast() throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean isBeforeFirst() throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean isClosed() throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean isFirst() throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean isLast() throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean last() throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public void moveToCurrentRow() throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void moveToInsertRow() throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public boolean next() throws SQLException {
+        boolean next = hasNext;
+        hasNext = false;
+        // TODO Auto-generated method stub
+        return next;
+    }
+
+    @Override
+    public boolean previous() throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public void refreshRow() throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public boolean relative(int rows) throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean rowDeleted() throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean rowInserted() throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean rowUpdated() throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public void setFetchDirection(int direction) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setFetchSize(int rows) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateArray(int columnIndex, Array x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateArray(String columnLabel, Array x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateAsciiStream(int columnIndex, InputStream x)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateAsciiStream(String columnLabel, InputStream x)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateAsciiStream(int columnIndex, InputStream x, int length)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateAsciiStream(String columnLabel, InputStream x, int length)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateAsciiStream(int columnIndex, InputStream x, long length)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateAsciiStream(String columnLabel, InputStream x, long length)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateBigDecimal(int columnIndex, BigDecimal x)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateBigDecimal(String columnLabel, BigDecimal x)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateBinaryStream(int columnIndex, InputStream x)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateBinaryStream(String columnLabel, InputStream x)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateBinaryStream(int columnIndex, InputStream x, int length)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateBinaryStream(String columnLabel, InputStream x, int length)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateBinaryStream(int columnIndex, InputStream x, long length)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateBinaryStream(String columnLabel, InputStream x,
+            long length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateBlob(int columnIndex, Blob x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateBlob(String columnLabel, Blob x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateBlob(int columnIndex, InputStream inputStream)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateBlob(String columnLabel, InputStream inputStream)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateBlob(int columnIndex, InputStream inputStream, long length)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateBlob(String columnLabel, InputStream inputStream,
+            long length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateBoolean(int columnIndex, boolean x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateBoolean(String columnLabel, boolean x)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateByte(int columnIndex, byte x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateByte(String columnLabel, byte x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateBytes(int columnIndex, byte[] x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateBytes(String columnLabel, byte[] x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateCharacterStream(int columnIndex, Reader x)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateCharacterStream(String columnLabel, Reader reader)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateCharacterStream(int columnIndex, Reader x, int length)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateCharacterStream(String columnLabel, Reader reader,
+            int length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateCharacterStream(int columnIndex, Reader x, long length)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateCharacterStream(String columnLabel, Reader reader,
+            long length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateClob(int columnIndex, Clob x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateClob(String columnLabel, Clob x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateClob(int columnIndex, Reader reader) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateClob(String columnLabel, Reader reader)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateClob(int columnIndex, Reader reader, long length)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateClob(String columnLabel, Reader reader, long length)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateDate(int columnIndex, Date x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateDate(String columnLabel, Date x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateDouble(int columnIndex, double x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateDouble(String columnLabel, double x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateFloat(int columnIndex, float x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateFloat(String columnLabel, float x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateInt(int columnIndex, int x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateInt(String columnLabel, int x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateLong(int columnIndex, long x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateLong(String columnLabel, long x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateNCharacterStream(int columnIndex, Reader x)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateNCharacterStream(String columnLabel, Reader reader)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateNCharacterStream(int columnIndex, Reader x, long length)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateNCharacterStream(String columnLabel, Reader reader,
+            long length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateNClob(int columnIndex, NClob clob) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateNClob(String columnLabel, NClob clob) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateNClob(int columnIndex, Reader reader) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateNClob(String columnLabel, Reader reader)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateNClob(int columnIndex, Reader reader, long length)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateNClob(String columnLabel, Reader reader, long length)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateNString(int columnIndex, String string)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateNString(String columnLabel, String string)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateNull(int columnIndex) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateNull(String columnLabel) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateObject(int columnIndex, Object x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateObject(String columnLabel, Object x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateObject(int columnIndex, Object x, int scaleOrLength)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateObject(String columnLabel, Object x, int scaleOrLength)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateRef(int columnIndex, Ref x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateRef(String columnLabel, Ref x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateRow() throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateRowId(int columnIndex, RowId x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateRowId(String columnLabel, RowId x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateSQLXML(int columnIndex, SQLXML xmlObject)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateSQLXML(String columnLabel, SQLXML xmlObject)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateShort(int columnIndex, short x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateShort(String columnLabel, short x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateString(int columnIndex, String x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateString(String columnLabel, String x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateTime(int columnIndex, Time x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateTime(String columnLabel, Time x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateTimestamp(int columnIndex, Timestamp x)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void updateTimestamp(String columnLabel, Timestamp x)
+            throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public boolean wasNull() throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean isWrapperFor(Class<?> iface) throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public <T> T unwrap(Class<T> iface) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+}
diff --git a/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/driver/Statement.java b/modules/jdbc-pool/src/test/java/org/apache/tomcat/jdbc/test/driver/Statement.java
new file mode 100644 (file)
index 0000000..d7d5f9e
--- /dev/null
@@ -0,0 +1,1293 @@
+/*
+ *  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.driver;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.CallableStatement;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.NClob;
+import java.sql.ParameterMetaData;
+import java.sql.Ref;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.RowId;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.Map;
+
+public class Statement implements CallableStatement {
+
+    @Override
+    public Array getArray(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Array getArray(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public BigDecimal getBigDecimal(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public BigDecimal getBigDecimal(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public BigDecimal getBigDecimal(int parameterIndex, int scale) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Blob getBlob(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Blob getBlob(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public boolean getBoolean(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean getBoolean(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public byte getByte(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public byte getByte(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public byte[] getBytes(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public byte[] getBytes(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Reader getCharacterStream(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Reader getCharacterStream(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Clob getClob(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Clob getClob(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Date getDate(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Date getDate(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Date getDate(int parameterIndex, Calendar cal) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Date getDate(String parameterName, Calendar cal) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public double getDouble(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public double getDouble(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public float getFloat(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public float getFloat(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public int getInt(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public int getInt(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public long getLong(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public long getLong(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public Reader getNCharacterStream(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Reader getNCharacterStream(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public NClob getNClob(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public NClob getNClob(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public String getNString(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public String getNString(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Object getObject(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Object getObject(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Object getObject(int parameterIndex, Map<String, Class<?>> map) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Object getObject(String parameterName, Map<String, Class<?>> map) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Ref getRef(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Ref getRef(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public RowId getRowId(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public RowId getRowId(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public SQLXML getSQLXML(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public SQLXML getSQLXML(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public short getShort(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public short getShort(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public String getString(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public String getString(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Time getTime(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Time getTime(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Time getTime(int parameterIndex, Calendar cal) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Time getTime(String parameterName, Calendar cal) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Timestamp getTimestamp(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Timestamp getTimestamp(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Timestamp getTimestamp(int parameterIndex, Calendar cal) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Timestamp getTimestamp(String parameterName, Calendar cal) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public URL getURL(int parameterIndex) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public URL getURL(String parameterName) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void registerOutParameter(String parameterName, int sqlType) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void registerOutParameter(int parameterIndex, int sqlType, int scale) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void registerOutParameter(int parameterIndex, int sqlType, String typeName) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void registerOutParameter(String parameterName, int sqlType, int scale) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void registerOutParameter(String parameterName, int sqlType, String typeName) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setAsciiStream(String parameterName, InputStream x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setAsciiStream(String parameterName, InputStream x, int length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setAsciiStream(String parameterName, InputStream x, long length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setBinaryStream(String parameterName, InputStream x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setBinaryStream(String parameterName, InputStream x, int length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setBinaryStream(String parameterName, InputStream x, long length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setBlob(String parameterName, Blob x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setBlob(String parameterName, InputStream inputStream) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setBlob(String parameterName, InputStream inputStream, long length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setBoolean(String parameterName, boolean x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setByte(String parameterName, byte x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setBytes(String parameterName, byte[] x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setCharacterStream(String parameterName, Reader reader) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setCharacterStream(String parameterName, Reader reader, int length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setCharacterStream(String parameterName, Reader reader, long length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setClob(String parameterName, Clob x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setClob(String parameterName, Reader reader) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setClob(String parameterName, Reader reader, long length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setDate(String parameterName, Date x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setDate(String parameterName, Date x, Calendar cal) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setDouble(String parameterName, double x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setFloat(String parameterName, float x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setInt(String parameterName, int x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setLong(String parameterName, long x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setNCharacterStream(String parameterName, Reader value) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setNCharacterStream(String parameterName, Reader value, long length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setNClob(String parameterName, NClob value) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setNClob(String parameterName, Reader reader) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setNClob(String parameterName, Reader reader, long length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setNString(String parameterName, String value) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setNull(String parameterName, int sqlType) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setNull(String parameterName, int sqlType, String typeName) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setObject(String parameterName, Object x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setObject(String parameterName, Object x, int targetSqlType) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setObject(String parameterName, Object x, int targetSqlType, int scale) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setRowId(String parameterName, RowId x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setShort(String parameterName, short x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setString(String parameterName, String x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setTime(String parameterName, Time x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setTime(String parameterName, Time x, Calendar cal) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setTimestamp(String parameterName, Timestamp x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setTimestamp(String parameterName, Timestamp x, Calendar cal) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setURL(String parameterName, URL val) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public boolean wasNull() throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public void addBatch() throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void clearParameters() throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public boolean execute() throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public ResultSet executeQuery() throws SQLException {
+        // TODO Auto-generated method stub
+        return new org.apache.tomcat.jdbc.test.driver.ResultSet();
+    }
+
+    @Override
+    public int executeUpdate() throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public ResultSetMetaData getMetaData() throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public ParameterMetaData getParameterMetaData() throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void setArray(int parameterIndex, Array x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setBlob(int parameterIndex, Blob x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setBoolean(int parameterIndex, boolean x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setByte(int parameterIndex, byte x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setBytes(int parameterIndex, byte[] x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setClob(int parameterIndex, Clob x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setClob(int parameterIndex, Reader reader) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setClob(int parameterIndex, Reader reader, long length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setDate(int parameterIndex, Date x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setDouble(int parameterIndex, double x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setFloat(int parameterIndex, float x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setInt(int parameterIndex, int x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setLong(int parameterIndex, long x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setNClob(int parameterIndex, NClob value) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setNClob(int parameterIndex, Reader reader) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setNString(int parameterIndex, String value) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setNull(int parameterIndex, int sqlType) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setObject(int parameterIndex, Object x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setRef(int parameterIndex, Ref x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setRowId(int parameterIndex, RowId x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setShort(int parameterIndex, short x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setString(int parameterIndex, String x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setTime(int parameterIndex, Time x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setURL(int parameterIndex, URL x) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void addBatch(String sql) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void cancel() throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void clearBatch() throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void clearWarnings() throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void close() throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public boolean execute(String sql) throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean execute(String sql, int[] columnIndexes) throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean execute(String sql, String[] columnNames) throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public int[] executeBatch() throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public ResultSet executeQuery(String sql) throws SQLException {
+        // TODO Auto-generated method stub
+        return new org.apache.tomcat.jdbc.test.driver.ResultSet();
+    }
+
+    @Override
+    public int executeUpdate(String sql) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public int executeUpdate(String sql, int[] columnIndexes) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public int executeUpdate(String sql, String[] columnNames) throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public Connection getConnection() throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public int getFetchDirection() throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public int getFetchSize() throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public ResultSet getGeneratedKeys() throws SQLException {
+        // TODO Auto-generated method stub
+        return new org.apache.tomcat.jdbc.test.driver.ResultSet();
+    }
+
+    @Override
+    public int getMaxFieldSize() throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public int getMaxRows() throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public boolean getMoreResults() throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean getMoreResults(int current) throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public int getQueryTimeout() throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public ResultSet getResultSet() throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public int getResultSetConcurrency() throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public int getResultSetHoldability() throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public int getResultSetType() throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public int getUpdateCount() throws SQLException {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public SQLWarning getWarnings() throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public boolean isClosed() throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean isPoolable() throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public void setCursorName(String name) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setEscapeProcessing(boolean enable) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setFetchDirection(int direction) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setFetchSize(int rows) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setMaxFieldSize(int max) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setMaxRows(int max) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setPoolable(boolean poolable) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public void setQueryTimeout(int seconds) throws SQLException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public boolean isWrapperFor(Class<?> iface) throws SQLException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public <T> T unwrap(Class<T> iface) throws SQLException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/pool/interceptor/TestInterceptor.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/pool/interceptor/TestInterceptor.java
deleted file mode 100644 (file)
index 739347c..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- *  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.pool.interceptor;
-
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.apache.tomcat.jdbc.pool.ConnectionPool;
-import org.apache.tomcat.jdbc.pool.JdbcInterceptor;
-import org.apache.tomcat.jdbc.pool.PooledConnection;
-import org.apache.tomcat.jdbc.pool.PoolProperties.InterceptorProperty;
-
-public class TestInterceptor extends JdbcInterceptor {
-    public static boolean poolstarted = false;
-    public static boolean poolclosed = false;
-    public static AtomicInteger instancecount = new AtomicInteger(0);
-
-    @Override
-    public void poolClosed(ConnectionPool pool) {
-        // TODO Auto-generated method stub
-        super.poolClosed(pool);
-        poolclosed = true;
-    }
-
-    @Override
-    public void poolStarted(ConnectionPool pool) {
-        super.poolStarted(pool);
-        poolstarted = true;
-    }
-
-    @Override
-    public void reset(ConnectionPool parent, PooledConnection con) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    @Override
-    public void setProperties(Map<String, InterceptorProperty> properties) {
-        instancecount.incrementAndGet();
-        super.setProperties(properties);
-    }
-
-
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/AbandonPercentageTest.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/AbandonPercentageTest.java
deleted file mode 100644 (file)
index a86e6e9..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- *  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 org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer;
-
-public class AbandonPercentageTest extends DefaultTestCase {
-
-    public AbandonPercentageTest(String name) {
-        super(name);
-    }
-    
-    public void testDefaultAbandon() throws Exception {
-        this.init();
-        this.datasource.setMaxActive(100);
-        this.datasource.setMaxIdle(100);
-        this.datasource.setInitialSize(0);
-        this.datasource.getPoolProperties().setAbandonWhenPercentageFull(0);
-        this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(100);
-        this.datasource.getPoolProperties().setRemoveAbandoned(true);
-        this.datasource.getPoolProperties().setRemoveAbandonedTimeout(1);
-        Connection con = datasource.getConnection();
-        assertEquals("Number of connections active/busy should be 1",1,datasource.getPool().getActive());
-        Thread.sleep(2000);
-        assertEquals("Number of connections active/busy should be 0",0,datasource.getPool().getActive());
-        con.close();
-    }
-    
-    public void testMaxedOutAbandon() throws Exception {
-        int size = 100;
-        this.init();
-        this.datasource.setMaxActive(size);
-        this.datasource.setMaxIdle(size);
-        this.datasource.setInitialSize(0);
-        this.datasource.getPoolProperties().setAbandonWhenPercentageFull(100);
-        this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(100);
-        this.datasource.getPoolProperties().setRemoveAbandoned(true);
-        this.datasource.getPoolProperties().setRemoveAbandonedTimeout(1);
-        Connection con = datasource.getConnection();
-        assertEquals("Number of connections active/busy should be 1",1,datasource.getPool().getActive());
-        Thread.sleep(2000);
-        assertEquals("Number of connections active/busy should be 1",1,datasource.getPool().getActive());
-        con.close();
-    }
-
-    public void testResetConnection() throws Exception {
-        int size = 1;
-        this.init();
-        this.datasource.setMaxActive(size);
-        this.datasource.setMaxIdle(size);
-        this.datasource.setInitialSize(0);
-        this.datasource.getPoolProperties().setAbandonWhenPercentageFull(100);
-        this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(100);
-        this.datasource.getPoolProperties().setRemoveAbandoned(true);
-        this.datasource.getPoolProperties().setRemoveAbandonedTimeout(1);
-        this.datasource.getPoolProperties().setJdbcInterceptors(ResetAbandonedTimer.class.getName());
-        Connection con = datasource.getConnection();
-        assertEquals("Number of connections active/busy should be 1",1,datasource.getPool().getActive());
-        for (int i=0; i<20; i++) {
-            Thread.sleep(200);
-            con.isClosed();
-        }
-        assertEquals("Number of connections active/busy should be 1",1,datasource.getPool().getActive());
-        con.close();
-    }
-
-    public void testHalfway() throws Exception {
-        int size = 100;
-        this.init();
-        this.datasource.setMaxActive(size);
-        this.datasource.setMaxIdle(size);
-        this.datasource.setInitialSize(0);
-        this.datasource.getPoolProperties().setAbandonWhenPercentageFull(50);
-        this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(500);
-        this.datasource.getPoolProperties().setRemoveAbandoned(true);
-        this.datasource.getPoolProperties().setRemoveAbandonedTimeout(1);
-        Connection[] con = new Connection[size];
-        con[0] = datasource.getConnection();
-        assertEquals("Number of connections active/busy should be 1",1,datasource.getPool().getActive());
-        for (int i=1; i<25; i++) {
-            con[i] = datasource.getConnection();
-        }
-        assertEquals("Number of connections active/busy should be 25",25,datasource.getPool().getActive());
-        Thread.sleep(2500);
-        assertEquals("Number of connections active/busy should be 25",25,datasource.getPool().getActive());
-        this.datasource.getPoolProperties().setRemoveAbandonedTimeout(100);
-        for (int i=25; i<con.length; i++) {
-            con[i] = datasource.getConnection();
-        }
-        int active = datasource.getPool().getActive();
-        System.out.println("Active:"+active);
-        assertEquals("Number of connections active/busy should be "+con.length,con.length,datasource.getPool().getActive());
-        this.datasource.getPoolProperties().setRemoveAbandonedTimeout(1);
-        Thread.sleep(2500);
-        this.assertTrue("Number of connections should be less than 50.", (datasource.getPool().getActive()<50));
-        this.datasource.getPoolProperties().setAbandonWhenPercentageFull(0);
-        Thread.sleep(2500);
-        assertEquals("Number of connections active/busy should be "+0,0,datasource.getPool().getActive());
-    }
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/AlternateUsernameTest.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/AlternateUsernameTest.java
deleted file mode 100644 (file)
index 0ea3e2a..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- *  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.SQLException;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Random;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-
-import javax.sql.PooledConnection;
-
-import org.apache.tomcat.jdbc.test.driver.Connection;
-import org.apache.tomcat.jdbc.test.driver.Driver;
-
-
-public class AlternateUsernameTest extends DefaultTestCase {
-
-    private static final int iterations = 500000; //(new Random(System.currentTimeMillis())).nextInt(1000000)+100000;
-    public AlternateUsernameTest(String name) {
-        super(name);
-    }
-    public void testUsernameCompare() throws Exception {
-        testUsername(true);
-    }
-    
-    private void testUsername(boolean allowUsernameChange) throws Exception {
-        long start = System.currentTimeMillis();
-        int withoutuser =10;
-        int withuser = withoutuser;
-        this.init();
-        this.datasource.setMaxActive(withuser+withoutuser);
-        this.datasource.setDriverClassName(Driver.class.getName());
-        this.datasource.setUrl("jdbc:tomcat:test");
-        this.datasource.setAlternateUsernameAllowed(allowUsernameChange);
-        this.datasource.getConnection().close();
-        
-        TestRunner[] runners = new TestRunner[withuser+withoutuser];
-        for (int i=0; i<withuser; i++) {
-            TestRunner with = new TestRunner("foo","bar",datasource.getPoolProperties().getUsername(),datasource.getPoolProperties().getPassword());
-            TestRunner without = new TestRunner(null,null,datasource.getPoolProperties().getUsername(),datasource.getPoolProperties().getPassword());
-            runners[i] = allowUsernameChange?with:without;
-            runners[i+withuser] = without;
-        }
-        ExecutorService svc = Executors.newFixedThreadPool(withuser+withoutuser);
-        List<Future<TestResult>> results =  svc.invokeAll(Arrays.asList(runners));
-        int failures = 0;
-        int total = 0;
-        for (int i=0; i<withuser; i++) {
-            failures += results.get(i).get().failures;
-            total+=results.get(i).get().iterations;
-            failures += results.get(i+withuser).get().failures;
-            total+=results.get(i+withuser).get().iterations;
-        }
-        long stop = System.currentTimeMillis();
-        assertEquals("Nr of failures was:"+failures,0, failures);
-        svc.shutdownNow();
-        this.datasource.close();
-        System.out.println("Nr of connect() calls:"+Driver.connectCount.get());
-        System.out.println("Nr of disconnect() calls:"+Driver.disconnectCount.get());
-        System.out.println("Nr of iterations:"+total+" over "+(stop-start)+ " ms.");
-
-    }
-    
-    public void testUsernameCompareAgain() throws Exception {
-        testUsernameCompare();
-    }
-    
-    public void testUsernameCompareNotAllowed() throws Exception {
-        testUsername(false);
-    }
-    
-    public static class TestResult {
-        public int iterations;
-        public int failures;
-        public String lastMessage;
-    }
-    
-    public class TestRunner implements Callable<TestResult> {
-        String username;
-        String password;
-        volatile boolean done = false;
-        TestResult result = null;
-        boolean useuser = true;
-        
-        public TestRunner(String user, String pass, String guser, String gpass) {
-            username = user==null?guser : user;
-            password = pass==null?gpass : pass;
-            useuser = user!=null;
-        }
-        
-        public TestResult call() {
-            TestResult test = new TestResult();
-            PooledConnection pcon = null;
-            for (int i=0; (!done) && (i<iterations); i++) {
-                test.iterations = i+1;
-                try {
-                    
-                    
-                    pcon = useuser ? (PooledConnection)AlternateUsernameTest.this.datasource.getConnection(username, password) :
-                                     (PooledConnection)AlternateUsernameTest.this.datasource.getConnection();
-                    
-                    Connection con = (Connection)pcon.getConnection();
-                    
-                    assertTrue("Username mismatch: Requested User:"+username+" Actual user:"+con.getUsername(), con.getUsername().equals(username));
-                    assertTrue("Password mismatch: Requested Password:"+password+" Actual password:"+con.getPassword(), con.getPassword().equals(password));
-                }catch (SQLException x) {
-                    test.failures++;
-                    test.lastMessage = x.getMessage();
-                    done = true;
-                    x.printStackTrace();
-                }catch (Exception x) {
-                    test.failures++;
-                    test.lastMessage = x.getMessage();
-                    x.printStackTrace();
-                } finally {
-                    if (pcon!=null) {
-                        try {pcon.close(); }catch (Exception ignore) {}
-                        pcon = null;
-                    }
-                }
-            }
-            done = true;
-            result = test;
-            return result;
-        }
-    }
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/Async0IdleTestBug50477.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/Async0IdleTestBug50477.java
deleted file mode 100644 (file)
index cfc9210..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.tomcat.jdbc.pool.DataSourceProxy;
-
-/**
- * @author Filip Hanik
- * @version 1.0
- */
-public class Async0IdleTestBug50477 extends DefaultTestCase {
-    public Async0IdleTestBug50477(String name) {
-        super(name);
-    }
-    
-    public void testAsync0Idle0Size() throws Exception {
-        System.out.println("[testPoolThreads20Connections10FairAsync] Starting fairness - Tomcat JDBC - Fair - Async");
-        init();
-        this.datasource.getPoolProperties().setMaxActive(10);
-        this.datasource.getPoolProperties().setFairQueue(true);
-        this.datasource.getPoolProperties().setInitialSize(0);
-        try {
-            Future<Connection> cf = ((DataSourceProxy)datasource).getConnectionAsync();
-            Connection con  = cf.get(5, TimeUnit.SECONDS);
-        }finally {
-            tearDown();
-        }
-    }
-}
-
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/BorrowWaitTest.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/BorrowWaitTest.java
deleted file mode 100644 (file)
index 1244140..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- *  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.SQLException;
-
-public class BorrowWaitTest extends DefaultTestCase {
-
-    public BorrowWaitTest(String name) {
-        super(name);
-    }
-    
-    public void testWaitTime() throws Exception {
-        int wait = 10000;
-        this.init();
-        this.datasource.setMaxActive(1);
-        this.datasource.setMaxWait(wait);
-        Connection con = datasource.getConnection();
-        try {
-            Connection con2 = datasource.getConnection();
-            assertFalse("This should not happen, connection should be unavailable.",true);
-            con2.close();
-        }catch (SQLException x) {
-            long delta = System.currentTimeMillis();
-            boolean inrange = Math.abs(wait-delta) < 1000;
-            assertTrue("Connection should have been acquired within +/- 1 second.",true);
-        }
-        con.close();
-    }
-    
-    public void testWaitTimeInfinite() throws Exception {
-        if(true){
-            System.err.println("testWaitTimeInfinite() test is disabled.");
-            return;//this would lock up the test suite
-        }
-        int wait = -1;
-        this.init();
-        this.datasource.setMaxActive(1);
-        this.datasource.setMaxWait(wait);
-        Connection con = datasource.getConnection();
-        long start = System.currentTimeMillis();
-        try {
-            Connection con2 = datasource.getConnection();
-            assertFalse("This should not happen, connection should be unavailable.",true);
-        }catch (SQLException x) {
-            long delta = System.currentTimeMillis();
-            boolean inrange = Math.abs(wait-delta) < 1000;
-            assertTrue("Connection should have been acquired within +/- 1 second.",true);
-        }
-        con.close();
-    }
-
-
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/Bug50571.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/Bug50571.java
deleted file mode 100644 (file)
index 8a5650c..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*\r
- * Licensed to the Apache Software Foundation (ASF) under one or more\r
- * contributor license agreements.  See the NOTICE file distributed with\r
- * this work for additional information regarding copyright ownership.\r
- * The ASF licenses this file to You under the Apache License, Version 2.0\r
- * (the "License"); you may not use this file except in compliance with\r
- * the License.  You may obtain a copy of the License at\r
- *\r
- *      http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.apache.tomcat.jdbc.test;\r
-\r
-import org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;\r
-\r
-public class Bug50571 extends DefaultTestCase{\r
-    \r
-    public Bug50571(String name) {\r
-        super(name);\r
-    }\r
-    \r
-    @Override\r
-    public void setUp() throws Exception {\r
-        super.setUp();\r
-        this.datasource.setUrl("jdbc:h2:~/.h2/test;QUERY_TIMEOUT=0;DB_CLOSE_ON_EXIT=FALSE");\r
-        this.datasource.setJdbcInterceptors(ConnectionState.class.getName());\r
-        this.datasource.setDefaultTransactionIsolation(-55);\r
-        this.datasource.setInitialSize(1);\r
-    }\r
-    \r
-    public void testBug50571() throws Exception {\r
-        this.datasource.getConnection().close();\r
-    }\r
-}\r
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/Bug50805.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/Bug50805.java
deleted file mode 100644 (file)
index 80fc23e..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.util.concurrent.Future;
-
-public class Bug50805 extends DefaultTestCase {
-    public Bug50805(String name) {
-        super(name);
-    }
-    
-    public void test50805() throws Exception {
-        init();
-        this.datasource.setInitialSize(0);
-        this.datasource.setMaxActive(10);
-        this.datasource.setMinIdle(1);
-        
-        assertEquals("Current size should be 0.", 0, this.datasource.getSize());
-        
-        this.datasource.getConnection().close();
-        
-        assertEquals("Current size should be 1.", 1, this.datasource.getSize());
-        assertEquals("Idle size should be 1.", 1, this.datasource.getIdle());
-        assertEquals("Busy size should be 0.", 0, this.datasource.getActive());
-        
-        Future<Connection> fc = this.datasource.getConnectionAsync();
-        
-        Connection con = fc.get();
-        
-        assertEquals("Current size should be 1.", 1, this.datasource.getSize());
-        assertEquals("Idle size should be 0.", 0, this.datasource.getIdle());
-        assertEquals("Busy size should be 1.", 1, this.datasource.getActive());
-        
-        con.close();
-        assertEquals("Current size should be 1.", 1, this.datasource.getSize());
-        assertEquals("Idle size should be 1.", 1, this.datasource.getIdle());
-        assertEquals("Busy size should be 0.", 0, this.datasource.getActive());
-    }
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/CheckOutThreadTest.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/CheckOutThreadTest.java
deleted file mode 100644 (file)
index 2c5fa5e..0000000
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- * 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.util.concurrent.CountDownLatch;
-import java.sql.Connection;
-import java.sql.Statement;
-import java.sql.ResultSet;
-
-import javax.sql.DataSource;
-
-
-/**
- * @author Filip Hanik
- * @version 1.0
- */
-public class CheckOutThreadTest extends DefaultTestCase {
-    public CheckOutThreadTest(String name) {
-        super(name);
-    }
-
-    CountDownLatch latch = null;
-
-    public void testDBCPThreads10Connections10() throws Exception {
-        init();
-        this.datasource.getPoolProperties().setMaxActive(10);
-        this.threadcount = 10;
-        this.transferProperties();
-        this.tDatasource.getConnection().close();
-        latch = new CountDownLatch(threadcount);
-        long start = System.currentTimeMillis();
-        for (int i=0; i<threadcount; i++) {
-            TestThread t = new TestThread();
-            t.setName("tomcat-dbcp-"+i);
-            t.d = this.tDatasource;
-            t.start();
-        }
-        latch.await();
-        long delta = System.currentTimeMillis() - start;
-        System.out.println("[testDBCPThreads10Connections10]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
-        tearDown();
-    }
-
-    public void testPoolThreads10Connections10() throws Exception {
-        init();
-        this.datasource.getPoolProperties().setMaxActive(10);
-        this.datasource.getPoolProperties().setFairQueue(false);
-        this.threadcount = 10;
-        this.transferProperties();
-        this.datasource.getConnection().close();
-        latch = new CountDownLatch(threadcount);
-        long start = System.currentTimeMillis();
-        for (int i=0; i<threadcount; i++) {
-            TestThread t = new TestThread();
-            t.setName("tomcat-pool-"+i);
-            t.d = this.datasource;
-            t.start();
-        }
-        latch.await();
-        long delta = System.currentTimeMillis() - start;
-        System.out.println("[testPoolThreads10Connections10]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
-        tearDown();
-    }
-
-    public void testPoolThreads10Connections10Fair() throws Exception {
-        init();
-        this.datasource.getPoolProperties().setMaxActive(10);
-        this.datasource.getPoolProperties().setFairQueue(true);
-        this.threadcount = 10;
-        this.transferProperties();
-        this.datasource.getConnection().close();
-        latch = new CountDownLatch(threadcount);
-        long start = System.currentTimeMillis();
-        for (int i=0; i<threadcount; i++) {
-            TestThread t = new TestThread();
-            t.setName("tomcat-pool-"+i);
-            t.d = this.datasource;
-            t.start();
-        }
-        latch.await();
-        long delta = System.currentTimeMillis() - start;
-        System.out.println("[testPoolThreads10Connections10Fair]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
-        tearDown();
-    }
-
-//    public void testC3P0Threads10Connections10() throws Exception {
-//        init();
-//        this.datasource.getPoolProperties().setMaxActive(10);
-//        this.threadcount = 10;
-//        this.transferPropertiesToC3P0();
-//        this.c3p0Datasource.getConnection().close();
-//        latch = new CountDownLatch(threadcount);
-//        long start = System.currentTimeMillis();
-//        for (int i=0; i<threadcount; i++) {
-//            TestThread t = new TestThread();
-//            t.setName("tomcat-pool-"+i);
-//            t.d = this.c3p0Datasource;
-//            t.start();
-//        }
-//        latch.await();
-//        long delta = System.currentTimeMillis() - start;
-//        System.out.println("[testC3P0Threads10Connections10]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
-//        tearDown();
-//    }
-
-    public void testDBCPThreads20Connections10() throws Exception {
-        init();
-        this.datasource.getPoolProperties().setMaxActive(10);
-        this.threadcount = 20;
-        this.transferProperties();
-        this.tDatasource.getConnection().close();
-        latch = new CountDownLatch(threadcount);
-        long start = System.currentTimeMillis();
-        for (int i=0; i<threadcount; i++) {
-            TestThread t = new TestThread();
-            t.setName("tomcat-dbcp-"+i);
-            t.d = this.tDatasource;
-            t.start();
-        }
-        latch.await();
-        long delta = System.currentTimeMillis() - start;
-        System.out.println("[testDBCPThreads20Connections10]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
-        tearDown();
-    }
-
-    public void testPoolThreads20Connections10() throws Exception {
-        init();
-        this.datasource.getPoolProperties().setMaxActive(10);
-        this.datasource.getPoolProperties().setFairQueue(false);
-        this.threadcount = 20;
-        this.transferProperties();
-        this.datasource.getConnection().close();
-        latch = new CountDownLatch(threadcount);
-        long start = System.currentTimeMillis();
-        for (int i=0; i<threadcount; i++) {
-            TestThread t = new TestThread();
-            t.setName("tomcat-pool-"+i);
-            t.d = this.datasource;
-            t.start();
-        }
-        latch.await();
-        long delta = System.currentTimeMillis() - start;
-        System.out.println("[testPoolThreads20Connections10]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
-        tearDown();
-    }
-
-    public void testPoolThreads20Connections10Fair() throws Exception {
-        init();
-        this.datasource.getPoolProperties().setMaxActive(10);
-        this.datasource.getPoolProperties().setFairQueue(true);
-        this.threadcount = 20;
-        this.transferProperties();
-        this.datasource.getConnection().close();
-        latch = new CountDownLatch(threadcount);
-        long start = System.currentTimeMillis();
-        for (int i=0; i<threadcount; i++) {
-            TestThread t = new TestThread();
-            t.setName("tomcat-pool-"+i);
-            t.d = this.datasource;
-            t.start();
-        }
-        latch.await();
-        long delta = System.currentTimeMillis() - start;
-        System.out.println("[testPoolThreads20Connections10Fair]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
-        tearDown();
-    }
-
-//    public void testC3P0Threads20Connections10() throws Exception {
-//        init();
-//        this.datasource.getPoolProperties().setMaxActive(10);
-//        this.threadcount = 20;
-//        this.transferPropertiesToC3P0();
-//        this.c3p0Datasource.getConnection().close();
-//        latch = new CountDownLatch(threadcount);
-//        long start = System.currentTimeMillis();
-//        for (int i=0; i<threadcount; i++) {
-//            TestThread t = new TestThread();
-//            t.setName("tomcat-pool-"+i);
-//            t.d = this.c3p0Datasource;
-//            t.start();
-//        }
-//        latch.await();
-//        long delta = System.currentTimeMillis() - start;
-//        System.out.println("[testC3P0Threads20Connections10]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
-//        tearDown();
-//    }
-    
-    public void testDBCPThreads10Connections10Validate() throws Exception {
-        init();
-        this.datasource.getPoolProperties().setMaxActive(10);
-        this.datasource.getPoolProperties().setTestOnBorrow(true);
-        this.threadcount = 10;
-        this.transferProperties();
-        this.tDatasource.getConnection().close();
-        latch = new CountDownLatch(threadcount);
-        long start = System.currentTimeMillis();
-        for (int i=0; i<threadcount; i++) {
-            TestThread t = new TestThread();
-            t.setName("tomcat-dbcp-validate-"+i);
-            t.d = this.tDatasource;
-            t.start();
-        }
-        latch.await();
-        long delta = System.currentTimeMillis() - start;
-        System.out.println("[testDBCPThreads10Connections10Validate]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
-        tearDown();
-    }
-
-    public void testPoolThreads10Connections10Validate() throws Exception {
-        init();
-        this.datasource.getPoolProperties().setMaxActive(10);
-        this.datasource.getPoolProperties().setTestOnBorrow(true);
-        this.datasource.getPoolProperties().setFairQueue(false);
-        this.threadcount = 10;
-        this.transferProperties();
-        this.datasource.getConnection().close();
-        latch = new CountDownLatch(threadcount);
-        long start = System.currentTimeMillis();
-        for (int i=0; i<threadcount; i++) {
-            TestThread t = new TestThread();
-            t.setName("tomcat-pool-validate-"+i);
-            t.d = this.datasource;
-            t.start();
-        }
-        latch.await();
-        long delta = System.currentTimeMillis() - start;
-        System.out.println("[testPoolThreads10Connections10Validate]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
-        tearDown();
-    }
-    
-    public void testPoolThreads10Connections10ValidateFair() throws Exception {
-        init();
-        this.datasource.getPoolProperties().setMaxActive(10);
-        this.datasource.getPoolProperties().setTestOnBorrow(true);
-        this.datasource.getPoolProperties().setFairQueue(true);
-        this.threadcount = 10;
-        this.transferProperties();
-        this.datasource.getConnection().close();
-        latch = new CountDownLatch(threadcount);
-        long start = System.currentTimeMillis();
-        for (int i=0; i<threadcount; i++) {
-            TestThread t = new TestThread();
-            t.setName("tomcat-pool-validate-"+i);
-            t.d = this.datasource;
-            t.start();
-        }
-        latch.await();
-        long delta = System.currentTimeMillis() - start;
-        System.out.println("[testPoolThreads10Connections10ValidateFair]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
-        tearDown();
-    }
-
-//    public void testC3P0Threads10Connections10Validate() throws Exception {
-//        init();
-//        this.datasource.getPoolProperties().setMaxActive(10);
-//        this.datasource.getPoolProperties().setTestOnBorrow(true);
-//        this.threadcount = 10;
-//        this.transferPropertiesToC3P0();
-//        this.c3p0Datasource.getConnection().close();
-//        latch = new CountDownLatch(threadcount);
-//        long start = System.currentTimeMillis();
-//        for (int i=0; i<threadcount; i++) {
-//            TestThread t = new TestThread();
-//            t.setName("tomcat-pool-validate-"+i);
-//            t.d = this.c3p0Datasource;
-//            t.start();
-//        }
-//        latch.await();
-//        long delta = System.currentTimeMillis() - start;
-//        System.out.println("[testC3P0Threads10Connections10Validate]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
-//        tearDown();
-//    }
-
-    public void testDBCPThreads20Connections10Validate() throws Exception {
-        init();
-        this.datasource.getPoolProperties().setMaxActive(10);
-        this.datasource.getPoolProperties().setTestOnBorrow(true);
-        this.threadcount = 20;
-        this.transferProperties();
-        this.tDatasource.getConnection().close();
-        latch = new CountDownLatch(threadcount);
-        long start = System.currentTimeMillis();
-        for (int i=0; i<threadcount; i++) {
-            TestThread t = new TestThread();
-            t.setName("tomcat-dbcp-validate-"+i);
-            t.d = this.tDatasource;
-            t.start();
-        }
-        latch.await();
-        long delta = System.currentTimeMillis() - start;
-        System.out.println("[testDBCPThreads20Connections10Validate]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
-        tearDown();
-    }
-
-    public void testPoolThreads10Connections20Validate() throws Exception {
-        init();
-        this.datasource.getPoolProperties().setMaxActive(10);
-        this.datasource.getPoolProperties().setTestOnBorrow(true);
-        this.datasource.getPoolProperties().setFairQueue(false);
-        this.threadcount = 20;
-        this.transferProperties();
-        this.datasource.getConnection().close();
-        latch = new CountDownLatch(threadcount);
-        long start = System.currentTimeMillis();
-        for (int i=0; i<threadcount; i++) {
-            TestThread t = new TestThread();
-            t.setName("tomcat-pool-validate-"+i);
-            t.d = this.datasource;
-            t.start();
-        }
-        latch.await();
-        long delta = System.currentTimeMillis() - start;
-        System.out.println("[testPoolThreads20Connections10Validate]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
-        tearDown();
-    }
-    
-    public void testPoolThreads10Connections20ValidateFair() throws Exception {
-        init();
-        this.datasource.getPoolProperties().setMaxActive(10);
-        this.datasource.getPoolProperties().setTestOnBorrow(true);
-        this.datasource.getPoolProperties().setFairQueue(true);
-        this.threadcount = 20;
-        this.transferProperties();
-        this.datasource.getConnection().close();
-        latch = new CountDownLatch(threadcount);
-        long start = System.currentTimeMillis();
-        for (int i=0; i<threadcount; i++) {
-            TestThread t = new TestThread();
-            t.setName("tomcat-pool-validate-"+i);
-            t.d = this.datasource;
-            t.start();
-        }
-        latch.await();
-        long delta = System.currentTimeMillis() - start;
-        System.out.println("[testPoolThreads20Connections10ValidateFair]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
-        tearDown();
-    }
-    
-//    public void testC3P0Threads10Connections20Validate() throws Exception {
-//        init();
-//        this.datasource.getPoolProperties().setMaxActive(10);
-//        this.datasource.getPoolProperties().setTestOnBorrow(true);
-//        this.threadcount = 20;
-//        this.transferPropertiesToC3P0();
-//        this.c3p0Datasource.getConnection().close();
-//        latch = new CountDownLatch(threadcount);
-//        long start = System.currentTimeMillis();
-//        for (int i=0; i<threadcount; i++) {
-//            TestThread t = new TestThread();
-//            t.setName("tomcat-pool-validate-"+i);
-//            t.d = this.c3p0Datasource;
-//            t.start();
-//        }
-//        latch.await();
-//        long delta = System.currentTimeMillis() - start;
-//        System.out.println("[testC3P0Threads10Connections20Validate]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));
-//        tearDown();
-//    }
-
-    public class TestThread extends Thread {
-        protected DataSource d;
-        protected String query = null;
-        @Override
-        public void run() {
-            long max = -1, totalmax=0, totalcmax=0, cmax = -1, nroffetch = 0, totalruntime = 0;
-            try {
-                for (int i = 0; i < CheckOutThreadTest.this.iterations; i++) {
-                    long start = System.nanoTime();
-                    Connection con = null;
-                    try {
-                        con = d.getConnection();
-                        long delta = System.nanoTime() - start;
-                        totalmax += delta;
-                        max = Math.max(delta, max);
-                        nroffetch++;
-                        if (query!=null) {
-                            Statement st = con.createStatement();
-                            ResultSet rs = st.executeQuery(query);
-                            while (rs.next()) {
-                            }
-                            rs.close();
-                            st.close();
-                        }
-                    } finally {
-                        long cstart = System.nanoTime();
-                        if (con!=null) try {con.close();}catch(Exception x) {x.printStackTrace();}
-                        long cdelta = System.nanoTime() - cstart;
-                        totalcmax += cdelta;
-                        cmax = Math.max(cdelta, cmax);
-                    }
-                    totalruntime+=(System.nanoTime()-start);
-                }
-
-            } catch (Exception x) {
-                x.printStackTrace();
-            } finally {
-                CheckOutThreadTest.this.latch.countDown();
-            }
-            if (System.getProperty("print-thread-stats")!=null) {
-                System.out.println("["+getName()+"] "+
-                    "\n\tMax time to retrieve connection:"+(max/1000f/1000f)+" ms."+
-                    "\n\tTotal time to retrieve connection:"+(totalmax/1000f/1000f)+" ms."+
-                    "\n\tAverage time to retrieve connection:"+(totalmax/1000f/1000f)/nroffetch+" ms."+
-                    "\n\tMax time to close connection:"+(cmax/1000f/1000f)+" ms."+
-                    "\n\tTotal time to close connection:"+(totalcmax/1000f/1000f)+" ms."+
-                    "\n\tAverage time to close connection:"+(totalcmax/1000f/1000f)/nroffetch+" ms."+
-                    "\n\tRun time:"+(totalruntime/1000f/1000f)+" ms."+
-                    "\n\tNr of fetch:"+nroffetch);
-            }
-        }
-    }
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/ConnectCountTest.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/ConnectCountTest.java
deleted file mode 100644 (file)
index 339e1aa..0000000
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * 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.util.concurrent.CountDownLatch;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.sql.Connection;
-import java.sql.Statement;
-import java.sql.ResultSet;
-
-import javax.sql.DataSource;
-
-import org.apache.tomcat.jdbc.pool.DataSourceProxy;
-import org.apache.tomcat.jdbc.test.driver.Driver;
-
-/**
- * @author Filip Hanik
- * @version 1.0
- */
-public class ConnectCountTest extends DefaultTestCase {
-    public ConnectCountTest(String name) {
-        super(name);
-    }
-    
-    protected boolean run = true;
-    protected long sleep = Long.getLong("sleep", 10);
-    protected long complete = Long.getLong("complete",20000);
-    protected boolean printthread = Boolean.getBoolean("printthread");
-    CountDownLatch latch = null;
-
-
-    @Override
-    public org.apache.tomcat.jdbc.pool.DataSource createDefaultDataSource() {
-        // TODO Auto-generated method stub
-        org.apache.tomcat.jdbc.pool.DataSource ds = super.createDefaultDataSource();
-        ds.getPoolProperties().setDriverClassName(Driver.class.getName());
-        ds.getPoolProperties().setUrl(Driver.url);
-        ds.getPoolProperties().setInitialSize(0);
-        ds.getPoolProperties().setMaxIdle(10);
-        ds.getPoolProperties().setMinIdle(10);
-        ds.getPoolProperties().setMaxActive(10);
-        return ds;
-    }
-
-
-    @Override
-    protected void tearDown() throws Exception {
-        Driver.reset();
-        super.tearDown();
-    }
-
-
-    protected void printThreadResults(TestThread[] threads, String name, int active, int expected) {
-        long minfetch = Long.MAX_VALUE, maxfetch = Long.MIN_VALUE, totalfetch = 0;
-        long maxwait = 0, minwait = Long.MAX_VALUE, averagewait = 0, totalwait = 0;
-        float avgfetch = 0;
-        for (int i=0; i<threads.length; i++) {
-            TestThread t = threads[i];
-            totalfetch += t.nroffetch;
-            totalwait  += t.totalwait;
-            maxwait = Math.max(maxwait,t.maxwait);
-            minwait = Math.min(minwait, t.minwait);
-            minfetch = Math.min(minfetch, t.nroffetch);
-            maxfetch = Math.max(maxfetch, t.nroffetch);
-            if (ConnectCountTest.this.printthread)
-                System.out.println(t.getName()+" : Nr-of-fetch:"+t.nroffetch+ " Max fetch Time:"+(((float)t.maxwait)/1000000f)+"ms. :Max close time:"+(((float)t.cmax)/1000000f)+"ms.");
-        }
-        System.out.println("["+name+"] Max fetch:"+(maxfetch)+" Min fetch:"+(minfetch)+" Average fetch:"+
-                           (((float)totalfetch))/(float)threads.length);
-        System.out.println("["+name+"] Max wait:"+(((float)maxwait)/1000000f)+"ms. Min wait:"+(((float)minwait)/1000000f)+"ms. Average wait:"+(((((float)totalwait))/(float)totalfetch)/1000000f)+" ms.");
-        System.out.println("["+name+"] Max active:"+active+" Expected Active:"+expected);
-        
-        
-    }
-    
-    public void testDBCPThreads20Connections10() throws Exception {
-        System.out.println("[testDBCPThreads20Connections10] Starting fairness - DBCP");
-        this.threadcount = 20;
-        init();
-        this.transferProperties();
-        this.tDatasource.getConnection().close();
-        latch = new CountDownLatch(threadcount);
-        long start = System.currentTimeMillis();
-        TestThread[] threads = new TestThread[threadcount];
-        for (int i=0; i<threadcount; i++) {
-            threads[i] = new TestThread();
-            threads[i].setName("tomcat-dbcp-"+i);
-            threads[i].d = this.tDatasource;
-            
-        }
-        for (int i=0; i<threadcount; i++) {
-            threads[i].start();
-        }
-        if (!latch.await(complete+1000,TimeUnit.MILLISECONDS)) {
-            System.out.println("Latch timed out.");
-        }
-        this.run = false;
-        long delta = System.currentTimeMillis() - start;
-        printThreadResults(threads,"testDBCPThreads20Connections10",Driver.connectCount.get(),10);
-        tearDown();
-    }
-
-    public void testPoolThreads20Connections10() throws Exception {
-        System.out.println("[testPoolThreads20Connections10] Starting fairness - Tomcat JDBC - Non Fair");
-        init();
-        this.threadcount = 20;
-        this.transferProperties();
-        this.datasource.getConnection().close();
-        latch = new CountDownLatch(threadcount);
-        long start = System.currentTimeMillis();
-        TestThread[] threads = new TestThread[threadcount];
-        for (int i=0; i<threadcount; i++) {
-            threads[i] = new TestThread();
-            threads[i].setName("tomcat-pool-"+i);
-            threads[i].d = this.datasource;
-            
-        }
-        for (int i=0; i<threadcount; i++) {
-            threads[i].start();
-        }
-        if (!latch.await(complete+1000,TimeUnit.MILLISECONDS)) {
-            System.out.println("Latch timed out.");
-        }
-        this.run = false;
-        long delta = System.currentTimeMillis() - start;
-        printThreadResults(threads,"testPoolThreads20Connections10",Driver.connectCount.get(),10);
-        tearDown();
-
-    }
-
-    public void testPoolThreads20Connections10Fair() throws Exception {
-        System.out.println("[testPoolThreads20Connections10Fair] Starting fairness - Tomcat JDBC - Fair");
-        init();
-        this.threadcount = 20;
-        this.datasource.getPoolProperties().setFairQueue(true);
-        this.transferProperties();
-        this.datasource.getConnection().close();
-        latch = new CountDownLatch(threadcount);
-        long start = System.currentTimeMillis();
-        TestThread[] threads = new TestThread[threadcount];
-        for (int i=0; i<threadcount; i++) {
-            threads[i] = new TestThread();
-            threads[i].setName("tomcat-pool-"+i);
-            threads[i].d = this.datasource;
-            
-        }
-        for (int i=0; i<threadcount; i++) {
-            threads[i].start();
-        }
-        if (!latch.await(complete+1000,TimeUnit.MILLISECONDS)) {
-            System.out.println("Latch timed out.");
-        }
-        this.run = false;
-        long delta = System.currentTimeMillis() - start;
-        printThreadResults(threads,"testPoolThreads20Connections10Fair",Driver.connectCount.get(),10);
-        tearDown();
-    }
-    public void testPoolThreads20Connections10FairAsync() throws Exception {
-        System.out.println("[testPoolThreads20Connections10FairAsync] Starting fairness - Tomcat JDBC - Fair - Async");
-        init();
-        this.threadcount = 20;
-        this.datasource.getPoolProperties().setFairQueue(true);
-        this.datasource.getPoolProperties().setInitialSize(this.datasource.getPoolProperties().getMaxActive());
-        this.transferProperties();
-        this.datasource.getConnection().close();
-        latch = new CountDownLatch(threadcount);
-        long start = System.currentTimeMillis();
-        TestThread[] threads = new TestThread[threadcount];
-        for (int i=0; i<threadcount; i++) {
-            threads[i] = new TestThread();
-            threads[i].setName("tomcat-pool-"+i);
-            threads[i].async = true;
-            threads[i].d = this.datasource;
-            
-        }
-        for (int i=0; i<threadcount; i++) {
-            threads[i].start();
-        }
-        if (!latch.await(complete+1000,TimeUnit.MILLISECONDS)) {
-            System.out.println("Latch timed out.");
-        }
-        this.run = false;
-        long delta = System.currentTimeMillis() - start;
-        printThreadResults(threads,"testPoolThreads20Connections10FairAsync",Driver.connectCount.get(),10);
-        tearDown();
-    }
-    
-//    public void testC3P0Threads20Connections10() throws Exception {
-//        System.out.println("[testC3P0Threads20Connections10] Starting fairness - C3P0");
-//        init();
-//        this.threadcount = 20;
-//        this.transferPropertiesToC3P0();
-//        this.datasource.getConnection().close();
-//        latch = new CountDownLatch(threadcount);
-//        long start = System.currentTimeMillis();
-//        TestThread[] threads = new TestThread[threadcount];
-//        for (int i=0; i<threadcount; i++) {
-//            threads[i] = new TestThread();
-//            threads[i].setName("tomcat-pool-"+i);
-//            threads[i].d = this.c3p0Datasource;
-//            
-//        }
-//        for (int i=0; i<threadcount; i++) {
-//            threads[i].start();
-//        }
-//        if (!latch.await(complete+1000,TimeUnit.MILLISECONDS)) {
-//            System.out.println("Latch timed out.");
-//        }
-//        this.run = false;
-//        long delta = System.currentTimeMillis() - start;
-//        printThreadResults(threads,"testC3P0Threads20Connections10",Driver.connectCount.get(),10);
-//        tearDown();
-//
-//    }
-
-    
-    public class TestThread extends Thread {
-        protected DataSource d;
-        protected String query = null;
-        protected long sleep = 10;
-        protected boolean async = false;
-        long minwait = Long.MAX_VALUE, maxwait = -1, totalwait=0, totalcmax=0, cmax = -1, nroffetch = 0, totalruntime = 0;
-        @Override
-        public void run() {
-            try {
-                long now = System.currentTimeMillis();
-                while (ConnectCountTest.this.run) {
-                    if ((System.currentTimeMillis()-now)>=ConnectCountTest.this.complete) break;
-                    long start = System.nanoTime();
-                    Connection con = null;
-                    try {
-                        if (async) {
-                            Future<Connection> cf = ((DataSourceProxy)d).getConnectionAsync();
-                            con  = cf.get();
-                        } else {
-                            con = d.getConnection();
-                        }
-                        long delta = System.nanoTime() - start;
-                        totalwait += delta;
-                        maxwait = Math.max(delta, maxwait);
-                        minwait = Math.min(delta, minwait);
-                        nroffetch++;
-                        if (query!=null) {
-                            Statement st = con.createStatement();
-                            ResultSet rs = st.executeQuery(query);
-                            while (rs.next()) {
-                            }
-                            rs.close();
-                            st.close();
-                        }
-                        try { 
-                            if (ConnectCountTest.this.sleep>0) sleep(ConnectCountTest.this.sleep); 
-                        } catch (InterruptedException x) {
-                            interrupted();
-                        }
-                    } finally {
-                        long cstart = System.nanoTime();
-                        if (con!=null) try {con.close();}catch(Exception x) {x.printStackTrace();}
-                        long cdelta = System.nanoTime() - cstart;
-                        totalcmax += cdelta;
-                        cmax = Math.max(cdelta, cmax);
-                    }
-                    totalruntime+=(System.nanoTime()-start);
-                }
-
-            } catch (Exception x) {
-                x.printStackTrace();
-            } finally {
-                ConnectCountTest.this.latch.countDown();
-            }
-            if (System.getProperty("print-thread-stats")!=null) {
-                System.out.println("["+getName()+"] "+
-                    "\n\tMax time to retrieve connection:"+(((float)maxwait)/1000f/1000f)+" ms."+
-                    "\n\tTotal time to retrieve connection:"+(((float)totalwait)/1000f/1000f)+" ms."+
-                    "\n\tAverage time to retrieve connection:"+(((float)totalwait)/1000f/1000f)/(float)nroffetch+" ms."+
-                    "\n\tMax time to close connection:"+(((float)cmax)/1000f/1000f)+" ms."+
-                    "\n\tTotal time to close connection:"+(((float)totalcmax)/1000f/1000f)+" ms."+
-                    "\n\tAverage time to close connection:"+(((float)totalcmax)/1000f/1000f)/(float)nroffetch+" ms."+
-                    "\n\tRun time:"+(((float)totalruntime)/1000f/1000f)+" ms."+
-                    "\n\tNr of fetch:"+nroffetch);
-            }
-        }
-    }
-}
-
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/CreateTestTable.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/CreateTestTable.java
deleted file mode 100644 (file)
index 825cb00..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- *  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 java.sql.Statement;
-import java.util.Random;
-import java.sql.ResultSet;
-
-import org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer;
-
-public class CreateTestTable extends DefaultTestCase {
-    
-    public static volatile boolean recreate = Boolean.getBoolean("recreate");
-    
-    public CreateTestTable(String name) {
-        super(name);
-    }
-
-    public void testCreateTestTable() throws Exception {
-        this.init();
-        Connection con = datasource.getConnection();
-        Statement st = con.createStatement();
-        try {
-            st.execute("create table test(id int not null, val1 varchar(255), val2 varchar(255), val3 varchar(255), val4 varchar(255))");
-        }catch (Exception ignore) {}
-        st.close();
-        con.close();
-    }
-    
-    public int testCheckData() throws Exception {
-        int count = 0;
-        String check = "select count (*) from test";
-        this.init();
-        Connection con = datasource.getConnection();
-        Statement st = con.createStatement();
-        try {
-            ResultSet rs = st.executeQuery(check);
-            
-            if (rs.next())
-                count = rs.getInt(1);
-            rs.close();
-            st.close();
-            System.out.println("Count:"+count);
-        }catch (Exception ignore) {}
-        con.close();
-        return count;
-    }
-    
-    public void testPopulateData() throws Exception {
-        int count = 100000;
-        int actual = testCheckData();
-        if (actual>=count) {
-            System.out.println("Test tables has "+actual+" rows of data. No need to populate.");
-            return;
-        }
-        
-        datasource.setJdbcInterceptors(ResetAbandonedTimer.class.getName());
-        String insert = "insert into test values (?,?,?,?,?)";
-        this.init();
-        this.datasource.setRemoveAbandoned(false);
-        Connection con = datasource.getConnection();
-        
-        boolean commit = con.getAutoCommit();
-        con.setAutoCommit(false);
-        if (recreate) {
-            Statement st = con.createStatement();
-            try {
-                st.execute("drop table test");
-            }catch (Exception ignore) {}
-            st.execute("create table test(id int not null, val1 varchar(255), val2 varchar(255), val3 varchar(255), val4 varchar(255))");
-            st.close();
-        }
-        
-        
-        PreparedStatement ps = con.prepareStatement(insert);
-        ps.setQueryTimeout(0);
-        for (int i=actual; i<count; i++) {
-            ps.setInt(1,i);
-            String s = getRandom();
-            ps.setString(2, s);
-            ps.setString(3, s);
-            ps.setString(4, s);
-            ps.setString(5, s);
-            ps.addBatch();
-            ps.clearParameters();
-            if ((i+1) % 1000 == 0) {
-                System.out.print(".");
-            }
-            if ((i+1) % 10000 == 0) {
-                System.out.print("\n"+(i+1));
-                ps.executeBatch();
-                ps.close();
-                con.commit();
-                ps = con.prepareStatement(insert);
-                ps.setQueryTimeout(0);
-            }
-
-        }
-        ps.close();
-        con.setAutoCommit(commit);
-        con.close();
-    }
-    
-    public static Random random = new Random(System.currentTimeMillis());
-    public static String getRandom() {
-        StringBuilder s = new StringBuilder(256);
-        for (int i=0;i<254; i++) {
-            int b = Math.abs(random.nextInt() % 29);
-            char c = (char)(b+65);
-            s.append(c);
-        }
-        return s.toString();
-    }
-    
-    public static void main(String[] args) throws Exception {
-        recreate = true;
-        CreateTestTable test = new CreateTestTable("CreateTestTable");
-        test.testPopulateData();
-    }
-
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/DefaultProperties.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/DefaultProperties.java
deleted file mode 100644 (file)
index 235b555..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.util.Properties;
-
-import org.apache.tomcat.jdbc.pool.DataSourceFactory;
-import org.apache.tomcat.jdbc.pool.PoolProperties;
-
-/**
- * @author Filip Hanik
- * @version 1.0
- */
-public class DefaultProperties extends PoolProperties {
-    public DefaultProperties() {
-        dbProperties = new Properties();
-        
-        //mysql
-        //url = System.getProperty("url","jdbc:mysql://localhost:3306/mysql?autoReconnect=true"); 
-        //driverClassName = System.getProperty("driverClassName","com.mysql.jdbc.Driver");
-        
-        //derby
-        //url = System.getProperty("url","jdbc:derby:derbyDB;create=true");
-        //driverClassName = System.getProperty("driverClassName","org.apache.derby.jdbc.EmbeddedDriver");
-        
-        url = System.getProperty("url","jdbc:h2:~/.h2/test;QUERY_TIMEOUT=0;DB_CLOSE_ON_EXIT=FALSE");
-        driverClassName = System.getProperty("driverClassName","org.h2.Driver");
-        System.setProperty("h2.serverCachedObjects", "10000");
-        
-        password = System.getProperty("password","password");
-        username = System.getProperty("username","root");
-        
-        validationQuery = System.getProperty("validationQuery","SELECT 1");
-        defaultAutoCommit = true;
-        defaultReadOnly = false;
-        defaultTransactionIsolation = DataSourceFactory.UNKNOWN_TRANSACTIONISOLATION;
-        connectionProperties = null;
-        defaultCatalog = null;
-        initialSize = 10;
-        maxActive = 100;
-        maxIdle = initialSize;
-        minIdle = initialSize;
-        maxWait = 10000;
-        
-        testOnBorrow = true;
-        testOnReturn = false;
-        testWhileIdle = true;
-        timeBetweenEvictionRunsMillis = 5000;
-        numTestsPerEvictionRun = 0;
-        minEvictableIdleTimeMillis = 1000;
-        removeAbandoned = true;
-        removeAbandonedTimeout = 5000;
-        logAbandoned = true;
-        validationInterval = 0; //always validate
-        initSQL = null;
-        testOnConnect = false;;
-        dbProperties.setProperty("user",username);
-        dbProperties.setProperty("password",password);
-    }
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/DefaultTestCase.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/DefaultTestCase.java
deleted file mode 100644 (file)
index 401c380..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * 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.lang.reflect.Method;
-import java.util.Properties;
-
-import junit.framework.TestCase;
-
-import org.apache.tomcat.dbcp.dbcp.BasicDataSource;
-import org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory;
-import org.apache.tomcat.jdbc.pool.PoolConfiguration;
-import org.apache.tomcat.jdbc.pool.PoolProperties;
-
-//import com.mchange.v2.c3p0.ComboPooledDataSource;
-//import com.mchange.v2.log.MLevel;
-//import com.mchange.v2.log.MLog;
-
-/**
- * @author Filip Hanik
- * @version 1.0
- */
-public class DefaultTestCase extends TestCase {
-    protected org.apache.tomcat.jdbc.pool.DataSource datasource;
-    protected BasicDataSource tDatasource;
-//    protected ComboPooledDataSource c3p0Datasource;
-    protected int threadcount = 10;
-    protected int iterations = 100000;
-    public DefaultTestCase(String name) {
-        super(name);
-    }
-    
-    @Override
-    public void setUp() throws Exception {
-        init();
-    }
-
-    public org.apache.tomcat.jdbc.pool.DataSource createDefaultDataSource() {
-        org.apache.tomcat.jdbc.pool.DataSource datasource = null;
-        PoolConfiguration p = new DefaultProperties();
-        p.setFairQueue(false);
-        p.setJmxEnabled(false);
-        p.setTestWhileIdle(false);
-        p.setTestOnBorrow(false);
-        p.setTestOnReturn(false);
-        p.setValidationInterval(30000);
-        p.setTimeBetweenEvictionRunsMillis(30000);
-        p.setMaxActive(threadcount);
-        p.setInitialSize(threadcount);
-        p.setMaxWait(10000);
-        p.setRemoveAbandonedTimeout(10);
-        p.setMinEvictableIdleTimeMillis(10000);
-        p.setMinIdle(threadcount);
-        p.setLogAbandoned(false);
-        p.setRemoveAbandoned(false);
-        datasource = new org.apache.tomcat.jdbc.pool.DataSource();
-        datasource.setPoolProperties(p);
-        return datasource;
-    }
-    
-    protected void init() throws Exception {
-        this.datasource = createDefaultDataSource();
-    }
-
-    protected void transferProperties() {
-        try {
-            Properties p = new Properties();
-            for (int i=0; i< ALL_PROPERTIES.length; i++) {
-                String name = "get" + Character.toUpperCase(ALL_PROPERTIES[i].charAt(0)) + ALL_PROPERTIES[i].substring(1);
-                String bname = "is" + name.substring(3);
-                Method get = null;
-                try {
-                    get = PoolProperties.class.getMethod(name, new Class[0]);
-                }catch (NoSuchMethodException x) {
-                    try {
-                    get = PoolProperties.class.getMethod(bname, new Class[0]);
-                    }catch (NoSuchMethodException x2) {
-                        System.err.println(x2.getMessage());
-                    }
-                }
-                   if (get!=null) {
-                       Object value = get.invoke(datasource.getPoolProperties(), new Object[0]);
-                       if (value!=null) {
-                           p.setProperty(ALL_PROPERTIES[i], value.toString());
-                       }
-                }
-            }
-            tDatasource = (BasicDataSource) BasicDataSourceFactory.createDataSource(p);
-        }catch (Exception x) {
-            x.printStackTrace();
-        }
-    }
-    
-    protected void transferPropertiesToC3P0() throws Exception {
-//        System.setProperty("com.mchange.v2.log.FallbackMLog.DEFAULT_CUTOFF_LEVEL", "WARNING");
-//        MLog.getLogger().setLevel(MLevel.WARNING);
-//        MLog.getLogger("com").setLevel(MLevel.WARNING);
-//        //http://www.mchange.com/projects/c3p0/index.html#automaticTestTable
-//        ComboPooledDataSource c3p0 = new ComboPooledDataSource();  
-//        c3p0.setAcquireIncrement(1);
-//        c3p0.setAcquireRetryAttempts(2);
-//        c3p0.setAcquireRetryDelay(datasource.getPoolProperties().getMaxWait());
-//        c3p0.setCheckoutTimeout(datasource.getPoolProperties().getMaxWait());
-//        c3p0.setDebugUnreturnedConnectionStackTraces(datasource.getPoolProperties().isLogAbandoned());
-//        c3p0.setIdleConnectionTestPeriod(datasource.getPoolProperties().getTimeBetweenEvictionRunsMillis()/1000);
-//        c3p0.setInitialPoolSize(datasource.getPoolProperties().getInitialSize());
-//        c3p0.setMaxIdleTime(datasource.getPoolProperties().getMinEvictableIdleTimeMillis()/1000);
-//        c3p0.setMaxIdleTimeExcessConnections(datasource.getPoolProperties().getMaxIdle());
-//        c3p0.setMaxPoolSize(datasource.getPoolProperties().getMaxActive());
-//        c3p0.setMinPoolSize(datasource.getPoolProperties().getMinIdle());
-//        c3p0.setPassword(datasource.getPoolProperties().getPassword());
-//        c3p0.setPreferredTestQuery(datasource.getPoolProperties().getValidationQuery());
-//        c3p0.setTestConnectionOnCheckin(datasource.getPoolProperties().isTestOnReturn());
-//        c3p0.setTestConnectionOnCheckout(datasource.getPoolProperties().isTestOnBorrow());
-//        c3p0.setUnreturnedConnectionTimeout(datasource.getPoolProperties().getRemoveAbandonedTimeout());
-//        c3p0.setUser(datasource.getPoolProperties().getUsername());
-//        c3p0.setUsesTraditionalReflectiveProxies(true);
-//        c3p0.setJdbcUrl(datasource.getPoolProperties().getUrl());
-//        c3p0.setDriverClass(datasource.getPoolProperties().getDriverClassName());
-//        this.c3p0Datasource = c3p0;
-        
-      /**
-        acquireIncrement
-        acquireRetryAttempts
-        acquireRetryDelay
-        autoCommitOnClose
-        automaticTestTable
-        breakAfterAcquireFailure
-        checkoutTimeout
-        connectionCustomizerClassName
-        connectionTesterClassName
-        debugUnreturnedConnectionStackTraces
-        factoryClassLocation
-        forceIgnoreUnresolvedTransactions
-        idleConnectionTestPeriod
-        initialPoolSize
-        maxAdministrativeTaskTime
-        maxConnectionAge
-        maxIdleTime
-        maxIdleTimeExcessConnections
-        maxPoolSize
-        maxStatements
-        maxStatementsPerConnection
-        minPoolSize
-        numHelperThreads
-        overrideDefaultUser
-        overrideDefaultPassword
-        password
-        preferredTestQuery
-        propertyCycle
-        testConnectionOnCheckin
-        testConnectionOnCheckout
-        unreturnedConnectionTimeout
-        user
-        usesTraditionalReflectiveProxies
-        */
-    }
-
-
-    @Override
-    protected void tearDown() throws Exception {
-        try {datasource.close();}catch(Exception ignore){}
-        try {tDatasource.close();}catch(Exception ignore){}
-        //try {((ComboPooledDataSource)c3p0Datasource).close(true);}catch(Exception ignore){}
-        datasource = null;
-        tDatasource = null;
-        //c3p0Datasource = null;
-        System.gc();
-        org.apache.tomcat.jdbc.test.driver.Driver.reset();
-    }
-
-    private final static String PROP_DEFAULTAUTOCOMMIT = "defaultAutoCommit";
-    private final static String PROP_DEFAULTREADONLY = "defaultReadOnly";
-    private final static String PROP_DEFAULTTRANSACTIONISOLATION = "defaultTransactionIsolation";
-    private final static String PROP_DEFAULTCATALOG = "defaultCatalog";
-    private final static String PROP_DRIVERCLASSNAME = "driverClassName";
-    private final static String PROP_MAXACTIVE = "maxActive";
-    private final static String PROP_MAXIDLE = "maxIdle";
-    private final static String PROP_MINIDLE = "minIdle";
-    private final static String PROP_INITIALSIZE = "initialSize";
-    private final static String PROP_MAXWAIT = "maxWait";
-    private final static String PROP_TESTONBORROW = "testOnBorrow";
-    private final static String PROP_TESTONRETURN = "testOnReturn";
-    private final static String PROP_TIMEBETWEENEVICTIONRUNSMILLIS = "timeBetweenEvictionRunsMillis";
-    private final static String PROP_NUMTESTSPEREVICTIONRUN = "numTestsPerEvictionRun";
-    private final static String PROP_MINEVICTABLEIDLETIMEMILLIS = "minEvictableIdleTimeMillis";
-    private final static String PROP_TESTWHILEIDLE = "testWhileIdle";
-    private final static String PROP_PASSWORD = "password";
-    private final static String PROP_URL = "url";
-    private final static String PROP_USERNAME = "username";
-    private final static String PROP_VALIDATIONQUERY = "validationQuery";
-    private final static String PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED = "accessToUnderlyingConnectionAllowed";
-    private final static String PROP_REMOVEABANDONED = "removeAbandoned";
-    private final static String PROP_REMOVEABANDONEDTIMEOUT = "removeAbandonedTimeout";
-    private final static String PROP_LOGABANDONED = "logAbandoned";
-    private final static String PROP_POOLPREPAREDSTATEMENTS = "poolPreparedStatements";
-    private final static String PROP_MAXOPENPREPAREDSTATEMENTS = "maxOpenPreparedStatements";
-    private final static String PROP_CONNECTIONPROPERTIES = "connectionProperties";
-
-    private final static String[] ALL_PROPERTIES = {
-        PROP_DEFAULTAUTOCOMMIT,
-        PROP_DEFAULTREADONLY,
-        PROP_DEFAULTTRANSACTIONISOLATION,
-        PROP_DEFAULTCATALOG,
-        PROP_DRIVERCLASSNAME,
-        PROP_MAXACTIVE,
-        PROP_MAXIDLE,
-        PROP_MINIDLE,
-        PROP_INITIALSIZE,
-        PROP_MAXWAIT,
-        PROP_TESTONBORROW,
-        PROP_TESTONRETURN,
-        PROP_TIMEBETWEENEVICTIONRUNSMILLIS,
-        PROP_NUMTESTSPEREVICTIONRUN,
-        PROP_MINEVICTABLEIDLETIMEMILLIS,
-        PROP_TESTWHILEIDLE,
-        PROP_PASSWORD,
-        PROP_URL,
-        PROP_USERNAME,
-        PROP_VALIDATIONQUERY,
-        PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED,
-        PROP_REMOVEABANDONED,
-        PROP_REMOVEABANDONEDTIMEOUT,
-        PROP_LOGABANDONED,
-        PROP_CONNECTIONPROPERTIES
-    };
-
-
-
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/FairnessTest.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/FairnessTest.java
deleted file mode 100644 (file)
index b296eee..0000000
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * 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.util.concurrent.CountDownLatch;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.sql.Connection;
-import java.sql.Statement;
-import java.sql.ResultSet;
-
-import javax.sql.DataSource;
-
-import org.apache.tomcat.jdbc.pool.DataSourceProxy;
-
-/**
- * @author Filip Hanik
- * @version 1.0
- */
-public class FairnessTest extends DefaultTestCase {
-    public FairnessTest(String name) {
-        super(name);
-    }
-    
-    protected boolean run = true;
-    protected long sleep = Long.getLong("sleep", 10);
-    protected long complete = Long.getLong("complete",20000);
-    protected boolean printthread = Boolean.getBoolean("printthread");
-    CountDownLatch latch = null;
-    protected void printThreadResults(TestThread[] threads, String name, int active, int expected) {
-        long minfetch = Long.MAX_VALUE, maxfetch = Long.MIN_VALUE, totalfetch = 0;
-        long maxwait = 0, minwait = Long.MAX_VALUE, averagewait = 0, totalwait = 0;
-        float avgfetch = 0;
-        for (int i=0; i<threads.length; i++) {
-            TestThread t = threads[i];
-            totalfetch += t.nroffetch;
-            totalwait  += t.totalwait;
-            maxwait = Math.max(maxwait,t.maxwait);
-            minwait = Math.min(minwait, t.minwait);
-            minfetch = Math.min(minfetch, t.nroffetch);
-            maxfetch = Math.max(maxfetch, t.nroffetch);
-            if (FairnessTest.this.printthread)
-                System.out.println(t.getName()+" : Nr-of-fetch:"+t.nroffetch+ " Max fetch Time:"+(((float)t.maxwait)/1000000f)+"ms. :Max close time:"+(((float)t.cmax)/1000000f)+"ms.");
-        }
-        System.out.println("["+name+"] Max fetch:"+(maxfetch)+" Min fetch:"+(minfetch)+" Average fetch:"+
-                           (((float)totalfetch))/(float)threads.length);
-        System.out.println("["+name+"] Max wait:"+(((float)maxwait)/1000000f)+"ms. Min wait:"+(((float)minwait)/1000000f)+"ms. Average wait:"+(((((float)totalwait))/(float)totalfetch)/1000000f)+" ms.");
-        System.out.println("["+name+"] Max active:"+active+" Expected Active:"+expected);
-        
-        
-    }
-    
-    public void testDBCPThreads20Connections10() throws Exception {
-        System.out.println("[testDBCPThreads20Connections10] Starting fairness - DBCP");
-        init();
-        this.datasource.getPoolProperties().setMaxActive(10);
-        this.threadcount = 20;
-        this.transferProperties();
-        this.tDatasource.getConnection().close();
-        latch = new CountDownLatch(threadcount);
-        long start = System.currentTimeMillis();
-        TestThread[] threads = new TestThread[threadcount];
-        for (int i=0; i<threadcount; i++) {
-            threads[i] = new TestThread();
-            threads[i].setName("tomcat-dbcp-"+i);
-            threads[i].d = this.tDatasource;
-            
-        }
-        for (int i=0; i<threadcount; i++) {
-            threads[i].start();
-        }
-        if (!latch.await(complete+1000,TimeUnit.MILLISECONDS)) {
-            System.out.println("Latch timed out.");
-        }
-        this.run = false;
-        long delta = System.currentTimeMillis() - start;
-        printThreadResults(threads,"testDBCPThreads20Connections10",this.tDatasource.getNumActive(),10);
-        tearDown();
-    }
-
-    public void testPoolThreads20Connections10() throws Exception {
-        System.out.println("[testPoolThreads20Connections10] Starting fairness - Tomcat JDBC - Non Fair");
-        init();
-        this.datasource.getPoolProperties().setMaxActive(10);
-        this.datasource.getPoolProperties().setFairQueue(false);
-        this.threadcount = 20;
-        this.transferProperties();
-        this.datasource.getConnection().close();
-        latch = new CountDownLatch(threadcount);
-        long start = System.currentTimeMillis();
-        TestThread[] threads = new TestThread[threadcount];
-        for (int i=0; i<threadcount; i++) {
-            threads[i] = new TestThread();
-            threads[i].setName("tomcat-pool-"+i);
-            threads[i].d = this.datasource;
-            
-        }
-        for (int i=0; i<threadcount; i++) {
-            threads[i].start();
-        }
-        if (!latch.await(complete+1000,TimeUnit.MILLISECONDS)) {
-            System.out.println("Latch timed out.");
-        }
-        this.run = false;
-        long delta = System.currentTimeMillis() - start;
-        printThreadResults(threads,"testPoolThreads20Connections10",this.datasource.getSize(),10);
-        tearDown();
-
-    }
-
-    public void testPoolThreads20Connections10Fair() throws Exception {
-        System.out.println("[testPoolThreads20Connections10Fair] Starting fairness - Tomcat JDBC - Fair");
-        init();
-        this.datasource.getPoolProperties().setMaxActive(10);
-        this.datasource.getPoolProperties().setFairQueue(true);
-        this.threadcount = 20;
-        this.transferProperties();
-        this.datasource.getConnection().close();
-        latch = new CountDownLatch(threadcount);
-        long start = System.currentTimeMillis();
-        TestThread[] threads = new TestThread[threadcount];
-        for (int i=0; i<threadcount; i++) {
-            threads[i] = new TestThread();
-            threads[i].setName("tomcat-pool-"+i);
-            threads[i].d = this.datasource;
-            
-        }
-        for (int i=0; i<threadcount; i++) {
-            threads[i].start();
-        }
-        if (!latch.await(complete+1000,TimeUnit.MILLISECONDS)) {
-            System.out.println("Latch timed out.");
-        }
-        this.run = false;
-        long delta = System.currentTimeMillis() - start;
-        printThreadResults(threads,"testPoolThreads20Connections10Fair",this.datasource.getSize(),10);
-        tearDown();
-    }
-    public void testPoolThreads20Connections10FairAsync() throws Exception {
-        System.out.println("[testPoolThreads20Connections10FairAsync] Starting fairness - Tomcat JDBC - Fair - Async");
-        init();
-        this.datasource.getPoolProperties().setMaxActive(10);
-        this.datasource.getPoolProperties().setFairQueue(true);
-        this.threadcount = 20;
-        this.transferProperties();
-        this.datasource.getConnection().close();
-        latch = new CountDownLatch(threadcount);
-        long start = System.currentTimeMillis();
-        TestThread[] threads = new TestThread[threadcount];
-        for (int i=0; i<threadcount; i++) {
-            threads[i] = new TestThread();
-            threads[i].setName("tomcat-pool-"+i);
-            threads[i].async = true;
-            threads[i].d = this.datasource;
-            
-        }
-        for (int i=0; i<threadcount; i++) {
-            threads[i].start();
-        }
-        if (!latch.await(complete+1000,TimeUnit.MILLISECONDS)) {
-            System.out.println("Latch timed out.");
-        }
-        this.run = false;
-        long delta = System.currentTimeMillis() - start;
-        printThreadResults(threads,"testPoolThreads20Connections10FairAsync",this.datasource.getSize(),10);
-        tearDown();
-    }
-    
-//    public void testC3P0Threads20Connections10() throws Exception {
-//        System.out.println("[testC3P0Threads20Connections10] Starting fairness - C3P0");
-//        init();
-//        this.datasource.getPoolProperties().setMaxActive(10);
-//        this.datasource.getPoolProperties().setFairQueue(false);
-//        this.threadcount = 20;
-//        this.transferPropertiesToC3P0();
-//        this.datasource.getConnection().close();
-//        latch = new CountDownLatch(threadcount);
-//        long start = System.currentTimeMillis();
-//        TestThread[] threads = new TestThread[threadcount];
-//        for (int i=0; i<threadcount; i++) {
-//            threads[i] = new TestThread();
-//            threads[i].setName("tomcat-pool-"+i);
-//            threads[i].d = this.c3p0Datasource;
-//            
-//        }
-//        for (int i=0; i<threadcount; i++) {
-//            threads[i].start();
-//        }
-//        if (!latch.await(complete+1000,TimeUnit.MILLISECONDS)) {
-//            System.out.println("Latch timed out.");
-//        }
-//        this.run = false;
-//        long delta = System.currentTimeMillis() - start;
-//        printThreadResults(threads,"testC3P0Threads20Connections10",c3p0Datasource.getNumConnectionsAllUsers(),10);
-//        tearDown();
-//
-//    }
-
-    
-    public class TestThread extends Thread {
-        protected DataSource d;
-        protected String query = null;
-        protected long sleep = 10;
-        protected boolean async = false;
-        long minwait = Long.MAX_VALUE, maxwait = -1, totalwait=0, totalcmax=0, cmax = -1, nroffetch = 0, totalruntime = 0;
-        @Override
-        public void run() {
-            try {
-                long now = System.currentTimeMillis();
-                while (FairnessTest.this.run) {
-                    if ((System.currentTimeMillis()-now)>=FairnessTest.this.complete) break;
-                    long start = System.nanoTime();
-                    Connection con = null;
-                    try {
-                        if (async) {
-                            Future<Connection> cf = ((DataSourceProxy)d).getConnectionAsync();
-                            con  = cf.get();
-                        } else {
-                            con = d.getConnection();
-                        }
-                        long delta = System.nanoTime() - start;
-                        totalwait += delta;
-                        maxwait = Math.max(delta, maxwait);
-                        minwait = Math.min(delta, minwait);
-                        nroffetch++;
-                        if (query!=null) {
-                            Statement st = con.createStatement();
-                            ResultSet rs = st.executeQuery(query);
-                            while (rs.next()) {
-                            }
-                            rs.close();
-                            st.close();
-                        }
-                        try { 
-                            if (FairnessTest.this.sleep>0) sleep(FairnessTest.this.sleep); 
-                        } catch (InterruptedException x) {
-                            interrupted();
-                        }
-                    } finally {
-                        long cstart = System.nanoTime();
-                        if (con!=null) try {con.close();}catch(Exception x) {x.printStackTrace();}
-                        long cdelta = System.nanoTime() - cstart;
-                        totalcmax += cdelta;
-                        cmax = Math.max(cdelta, cmax);
-                    }
-                    totalruntime+=(System.nanoTime()-start);
-                }
-
-            } catch (Exception x) {
-                x.printStackTrace();
-            } finally {
-                FairnessTest.this.latch.countDown();
-            }
-            if (System.getProperty("print-thread-stats")!=null) {
-                System.out.println("["+getName()+"] "+
-                    "\n\tMax time to retrieve connection:"+(((float)maxwait)/1000f/1000f)+" ms."+
-                    "\n\tTotal time to retrieve connection:"+(((float)totalwait)/1000f/1000f)+" ms."+
-                    "\n\tAverage time to retrieve connection:"+(((float)totalwait)/1000f/1000f)/(float)nroffetch+" ms."+
-                    "\n\tMax time to close connection:"+(((float)cmax)/1000f/1000f)+" ms."+
-                    "\n\tTotal time to close connection:"+(((float)totalcmax)/1000f/1000f)+" ms."+
-                    "\n\tAverage time to close connection:"+(((float)totalcmax)/1000f/1000f)/(float)nroffetch+" ms."+
-                    "\n\tRun time:"+(((float)totalruntime)/1000f/1000f)+" ms."+
-                    "\n\tNr of fetch:"+nroffetch);
-            }
-        }
-    }
-}
-
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/JmxPasswordTest.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/JmxPasswordTest.java
deleted file mode 100644 (file)
index 5c63f70..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.lang.management.ManagementFactory;
-import java.util.Hashtable;
-import java.util.Properties;
-
-import javax.management.JMX;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-
-import org.apache.tomcat.jdbc.pool.ConnectionPool;
-import org.apache.tomcat.jdbc.pool.PoolUtilities;
-import org.apache.tomcat.jdbc.pool.jmx.ConnectionPoolMBean;
-import org.apache.tomcat.jdbc.test.driver.Driver;
-
-public class JmxPasswordTest extends DefaultTestCase{
-    public static final String password = "password";
-    public static final String username = "username";
-    public static ObjectName oname = null;
-    
-    public JmxPasswordTest(String s) {
-        super(s);
-    }
-    
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        this.datasource.setDriverClassName(Driver.class.getName());
-        this.datasource.setUrl("jdbc:tomcat:test");
-        this.datasource.setPassword(password);
-        this.datasource.setUsername(username);
-        this.datasource.getConnection().close();
-        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
-        String domain = "tomcat.jdbc";
-        Hashtable<String,String> properties = new Hashtable<String,String>();
-        properties.put("type", "ConnectionPool");
-        properties.put("class", this.getClass().getName());
-        oname = new ObjectName(domain,properties);
-        ConnectionPool pool = datasource.createPool();
-        org.apache.tomcat.jdbc.pool.jmx.ConnectionPool jmxPool = new org.apache.tomcat.jdbc.pool.jmx.ConnectionPool(pool);
-        mbs.registerMBean(jmxPool, oname);
-        
-    }
-    
-    public void testPassword() throws Exception {
-        assertEquals("Passwords should match when not using JMX.",password,datasource.getPoolProperties().getPassword());
-        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
-        ConnectionPoolMBean mbean = JMX.newMBeanProxy(mbs, oname, ConnectionPoolMBean.class);
-        String jmxPassword = mbean.getPassword();
-        Properties jmxProperties = mbean.getDbProperties();
-        assertFalse("Passwords should not match.", password.equals(jmxPassword));
-        assertFalse("Password property should be missing", jmxProperties.containsKey(PoolUtilities.PROP_PASSWORD));
-    }
-    
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/SimplePOJOAsyncExample.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/SimplePOJOAsyncExample.java
deleted file mode 100644 (file)
index c3cd071..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.ResultSet;
-import java.sql.Statement;
-import java.util.concurrent.Future;
-
-import org.apache.tomcat.jdbc.pool.DataSource;
-import org.apache.tomcat.jdbc.pool.PoolConfiguration;
-import org.apache.tomcat.jdbc.pool.PoolProperties;
-
-public class SimplePOJOAsyncExample {
-
-    public static void main(String[] args) throws Exception {
-        PoolConfiguration p = new PoolProperties();
-        p.setFairQueue(true);
-        p.setUrl("jdbc:mysql://localhost:3306/mysql?autoReconnect=true");
-        p.setDriverClassName("com.mysql.jdbc.Driver");
-        p.setUsername("root");
-        p.setPassword("password");
-        p.setJmxEnabled(true);
-        p.setTestWhileIdle(false);
-        p.setTestOnBorrow(true);
-        p.setValidationQuery("SELECT 1");
-        p.setTestOnReturn(false);
-        p.setValidationInterval(30000);
-        p.setTimeBetweenEvictionRunsMillis(30000);
-        p.setMaxActive(100);
-        p.setInitialSize(10);
-        p.setMaxWait(10000);
-        p.setRemoveAbandonedTimeout(60);
-        p.setMinEvictableIdleTimeMillis(30000);
-        p.setMinIdle(10);
-        p.setLogAbandoned(true);
-        p.setRemoveAbandoned(true);
-        p.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");
-        DataSource datasource = new DataSource();
-        datasource.setPoolProperties(p); 
-        
-        Connection con = null;
-        try {            
-          Future<Connection> future = datasource.getConnectionAsync();
-          while (!future.isDone()) {
-              System.out.println("Connection is not yet available. Do some background work");
-              try {
-                  Thread.sleep(100); //simulate work
-              }catch (InterruptedException x) {
-                  Thread.interrupted();
-              }
-          }
-          con = future.get(); //should return instantly 
-          Statement st = con.createStatement();
-          ResultSet rs = st.executeQuery("select * from user");
-          int cnt = 1;
-          while (rs.next()) {
-              System.out.println((cnt++)+". Host:" +rs.getString("Host")+" User:"+rs.getString("User")+" Password:"+rs.getString("Password"));
-          }
-          rs.close();
-          st.close();
-        } finally {
-          if (con!=null) try {con.close();}catch (Exception ignore) {}
-        }  
-    }
-
-}
\ No newline at end of file
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/SimplePOJOExample.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/SimplePOJOExample.java
deleted file mode 100644 (file)
index 5036857..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.ResultSet;
-import java.sql.Statement;
-
-import org.apache.tomcat.jdbc.pool.DataSource;
-import org.apache.tomcat.jdbc.pool.PoolConfiguration;
-import org.apache.tomcat.jdbc.pool.PoolProperties;
-
-public class SimplePOJOExample {
-
-    public static void main(String[] args) throws Exception {
-        PoolConfiguration p = new PoolProperties();
-        p.setUrl("jdbc:mysql://localhost:3306/mysql?autoReconnect=true");
-        p.setDriverClassName("com.mysql.jdbc.Driver");
-        p.setUsername("root");
-        p.setPassword("password");
-        p.setJmxEnabled(true);
-        p.setTestWhileIdle(false);
-        p.setTestOnBorrow(true);
-        p.setValidationQuery("SELECT 1");
-        p.setTestOnReturn(false);
-        p.setValidationInterval(30000);
-        p.setTimeBetweenEvictionRunsMillis(30000);
-        p.setMaxActive(100);
-        p.setInitialSize(10);
-        p.setMaxWait(10000);
-        p.setRemoveAbandonedTimeout(60);
-        p.setMinEvictableIdleTimeMillis(30000);
-        p.setMinIdle(10);
-        p.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");
-        p.setLogAbandoned(true);
-        p.setRemoveAbandoned(true);
-        DataSource datasource = new DataSource();
-        datasource.setPoolProperties(p); 
-        
-        Connection con = null;
-        try {            
-          con = datasource.getConnection();
-          Statement st = con.createStatement();
-          ResultSet rs = st.executeQuery("select * from user");
-          int cnt = 1;
-          while (rs.next()) {
-              System.out.println((cnt++)+". Host:" +rs.getString("Host")+" User:"+rs.getString("User")+" Password:"+rs.getString("Password"));
-          }
-          rs.close();
-          st.close();
-        } finally {
-          if (con!=null) try {con.close();}catch (Exception ignore) {}
-        }  
-    }
-
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/StarvationTest.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/StarvationTest.java
deleted file mode 100644 (file)
index 8013ba5..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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.SQLException;
-
-/**
- * If a connection is abandoned and closed, 
- * then that should free up a spot in the pool, and other threads 
- * that are waiting should not time out and throw an error but be 
- * able to acquire a connection, since one was just released.
- * @author fhanik
- *
- */
-public class StarvationTest extends DefaultTestCase {
-
-    public StarvationTest(String name) {
-        super(name);
-    }
-    
-    private void config() {
-        datasource.getPoolProperties().setMaxActive(1);
-        datasource.getPoolProperties().setMaxIdle(1);
-        datasource.getPoolProperties().setInitialSize(1);
-        datasource.getPoolProperties().setRemoveAbandoned(true);
-        datasource.getPoolProperties().setRemoveAbandonedTimeout(5);
-        datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(500);
-        datasource.getPoolProperties().setMaxWait(10000);
-        datasource.getPoolProperties().setLogAbandoned(true);
-    }
-    
-//    public void testDBCPConnectionStarvation() throws Exception {
-//        init();
-//        config();
-//        this.transferProperties();
-//        this.tDatasource.getConnection().close();
-//        javax.sql.DataSource datasource = this.tDatasource;
-//        Connection con1 = datasource.getConnection(); 
-//        Connection con2 = null;
-//        try {
-//            con2 = datasource.getConnection();
-//            try {
-//                con2.setCatalog("mysql");//make sure connection is valid
-//            }catch (SQLException x) {
-//                assertFalse("2nd Connection is not valid:"+x.getMessage(),true);
-//            }
-//            assertTrue("Connection 1 should be closed.",con1.isClosed()); //first connection should be closed
-//        }catch (Exception x) {
-//            assertFalse("Connection got starved:"+x.getMessage(),true);
-//        }finally {
-//            if (con2!=null) con2.close();
-//        }
-//
-//    }
-    
-    public void testConnectionStarvation() throws Exception {
-        init();
-        config();
-        Connection con1 = datasource.getConnection(); 
-        Connection con2 = null;
-        try {
-            con2 = datasource.getConnection();
-            try {
-                con2.setCatalog("mysql");//make sure connection is valid
-            }catch (SQLException x) {
-                assertFalse("2nd Connection is not valid:"+x.getMessage(),true);
-            }
-            assertTrue("Connection 1 should be closed.",con1.isClosed()); //first connection should be closed
-        }catch (Exception x) {
-            assertFalse("Connection got starved:"+x.getMessage(),true);
-        }finally {
-            if (con2!=null) con2.close();
-        }
-    }
-
-    public void testFairConnectionStarvation() throws Exception {
-        init();
-        config();
-        datasource.getPoolProperties().setFairQueue(true);
-        Connection con1 = datasource.getConnection(); 
-        Connection con2 = null;
-        try {
-            con2 = datasource.getConnection();
-            try {
-                con2.setCatalog("mysql");//make sure connection is valid
-            }catch (SQLException x) {
-                assertFalse("2nd Connection is not valid:"+x.getMessage(),true);
-            }
-            assertTrue("Connection 1 should be closed.",con1.isClosed()); //first connection should be closed
-        }catch (Exception x) {
-            assertFalse("Connection got starved:"+x.getMessage(),true);
-        }finally {
-            if (con2!=null) con2.close();
-        }
-    }
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/StatementFinalizerTest.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/StatementFinalizerTest.java
deleted file mode 100644 (file)
index b2570a5..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- *  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.Statement;
-
-import org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;
-
-public class StatementFinalizerTest extends DefaultTestCase {
-
-    public StatementFinalizerTest(String name) {
-        super(name);
-    }
-    
-    public void testStatementFinalization() throws Exception {
-        this.init();
-        datasource.setJdbcInterceptors(StatementFinalizer.class.getName());
-        Connection con = datasource.getConnection();
-        Statement st = con.createStatement();
-        assertFalse("Statement should not be closed.",st.isClosed());
-        con.close();
-        assertTrue("Statement should be closed.",st.isClosed());
-    }
-
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestAsyncQueue.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestAsyncQueue.java
deleted file mode 100644 (file)
index 7f21c52..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- *  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.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-import org.apache.tomcat.jdbc.pool.FairBlockingQueue;
-
-import junit.framework.TestCase;
-
-public class TestAsyncQueue extends TestCase {
-    protected FairBlockingQueue<Object> queue = null;
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        this.queue = new FairBlockingQueue<Object>();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        this.queue = null;
-        super.tearDown();
-    }
-    
-    
-    public void testAsyncPoll1() throws Exception {
-        Object item = new Object();
-        queue.offer(item);
-        Future<Object> future = queue.pollAsync();
-        assertEquals(future.get(),item);
-    }
-
-    public void testAsyncPoll2() throws Exception {
-        Object item = new Object();
-        OfferThread thread = new OfferThread(item,5000);
-        thread.start();
-        Future<Object> future = queue.pollAsync();
-        try {
-            future.get(2000, TimeUnit.MILLISECONDS);
-            assertFalse("Request should have timed out",true);
-        }catch (TimeoutException x) {
-            assertTrue("Request timed out properly",true);
-        }catch (Exception x) {
-            assertTrue("Request threw an error",false);
-            x.printStackTrace();
-        }
-        assertEquals(future.get(),item);
-    }
-
-    protected class OfferThread extends Thread {
-        Object item = null;
-        long delay = 5000;
-        volatile boolean offered = false;
-        public OfferThread(Object i, long d) {
-            this.item = i;
-            this.delay = d;
-            this.setDaemon(false);
-            this.setName(TestAsyncQueue.class.getName()+"-OfferThread");
-        }
-        @Override
-        public void run() {
-            try {
-                sleep(delay);
-            }catch (Exception ignore){}
-            offered = true;
-            TestAsyncQueue.this.queue.offer(item);
-        }
-    }
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestConcurrency.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestConcurrency.java
deleted file mode 100644 (file)
index 6a22d0a..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- *  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.util.concurrent.atomic.AtomicInteger;
-
-import org.apache.tomcat.jdbc.pool.DataSource;
-import org.apache.tomcat.jdbc.test.driver.Driver;
-
-public class TestConcurrency extends DefaultTestCase {
-
-    public static final  boolean debug = Boolean.getBoolean("jdbc.debug");
-    
-    protected volatile DataSource ds = null;
-    
-    public TestConcurrency(String name) {
-        super(name);
-    }
-    
-    @Override
-    public void setUp() {
-        // TODO Auto-generated method stub
-        ds = createDefaultDataSource();
-        ds.getPoolProperties().setDriverClassName(Driver.class.getName());
-        ds.getPoolProperties().setUrl(Driver.url);
-        ds.getPoolProperties().setInitialSize(0);
-        ds.getPoolProperties().setMaxIdle(0);
-        ds.getPoolProperties().setMinIdle(0);
-        ds.getPoolProperties().setMaxActive(10);
-        ds.getPoolProperties().setRemoveAbandoned(true);
-        ds.getPoolProperties().setLogAbandoned(true);
-        ds.getPoolProperties().setTestWhileIdle(true);
-        ds.getPoolProperties().setMinEvictableIdleTimeMillis(750);
-        ds.getPoolProperties().setTimeBetweenEvictionRunsMillis(25);
-        ds.setFairQueue(true);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        ds.close(true);
-        Driver.reset();
-        super.tearDown();
-    }
-    
-    public void testSimple() throws Exception {
-        ds.getConnection().close();
-        final int iter = 1000 * 10;
-        final AtomicInteger loopcount = new AtomicInteger(0);
-        final Runnable run = new Runnable() {
-            public void run() {
-                try {
-                    while (loopcount.incrementAndGet() < iter) {
-                        Connection con = ds.getConnection();
-                        Thread.sleep(10);
-                        con.close();
-                    }
-                }catch (Exception x) {
-                    loopcount.set(iter); //stops the test
-                    x.printStackTrace();
-                }
-            }
-        };
-        Thread[] threads = new Thread[20];
-        for (int i=0; i<threads.length; i++) {
-            threads[i] = new Thread(run);
-        }
-        for (int i=0; i<threads.length; i++) {
-            threads[i].start();
-        }
-        try {
-            while (loopcount.get()<iter) {
-                assertTrue("Size comparison(less than 11):",ds.getPool().getSize()<=10);
-                if (debug) {
-                    System.out.println("Size: "+ds.getPool().getSize());
-                    System.out.println("Used: "+ds.getPool().getActive());
-                    System.out.println("Idle: "+ds.getPool().getIdle());
-                    System.out.println("Wait: "+ds.getPool().getWaitCount());
-                }
-                Thread.sleep(250);
-            }
-        }catch (Exception x) {
-            loopcount.set(iter); //stops the test
-            x.printStackTrace();
-        }
-        for (int i=0; i<threads.length; i++) {
-            threads[i].join();
-        }
-        assertEquals("Size comparison:",10, ds.getPool().getSize());
-        assertEquals("Idle comparison:",10, ds.getPool().getIdle());
-        assertEquals("Used comparison:",0, ds.getPool().getActive());
-        assertEquals("Connect count",10,Driver.connectCount.get());
-            
-    }
-    
-    public void testBrutal() throws Exception {
-        ds.getPoolProperties().setRemoveAbandoned(false);
-        ds.getPoolProperties().setRemoveAbandonedTimeout(1);
-        ds.getPoolProperties().setMinEvictableIdleTimeMillis(100);
-        ds.getPoolProperties().setTimeBetweenEvictionRunsMillis(10);
-        ds.getConnection().close();
-        final int iter = 100000 * 10;
-        final AtomicInteger loopcount = new AtomicInteger(0);
-        final Runnable run = new Runnable() {
-            public void run() {
-                try {
-                    while (loopcount.incrementAndGet() < iter) {
-                        Connection con = ds.getConnection();
-                        con.close();
-                    }
-                }catch (Exception x) {
-                    loopcount.set(iter); //stops the test
-                    x.printStackTrace();
-                }
-            }
-        };
-        Thread[] threads = new Thread[20];
-        for (int i=0; i<threads.length; i++) {
-            threads[i] = new Thread(run);
-        }
-        for (int i=0; i<threads.length; i++) {
-            threads[i].start();
-        }
-        try {
-            while (loopcount.get()<iter) {
-                assertTrue("Size comparison(less than 11):",ds.getPool().getSize()<=10);
-                ds.getPool().testAllIdle();
-                ds.getPool().checkAbandoned();
-                ds.getPool().checkIdle();
-            }
-        }catch (Exception x) {
-            loopcount.set(iter); //stops the test
-            x.printStackTrace();
-        }
-        for (int i=0; i<threads.length; i++) {
-            threads[i].join();
-        }
-        System.out.println("Connect count:"+Driver.connectCount.get());
-        System.out.println("DisConnect count:"+Driver.disconnectCount.get());
-        assertEquals("Size comparison:",10, ds.getPool().getSize());
-        assertEquals("Idle comparison:",10, ds.getPool().getIdle());
-        assertEquals("Used comparison:",0, ds.getPool().getActive());
-        assertEquals("Connect count",10,Driver.connectCount.get());
-    }
-
-    public void testBrutalNonFair() throws Exception {
-        ds.getPoolProperties().setRemoveAbandoned(false);
-        ds.getPoolProperties().setRemoveAbandonedTimeout(1);
-        ds.getPoolProperties().setMinEvictableIdleTimeMillis(100);
-        ds.getPoolProperties().setTimeBetweenEvictionRunsMillis(10);
-        ds.getConnection().close();
-        final int iter = 100000 * 10;
-        final AtomicInteger loopcount = new AtomicInteger(0);
-        final Runnable run = new Runnable() {
-            public void run() {
-                try {
-                    while (loopcount.incrementAndGet() < iter) {
-                        Connection con = ds.getConnection();
-                        con.close();
-                    }
-                }catch (Exception x) {
-                    loopcount.set(iter); //stops the test
-                    x.printStackTrace();
-                }
-            }
-        };
-        Thread[] threads = new Thread[20];
-        for (int i=0; i<threads.length; i++) {
-            threads[i] = new Thread(run);
-        }
-        for (int i=0; i<threads.length; i++) {
-            threads[i].start();
-        }
-        try {
-            while (loopcount.get()<iter) {
-                assertTrue("Size comparison(less than 11):",ds.getPool().getSize()<=10);
-                ds.getPool().testAllIdle();
-                ds.getPool().checkAbandoned();
-                ds.getPool().checkIdle();
-            }
-        }catch (Exception x) {
-            loopcount.set(iter); //stops the test
-            x.printStackTrace();
-        }
-        for (int i=0; i<threads.length; i++) {
-            threads[i].join();
-        }
-        System.out.println("Connect count:"+Driver.connectCount.get());
-        System.out.println("DisConnect count:"+Driver.disconnectCount.get());
-        assertEquals("Size comparison:",10, ds.getPool().getSize());
-        assertEquals("Idle comparison:",10, ds.getPool().getIdle());
-        assertEquals("Used comparison:",0, ds.getPool().getActive());
-        assertEquals("Connect count",10,Driver.connectCount.get());
-    }
-    
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestConnectionState.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestConnectionState.java
deleted file mode 100644 (file)
index 8ed9bb2..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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 org.apache.tomcat.jdbc.pool.DataSourceProxy;
-import org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;
-
-public class TestConnectionState extends DefaultTestCase {
-
-    public TestConnectionState(String name) {
-        super(name);
-    }
-
-    public void testAutoCommitFalse() throws Exception {
-        DataSourceProxy d1 = this.createDefaultDataSource();
-        d1.setMaxActive(1);
-        d1.setMinIdle(1);
-        d1.setMaxIdle(1);
-        d1.setJdbcInterceptors(ConnectionState.class.getName());
-        d1.setDefaultAutoCommit(Boolean.FALSE);
-        Connection c1 = d1.getConnection();
-        assertFalse("Auto commit should be false",c1.getAutoCommit());
-        c1.setAutoCommit(true);
-        assertTrue("Auto commit should be true",c1.getAutoCommit());
-        c1.close();
-        c1 = d1.getConnection();
-        assertFalse("Auto commit should be false for a reused connection",c1.getAutoCommit());
-        d1.close(true);
-        assertTrue("Connection should be closed",c1.isClosed());
-    }
-    
-    public void testAutoCommitTrue() throws Exception {
-        DataSourceProxy d1 = this.createDefaultDataSource();
-        d1.setMaxActive(1);
-        d1.setJdbcInterceptors(ConnectionState.class.getName());
-        d1.setDefaultAutoCommit(Boolean.TRUE);
-        d1.setMinIdle(1);
-        Connection c1 = d1.getConnection();
-        assertTrue("Auto commit should be true",c1.getAutoCommit());
-        c1.setAutoCommit(false);
-        assertFalse("Auto commit should be false",c1.getAutoCommit());
-        c1.close();
-        c1 = d1.getConnection();
-        assertTrue("Auto commit should be true for a reused connection",c1.getAutoCommit());
-    }
-    
-    public void testDefaultCatalog() throws Exception {
-        DataSourceProxy d1 = this.createDefaultDataSource();
-        d1.setMaxActive(1);
-        d1.setJdbcInterceptors(ConnectionState.class.getName());
-        d1.setDefaultCatalog("information_schema");
-        d1.setMinIdle(1);
-        Connection c1 = d1.getConnection();
-        assertEquals("Catalog should be information_schema",c1.getCatalog(),"information_schema");
-        c1.close();
-        c1 = d1.getConnection();
-        assertEquals("Catalog should be information_schema",c1.getCatalog(),"information_schema");
-        c1.setCatalog("mysql");
-        assertEquals("Catalog should be information_schema",c1.getCatalog(),"mysql");
-        c1.close();
-        c1 = d1.getConnection();
-        assertEquals("Catalog should be information_schema",c1.getCatalog(),"information_schema");
-    }
-
-
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestException.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestException.java
deleted file mode 100644 (file)
index 0a8df77..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- *  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 org.apache.tomcat.jdbc.pool.ConnectionPool;
-import org.apache.tomcat.jdbc.pool.JdbcInterceptor;
-import org.apache.tomcat.jdbc.pool.PooledConnection;
-
-public class TestException extends DefaultTestCase {
-
-    public TestException(String name) {
-        super(name);
-    }
-    
-    public void testException() throws Exception {
-        init();
-        datasource.getPoolProperties().setJdbcInterceptors(TestInterceptor.class.getName());
-        Connection con = datasource.getConnection();
-        try {
-            con.createStatement();
-        }catch (Exception x) {
-            
-        }
-    }
-    
-    
-    public static class TestInterceptor extends JdbcInterceptor {
-
-        @Override
-        public void reset(ConnectionPool parent, PooledConnection con) {
-            // TODO Auto-generated method stub
-            
-        }
-
-    
-    }
-
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestGCClose.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestGCClose.java
deleted file mode 100644 (file)
index 7bb8157..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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;
-
-/**
- * @author Filip Hanik
- * @version 1.0
- */
-public class TestGCClose extends DefaultTestCase {
-    public TestGCClose(String name) {
-        super(name);
-    }
-    
-    public void testGCStop() throws Exception {
-        init();
-        datasource.getConnection();
-        System.out.println("Got a connection, but didn't return it");
-        tearDown();
-        Thread.sleep(20000);
-    }
-    
-    public void testClose() throws Exception {
-        init();
-        datasource.getConnection();
-        System.out.println("Got a connection, but didn't return it");
-        datasource.close(true);
-        Thread.sleep(20000);
-    }
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestGetConnection.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestGetConnection.java
deleted file mode 100644 (file)
index 1d890b4..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- *  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 javax.sql.PooledConnection;
-
-public class TestGetConnection extends DefaultTestCase {
-
-    public TestGetConnection(String name) {
-        super(name);
-    }
-    
-    public void testGetConnection() throws Exception {
-        this.init();
-        Connection con = this.datasource.getConnection();
-        assertTrue("Connection should implement javax.sql.PooledConnection",con instanceof PooledConnection);
-        Connection actual = ((PooledConnection)con).getConnection();
-        assertNotNull("Connection delegate should not be null.",actual);
-        System.out.println("Actual connection:"+actual.getClass().getName());
-        
-    }
-
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestInterceptorShortName.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestInterceptorShortName.java
deleted file mode 100644 (file)
index 1641bb8..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- *  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 org.apache.tomcat.jdbc.pool.interceptor.TestInterceptor;
-
-public class TestInterceptorShortName extends DefaultTestCase {
-
-    public TestInterceptorShortName(String name) {
-        super(name);
-    }
-    
-    public void testShortInterceptor() throws Exception {
-        this.datasource = this.createDefaultDataSource();
-        this.datasource.setJdbcInterceptors("TestInterceptor");
-        this.datasource.setMaxActive(1);
-        Connection con = this.datasource.getConnection();
-        assertTrue("Pool should have been started.",TestInterceptor.poolstarted);
-        assertEquals("Only one interceptor should have been called setProperties",1,TestInterceptor.instancecount.get());
-        con.close();
-        this.datasource.close();
-        assertTrue("Pool should have been closed.",TestInterceptor.poolclosed);
-    }
-
-
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestSizePreservation.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestSizePreservation.java
deleted file mode 100644 (file)
index 183532e..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- *  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.util.concurrent.atomic.AtomicInteger;
-
-import junit.framework.TestCase;
-
-import org.apache.tomcat.jdbc.pool.DataSource;
-import org.apache.tomcat.jdbc.pool.PoolConfiguration;
-import org.apache.tomcat.jdbc.test.driver.Driver;
-/**
- * 
- * @author Jeremy Norris
- * https://issues.apache.org/bugzilla/show_bug.cgi?id=50613
- *
- */
-public class TestSizePreservation extends TestCase {
-
-    protected volatile DataSource ds = null;
-
-    public TestSizePreservation() {
-    }
-
-    private void initSimplePoolProperties() {
-        PoolConfiguration p = new DefaultProperties();
-        ds = new org.apache.tomcat.jdbc.pool.DataSource();
-        ds.setPoolProperties(p);
-
-        ds.getPoolProperties().setDriverClassName(Driver.class.getName());
-        ds.getPoolProperties().setUrl(Driver.url);
-        ds.getPoolProperties().setFairQueue(true);
-        ds.getPoolProperties().setJmxEnabled(false);
-        ds.getPoolProperties().setTestWhileIdle(true);
-        ds.getPoolProperties().setTestOnBorrow(false);
-        ds.getPoolProperties().setTestOnReturn(false);
-        ds.getPoolProperties().setValidationInterval(30000);
-        ds.getPoolProperties().setTimeBetweenEvictionRunsMillis(30000);
-        ds.getPoolProperties().setInitialSize(100);
-        ds.getPoolProperties().setMaxActive(100);
-        ds.getPoolProperties().setMinIdle(0);
-        ds.getPoolProperties().setMaxIdle(0);
-        ds.getPoolProperties().setMaxWait(10000);
-        ds.getPoolProperties().setRemoveAbandonedTimeout(10);
-        ds.getPoolProperties().setMinEvictableIdleTimeMillis(10000);
-        ds.getPoolProperties().setLogAbandoned(false);
-        ds.getPoolProperties().setRemoveAbandoned(false);
-        ds.getPoolProperties().setUseLock(true);
-    }
-
-    private void initEvictingPool() {
-        initSimplePoolProperties();
-        ds.getPoolProperties().setTimeBetweenEvictionRunsMillis(25);
-        ds.getPoolProperties().setMinEvictableIdleTimeMillis(750);
-        ds.getPoolProperties().setRemoveAbandoned(true);
-        ds.getPoolProperties().setRemoveAbandonedTimeout(1);
-    }
-
-    public void testSimple() throws Exception {
-        initSimplePoolProperties();
-        common();
-        ds.close(true);
-        Driver.reset();
-    }
-
-    public void testEvicting() throws Exception {
-        initEvictingPool();
-        common();
-        ds.close(true);
-        Driver.reset();
-    }
-
-    private void common() throws Exception {
-        ds.getConnection().close();
-        final int iterations = 1000;
-        final AtomicInteger loopcount = new AtomicInteger(0);
-        final Runnable run = new Runnable() {
-            public void run() {
-                try {
-                    while (loopcount.incrementAndGet() < iterations) {
-                        Connection c = ds.getConnection();
-                        Thread.sleep(1000);
-                        c.close();
-                    }
-                } catch (Exception x) {
-                    x.printStackTrace();
-                }
-            }
-        };
-        Thread[] threads = new Thread[200];
-        for (int i = 0; i < threads.length; i++) {
-            threads[i] = new Thread(run);
-        }
-        for (int i = 0; i < threads.length; i++) {
-            threads[i].start();
-        }
-        try {
-            while (loopcount.get() < iterations) {
-                Thread.sleep(250);
-            }
-        } catch (Exception x) {
-            loopcount.set(iterations); // stops the test
-            x.printStackTrace();
-        }
-        for (int i = 0; i < threads.length; i++) {
-            threads[i].join();
-        }
-        System.out.println("Pool size:"+ds.getPool().getSize());
-        assertTrue("Size validity check: ", ds.getPool().getSize() >= 0);
-    }
-
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestSlowQueryReport.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestSlowQueryReport.java
deleted file mode 100644 (file)
index 33dbec6..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * 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.lang.management.ManagementFactory;
-import java.sql.CallableStatement;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.Statement;
-import java.util.Map;
-
-import javax.management.AttributeChangeNotification;
-import javax.management.Notification;
-import javax.management.NotificationListener;
-
-import org.apache.tomcat.jdbc.pool.ConnectionPool;
-import org.apache.tomcat.jdbc.pool.interceptor.SlowQueryReport;
-import org.apache.tomcat.jdbc.pool.interceptor.SlowQueryReportJmx;
-
-public class TestSlowQueryReport extends DefaultTestCase {
-
-    public TestSlowQueryReport(String name) {
-        super(name);
-    }
-    
-    public void testSlowSql() throws Exception {
-        int count = 3;
-        this.init();
-        this.datasource.setMaxActive(1);
-        this.datasource.setJdbcInterceptors(SlowQueryReport.class.getName()+"(threshold=50)");
-        Connection con = this.datasource.getConnection();
-        String slowSql = "select count(1) from test where val1 like 'ewq%eq' and val2 = 'ew%rre' and val3 = 'sda%da' and val4 = 'dad%ada'";
-        for (int i=0; i<count; i++) {
-            Statement st = con.createStatement();
-            ResultSet rs = st.executeQuery(slowSql);
-            rs.close();
-            st.close();
-        }
-        Map<String,SlowQueryReport.QueryStats> map = SlowQueryReport.getPoolStats(datasource.getPool().getName());
-        assertNotNull(map);
-        assertEquals(1,map.size());
-        String key = map.keySet().iterator().next();
-        SlowQueryReport.QueryStats stats = map.get(key);
-        System.out.println("Stats:"+stats);
-        
-        for (int i=0; i<count; i++) {
-            PreparedStatement st = con.prepareStatement(slowSql);
-            ResultSet rs = st.executeQuery();
-            rs.close();
-            st.close();
-        }
-        System.out.println("Stats:"+stats);
-        
-        for (int i=0; i<count; i++) {
-            CallableStatement st = con.prepareCall(slowSql);
-            ResultSet rs = st.executeQuery();
-            rs.close();
-            st.close();
-        }
-        System.out.println("Stats:"+stats);
-        ConnectionPool pool = datasource.getPool();
-        con.close();
-        tearDown();
-        //make sure we actually did clean up when the pool closed
-        assertNull(SlowQueryReport.getPoolStats(pool.getName()));
-    }
-
-    public void testSlowSqlJmx() throws Exception {
-        int count = 1;
-        this.init();
-        this.datasource.setMaxActive(1);
-        this.datasource.setJdbcInterceptors(SlowQueryReportJmx.class.getName()+"(threshold=50,notifyPool=false)");
-        Connection con = this.datasource.getConnection();
-        String slowSql = "select count(1) from test where val1 like 'ewq%eq'";
-        for (int i=0; i<count; i++) {
-            Statement st = con.createStatement();
-            ResultSet rs = st.executeQuery(slowSql);
-            rs.close();
-            st.close();
-        }
-        Map<String,SlowQueryReport.QueryStats> map = SlowQueryReport.getPoolStats(datasource.getPool().getName());
-        assertNotNull(map);
-        assertEquals(1,map.size());
-        String key = map.keySet().iterator().next();
-        SlowQueryReport.QueryStats stats = map.get(key);
-        System.out.println("Stats:"+stats);
-        ClientListener listener = new ClientListener();
-        ConnectionPool pool = datasource.getPool();
-        ManagementFactory.getPlatformMBeanServer().addNotificationListener(
-                SlowQueryReportJmx.getObjectName(SlowQueryReportJmx.class, pool.getName()), 
-                listener,
-                null,
-                null);
-        
-        for (int i=0; i<count; i++) {
-            PreparedStatement st = con.prepareStatement(slowSql);
-            ResultSet rs = st.executeQuery();
-            rs.close();
-            st.close();
-        }
-        System.out.println("Stats:"+stats);
-        
-        for (int i=0; i<count; i++) {
-            CallableStatement st = con.prepareCall(slowSql);
-            ResultSet rs = st.executeQuery();
-            rs.close();
-            st.close();
-        }
-        System.out.println("Stats:"+stats);
-        assertEquals("Expecting to have received "+(2*count)+" notifications.",2*count, listener.notificationCount);
-        con.close();
-        tearDown();
-        //make sure we actually did clean up when the pool closed
-        assertNull(SlowQueryReport.getPoolStats(pool.getName()));
-    }
-
-    
-    public void testFastSql() throws Exception {
-        int count = 3;
-        this.init();
-        this.datasource.setMaxActive(1);
-        this.datasource.setJdbcInterceptors(SlowQueryReport.class.getName());
-        Connection con = this.datasource.getConnection();
-        String fastSql = this.datasource.getValidationQuery();
-        for (int i=0; i<count; i++) {
-            Statement st = con.createStatement();
-            ResultSet rs = st.executeQuery(fastSql);
-            rs.close();
-            st.close();
-        }
-        Map<String,SlowQueryReport.QueryStats> map = SlowQueryReport.getPoolStats(datasource.getPool().getName());
-        assertNotNull(map);
-        assertEquals(0,map.size());
-        ConnectionPool pool = datasource.getPool();
-        con.close();
-        tearDown();
-        assertNull(SlowQueryReport.getPoolStats(pool.getName()));
-    }    
-    
-    public void testFailedSql() throws Exception {
-        int count = 3;
-        this.init();
-        this.datasource.setMaxActive(1);
-        this.datasource.setJdbcInterceptors(SlowQueryReport.class.getName());
-        Connection con = this.datasource.getConnection();
-        String slowSql = "select 1 from non_existent";
-        int exceptionCount = 0;
-        for (int i=0; i<count; i++) {
-            Statement st = con.createStatement();
-            try {
-                ResultSet rs = st.executeQuery(slowSql);
-                rs.close();
-            }catch (Exception x) {
-                exceptionCount++;
-            }
-            st.close();
-            
-        }
-        Map<String,SlowQueryReport.QueryStats> map = SlowQueryReport.getPoolStats(datasource.getPool().getName());
-        assertNotNull(map);
-        assertEquals(1,map.size());
-        ConnectionPool pool = datasource.getPool();
-        String key = map.keySet().iterator().next();
-        SlowQueryReport.QueryStats stats = map.get(key);
-        System.out.println("Stats:"+stats);
-        con.close();
-        tearDown();
-        assertNull(SlowQueryReport.getPoolStats(pool.getName()));
-    }   
-    
-    
-    public class ClientListener implements NotificationListener {
-        volatile int notificationCount = 0;
-        public void handleNotification(Notification notification,
-                                       Object handback) {
-            notificationCount++;
-            System.out.println("\nReceived notification:");
-            System.out.println("\tClassName: " + notification.getClass().getName());
-            System.out.println("\tSource: " + notification.getSource());
-            System.out.println("\tType: " + notification.getType());
-            System.out.println("\tMessage: " + notification.getMessage());
-            if (notification instanceof AttributeChangeNotification) {
-                AttributeChangeNotification acn =
-                    (AttributeChangeNotification) notification;
-                System.out.println("\tAttributeName: " + acn.getAttributeName());
-                System.out.println("\tAttributeType: " + acn.getAttributeType());
-                System.out.println("\tNewValue: " + acn.getNewValue());
-                System.out.println("\tOldValue: " + acn.getOldValue());
-            }
-        }
-    }
-
-
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestStatementCache.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestStatementCache.java
deleted file mode 100644 (file)
index d3d5740..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * 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;
-        }
-    }
-
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestSuspectTimeout.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestSuspectTimeout.java
deleted file mode 100644 (file)
index b4b18d9..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- *  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 org.apache.tomcat.jdbc.pool.PooledConnection;
-
-
-public class TestSuspectTimeout extends DefaultTestCase {
-
-    public TestSuspectTimeout(String name) {
-        super(name);
-    }
-    
-    public void testSuspect() throws Exception {
-        this.init();
-        this.datasource.setMaxActive(100);
-        this.datasource.setMaxIdle(100);
-        this.datasource.setInitialSize(0);
-        this.datasource.getPoolProperties().setAbandonWhenPercentageFull(0);
-        this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(100);
-        this.datasource.getPoolProperties().setRemoveAbandoned(true);
-        this.datasource.getPoolProperties().setRemoveAbandonedTimeout(100);
-        this.datasource.getPoolProperties().setSuspectTimeout(1);
-        this.datasource.getPoolProperties().setLogAbandoned(true);
-        Connection con = datasource.getConnection();
-        assertEquals("Number of connections active/busy should be 1",1,datasource.getPool().getActive());
-        Thread.sleep(3000);
-        PooledConnection pcon = con.unwrap(PooledConnection.class);
-        assertTrue("Connection should be marked suspect",pcon.isSuspect());
-        con.close();
-    }
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestTimeout.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TestTimeout.java
deleted file mode 100644 (file)
index 6697e9a..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.util.concurrent.atomic.AtomicInteger;
-
-/**
- * @author Filip Hanik
- * @version 1.0
- */
-public class TestTimeout extends DefaultTestCase {
-    public TestTimeout(String name) {
-        super(name);
-    }
-
-    AtomicInteger counter = new AtomicInteger(0);
-
-    public void testCheckoutTimeout() throws Exception {
-        try {
-            init();
-            this.datasource.getPoolProperties().setTestWhileIdle(true);
-            this.datasource.getPoolProperties().setTestOnBorrow(false);
-            this.datasource.getPoolProperties().setTestOnReturn(false);
-            this.datasource.getPoolProperties().setValidationInterval(30000);
-            this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(1000);
-            this.datasource.getPoolProperties().setMaxActive(20);
-            this.datasource.getPoolProperties().setMaxWait(3000);
-            this.datasource.getPoolProperties().setRemoveAbandonedTimeout(5);
-            this.datasource.getPoolProperties().setMinEvictableIdleTimeMillis(5000);
-            this.datasource.getPoolProperties().setMinIdle(5);
-            this.datasource.getPoolProperties().setLogAbandoned(true);
-            System.out.println("About to test connection pool:"+datasource);
-            for (int i = 0; i < 21; i++) {
-                long now = System.currentTimeMillis();
-                this.datasource.getConnection();
-                long delta = System.currentTimeMillis()-now;
-                System.out.println("Got connection #"+i+" in "+delta+" ms.");
-            }
-            assertTrue(false);
-        } catch ( Exception x ) {
-            assertTrue(true);
-        }finally {
-            Thread.sleep(2000);
-            tearDown();
-        }
-    }
-
-    public void testCheckoutTimeoutFair() throws Exception {
-        try {
-            init();
-            this.datasource.getPoolProperties().setFairQueue(true);
-            this.datasource.getPoolProperties().setTestWhileIdle(true);
-            this.datasource.getPoolProperties().setTestOnBorrow(false);
-            this.datasource.getPoolProperties().setTestOnReturn(false);
-            this.datasource.getPoolProperties().setValidationInterval(30000);
-            this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(1000);
-            this.datasource.getPoolProperties().setMaxActive(20);
-            this.datasource.getPoolProperties().setMaxWait(3000);
-            this.datasource.getPoolProperties().setRemoveAbandonedTimeout(5);
-            this.datasource.getPoolProperties().setMinEvictableIdleTimeMillis(5000);
-            this.datasource.getPoolProperties().setMinIdle(5);
-            this.datasource.getPoolProperties().setLogAbandoned(true);
-            System.out.println("About to test connection pool:"+datasource);
-            for (int i = 0; i < 21; i++) {
-                long now = System.currentTimeMillis();
-                this.datasource.getConnection();
-                long delta = System.currentTimeMillis()-now;
-                System.out.println("Got connection #"+i+" in "+delta+" ms.");
-            }
-            assertTrue(false);
-        } catch ( Exception x ) {
-            assertTrue(true);
-        }finally {
-            Thread.sleep(2000);
-            tearDown();
-        }
-    }
-
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TwoDataSources.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/TwoDataSources.java
deleted file mode 100644 (file)
index 2a500e7..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- *  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;
-
-public class TwoDataSources extends DefaultTestCase {
-
-    public TwoDataSources(String name) {
-        super(name);
-    }
-    
-    public void testTwoDataSources() throws Exception {
-        org.apache.tomcat.jdbc.pool.DataSource d1 = this.createDefaultDataSource();
-        org.apache.tomcat.jdbc.pool.DataSource d2 = this.createDefaultDataSource();
-        d1.setRemoveAbandoned(true);
-        d1.setRemoveAbandonedTimeout(10);
-        d1.setTimeBetweenEvictionRunsMillis(1000);
-        d2.setRemoveAbandoned(false);
-        Connection c1 = d1.getConnection();
-        Connection c2 = d2.getConnection();
-        Thread.sleep(5000);
-        try {
-            c1.createStatement();
-            assertTrue("Connection should have been abandoned.",false);
-        }catch (Exception x) {
-            assertTrue("This is correct, c1 is abandoned",true);
-        }
-
-        try {
-            c2.createStatement();
-            assertTrue("Connection should not have been abandoned.",true);
-        }catch (Exception x) {
-            assertTrue("Connection c2 should be working",false);
-        }
-        try {
-            assertTrue("Connection should have been closed.",c1.isClosed());
-        }catch (Exception x) {
-            assertTrue("This is correct, c1 is closed",true);
-        }
-        try {
-            assertFalse("Connection c2 should not have been closed.",c2.isClosed());
-        }catch (Exception x) {
-            assertTrue("Connection c2 should be working",false);
-        }
-
-
-    }
-
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/driver/Connection.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/driver/Connection.java
deleted file mode 100644 (file)
index 8fc3888..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- *  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.driver;
-
-import java.sql.Array;
-import java.sql.Blob;
-import java.sql.CallableStatement;
-import java.sql.Clob;
-import java.sql.DatabaseMetaData;
-import java.sql.NClob;
-import java.sql.PreparedStatement;
-import java.sql.SQLClientInfoException;
-import java.sql.SQLException;
-import java.sql.SQLWarning;
-import java.sql.SQLXML;
-import java.sql.Savepoint;
-import java.sql.Statement;
-import java.sql.Struct;
-import java.util.Map;
-import java.util.Properties;
-
-import org.apache.tomcat.jdbc.pool.PooledConnection;
-
-public class Connection implements java.sql.Connection {
-    Properties info;
-    
-    public Connection(Properties info) {
-        this.info = info;
-    }
-    
-    public String getUsername() {
-        return info.getProperty(PooledConnection.PROP_USER);
-    }
-    
-    public String getPassword() {
-        return info.getProperty(PooledConnection.PROP_PASSWORD);
-    }
-    
-    public void clearWarnings() throws SQLException {
-    }
-
-    public void close() throws SQLException {
-        Driver.disconnectCount.incrementAndGet();
-    }
-
-    public void commit() throws SQLException {
-    }
-
-    public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
-        return null;
-    }
-
-    public Blob createBlob() throws SQLException {
-        return null;
-    }
-
-    public Clob createClob() throws SQLException {
-        return null;
-    }
-
-    public NClob createNClob() throws SQLException {
-        return null;
-    }
-
-    public SQLXML createSQLXML() throws SQLException {
-        return null;
-    }
-
-    public Statement createStatement() throws SQLException {
-        return new org.apache.tomcat.jdbc.test.driver.Statement();
-    }
-
-    public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
-        return new org.apache.tomcat.jdbc.test.driver.Statement();
-    }
-
-    public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
-        return new org.apache.tomcat.jdbc.test.driver.Statement();
-    }
-
-    public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
-        return null;
-    }
-
-    public boolean getAutoCommit() throws SQLException {
-        return false;
-    }
-
-    public String getCatalog() throws SQLException {
-        return null;
-    }
-
-    public Properties getClientInfo() throws SQLException {
-        return null;
-    }
-
-    public String getClientInfo(String name) throws SQLException {
-        return null;
-    }
-
-    public int getHoldability() throws SQLException {
-        return 0;
-    }
-
-    public DatabaseMetaData getMetaData() throws SQLException {
-        return null;
-    }
-
-    public int getTransactionIsolation() throws SQLException {
-        return 0;
-    }
-
-    public Map<String, Class<?>> getTypeMap() throws SQLException {
-        return null;
-    }
-
-    public SQLWarning getWarnings() throws SQLException {
-        return null;
-    }
-
-    public boolean isClosed() throws SQLException {
-        return false;
-    }
-
-    public boolean isReadOnly() throws SQLException {
-        return false;
-    }
-
-    public boolean isValid(int timeout) throws SQLException {
-        return false;
-    }
-
-    public String nativeSQL(String sql) throws SQLException {
-        return null;
-    }
-
-    public CallableStatement prepareCall(String sql) throws SQLException {
-        return new org.apache.tomcat.jdbc.test.driver.Statement();
-    }
-
-    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
-        return new org.apache.tomcat.jdbc.test.driver.Statement();
-    }
-
-    public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
-        return new org.apache.tomcat.jdbc.test.driver.Statement();
-    }
-
-    public PreparedStatement prepareStatement(String sql) throws SQLException {
-        return new org.apache.tomcat.jdbc.test.driver.Statement();
-    }
-
-    public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
-        return new org.apache.tomcat.jdbc.test.driver.Statement();
-    }
-
-    
-    public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
-        return new org.apache.tomcat.jdbc.test.driver.Statement();
-    }
-
-    public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
-        return new org.apache.tomcat.jdbc.test.driver.Statement();
-    }
-
-    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
-        return new org.apache.tomcat.jdbc.test.driver.Statement();
-    }
-
-    
-    public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
-        return new org.apache.tomcat.jdbc.test.driver.Statement();
-    }
-
-    public void releaseSavepoint(Savepoint savepoint) throws SQLException {
-    }
-
-    public void rollback() throws SQLException {
-    }
-
-    public void rollback(Savepoint savepoint) throws SQLException {
-    }
-
-    public void setAutoCommit(boolean autoCommit) throws SQLException {
-    }
-
-    public void setCatalog(String catalog) throws SQLException {
-    }
-
-    public void setClientInfo(Properties properties) throws SQLClientInfoException {
-    }
-
-    public void setClientInfo(String name, String value) throws SQLClientInfoException {
-    }
-
-    public void setHoldability(int holdability) throws SQLException {
-    }
-
-    public void setReadOnly(boolean readOnly) throws SQLException {
-    }
-
-    public Savepoint setSavepoint() throws SQLException {
-        return null;
-    }
-
-    public Savepoint setSavepoint(String name) throws SQLException {
-        return null;
-    }
-
-    public void setTransactionIsolation(int level) throws SQLException {
-    }
-
-    public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
-    }
-
-    public boolean isWrapperFor(Class<?> iface) throws SQLException {
-        return false;
-    }
-
-    public <T> T unwrap(Class<T> iface) throws SQLException {
-        return null;
-    }
-
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/driver/Driver.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/driver/Driver.java
deleted file mode 100644 (file)
index 0b3d8cd..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- *  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.driver;
-
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.DriverPropertyInfo;
-import java.sql.SQLException;
-import java.util.Properties;
-import java.util.concurrent.atomic.AtomicInteger;
-
-public class Driver implements java.sql.Driver {
-    public static final String url = "jdbc:tomcat:test";
-    public static final AtomicInteger connectCount = new AtomicInteger(0);
-    public static final AtomicInteger disconnectCount = new AtomicInteger(0);
-
-    public static void reset() {
-        connectCount.set(0);
-        disconnectCount.set(0);
-    }
-    
-    static {
-        try {
-            DriverManager.registerDriver(new Driver());
-        }catch (Exception x) {
-            x.printStackTrace();
-            throw new RuntimeException(x);
-        }
-    }
-    
-    public Driver() {
-    }
-    
-    public boolean acceptsURL(String url) throws SQLException {
-        return url!=null && url.equals(Driver.url);
-    }
-
-    public Connection connect(String url, Properties info) throws SQLException {
-        connectCount.addAndGet(1);
-        return new org.apache.tomcat.jdbc.test.driver.Connection(info);
-    }
-
-    public int getMajorVersion() {
-        return 0;
-    }
-
-    public int getMinorVersion() {
-        return 0;
-    }
-
-    public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
-        return null;
-    }
-
-    public boolean jdbcCompliant() {
-        return false;
-    }
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/driver/ResultSet.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/driver/ResultSet.java
deleted file mode 100644 (file)
index 9986c48..0000000
+++ /dev/null
@@ -1,1200 +0,0 @@
-/*
- *  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.driver;
-
-import java.io.InputStream;
-import java.io.Reader;
-import java.math.BigDecimal;
-import java.net.URL;
-import java.sql.Array;
-import java.sql.Blob;
-import java.sql.Clob;
-import java.sql.Date;
-import java.sql.NClob;
-import java.sql.Ref;
-import java.sql.ResultSetMetaData;
-import java.sql.RowId;
-import java.sql.SQLException;
-import java.sql.SQLWarning;
-import java.sql.SQLXML;
-import java.sql.Statement;
-import java.sql.Time;
-import java.sql.Timestamp;
-import java.util.Calendar;
-import java.util.Map;
-
-public class ResultSet implements java.sql.ResultSet {
-    boolean hasNext = true;
-    
-    public boolean absolute(int row) throws SQLException {
-        return false;
-    }
-
-    public void afterLast() throws SQLException {
-    }
-
-    public void beforeFirst() throws SQLException {
-    }
-
-    public void cancelRowUpdates() throws SQLException {
-    }
-
-    public void clearWarnings() throws SQLException {
-    }
-    public void close() throws SQLException {
-    }
-
-    public void deleteRow() throws SQLException {
-    }
-
-    public int findColumn(String columnLabel) throws SQLException {
-        return 0;
-    }
-
-    public boolean first() throws SQLException {
-        return hasNext;
-    }
-
-    public Array getArray(int columnIndex) throws SQLException {
-        return null;
-    }
-
-    public Array getArray(String columnLabel) throws SQLException {
-        return null;
-    }
-
-    @Override
-    public InputStream getAsciiStream(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public InputStream getAsciiStream(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public BigDecimal getBigDecimal(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public BigDecimal getBigDecimal(int columnIndex, int scale)
-            throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public BigDecimal getBigDecimal(String columnLabel, int scale)
-            throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public InputStream getBinaryStream(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public InputStream getBinaryStream(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Blob getBlob(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Blob getBlob(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public boolean getBoolean(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean getBoolean(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public byte getByte(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public byte getByte(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public byte[] getBytes(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public byte[] getBytes(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Reader getCharacterStream(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Reader getCharacterStream(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Clob getClob(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Clob getClob(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public int getConcurrency() throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public String getCursorName() throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Date getDate(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Date getDate(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Date getDate(int columnIndex, Calendar cal) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Date getDate(String columnLabel, Calendar cal) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public double getDouble(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public double getDouble(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public int getFetchDirection() throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public int getFetchSize() throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public float getFloat(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public float getFloat(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public int getHoldability() throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public int getInt(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public int getInt(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public long getLong(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public long getLong(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public ResultSetMetaData getMetaData() throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Reader getNCharacterStream(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Reader getNCharacterStream(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public NClob getNClob(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public NClob getNClob(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public String getNString(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public String getNString(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Object getObject(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Object getObject(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Object getObject(int columnIndex, Map<String, Class<?>> map)
-            throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Object getObject(String columnLabel, Map<String, Class<?>> map)
-            throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Ref getRef(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Ref getRef(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public int getRow() throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public RowId getRowId(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public RowId getRowId(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public SQLXML getSQLXML(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public SQLXML getSQLXML(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public short getShort(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public short getShort(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public Statement getStatement() throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public String getString(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public String getString(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Time getTime(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Time getTime(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Time getTime(int columnIndex, Calendar cal) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Time getTime(String columnLabel, Calendar cal) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Timestamp getTimestamp(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Timestamp getTimestamp(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Timestamp getTimestamp(int columnIndex, Calendar cal)
-            throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Timestamp getTimestamp(String columnLabel, Calendar cal)
-            throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public int getType() throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public URL getURL(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public URL getURL(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public InputStream getUnicodeStream(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public InputStream getUnicodeStream(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public SQLWarning getWarnings() throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public void insertRow() throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public boolean isAfterLast() throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean isBeforeFirst() throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean isClosed() throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean isFirst() throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean isLast() throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean last() throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public void moveToCurrentRow() throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void moveToInsertRow() throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public boolean next() throws SQLException {
-        boolean next = hasNext;
-        hasNext = false;
-        // TODO Auto-generated method stub
-        return next;
-    }
-
-    @Override
-    public boolean previous() throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public void refreshRow() throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public boolean relative(int rows) throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean rowDeleted() throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean rowInserted() throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean rowUpdated() throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public void setFetchDirection(int direction) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setFetchSize(int rows) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateArray(int columnIndex, Array x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateArray(String columnLabel, Array x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateAsciiStream(int columnIndex, InputStream x)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateAsciiStream(String columnLabel, InputStream x)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateAsciiStream(int columnIndex, InputStream x, int length)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateAsciiStream(String columnLabel, InputStream x, int length)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateAsciiStream(int columnIndex, InputStream x, long length)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateAsciiStream(String columnLabel, InputStream x, long length)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateBigDecimal(int columnIndex, BigDecimal x)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateBigDecimal(String columnLabel, BigDecimal x)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateBinaryStream(int columnIndex, InputStream x)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateBinaryStream(String columnLabel, InputStream x)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateBinaryStream(int columnIndex, InputStream x, int length)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateBinaryStream(String columnLabel, InputStream x, int length)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateBinaryStream(int columnIndex, InputStream x, long length)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateBinaryStream(String columnLabel, InputStream x,
-            long length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateBlob(int columnIndex, Blob x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateBlob(String columnLabel, Blob x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateBlob(int columnIndex, InputStream inputStream)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateBlob(String columnLabel, InputStream inputStream)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateBlob(int columnIndex, InputStream inputStream, long length)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateBlob(String columnLabel, InputStream inputStream,
-            long length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateBoolean(int columnIndex, boolean x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateBoolean(String columnLabel, boolean x)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateByte(int columnIndex, byte x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateByte(String columnLabel, byte x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateBytes(int columnIndex, byte[] x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateBytes(String columnLabel, byte[] x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateCharacterStream(int columnIndex, Reader x)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateCharacterStream(String columnLabel, Reader reader)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateCharacterStream(int columnIndex, Reader x, int length)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateCharacterStream(String columnLabel, Reader reader,
-            int length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateCharacterStream(int columnIndex, Reader x, long length)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateCharacterStream(String columnLabel, Reader reader,
-            long length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateClob(int columnIndex, Clob x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateClob(String columnLabel, Clob x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateClob(int columnIndex, Reader reader) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateClob(String columnLabel, Reader reader)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateClob(int columnIndex, Reader reader, long length)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateClob(String columnLabel, Reader reader, long length)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateDate(int columnIndex, Date x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateDate(String columnLabel, Date x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateDouble(int columnIndex, double x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateDouble(String columnLabel, double x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateFloat(int columnIndex, float x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateFloat(String columnLabel, float x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateInt(int columnIndex, int x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateInt(String columnLabel, int x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateLong(int columnIndex, long x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateLong(String columnLabel, long x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateNCharacterStream(int columnIndex, Reader x)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateNCharacterStream(String columnLabel, Reader reader)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateNCharacterStream(int columnIndex, Reader x, long length)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateNCharacterStream(String columnLabel, Reader reader,
-            long length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateNClob(int columnIndex, NClob clob) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateNClob(String columnLabel, NClob clob) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateNClob(int columnIndex, Reader reader) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateNClob(String columnLabel, Reader reader)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateNClob(int columnIndex, Reader reader, long length)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateNClob(String columnLabel, Reader reader, long length)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateNString(int columnIndex, String string)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateNString(String columnLabel, String string)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateNull(int columnIndex) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateNull(String columnLabel) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateObject(int columnIndex, Object x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateObject(String columnLabel, Object x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateObject(int columnIndex, Object x, int scaleOrLength)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateObject(String columnLabel, Object x, int scaleOrLength)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateRef(int columnIndex, Ref x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateRef(String columnLabel, Ref x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateRow() throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateRowId(int columnIndex, RowId x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateRowId(String columnLabel, RowId x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateSQLXML(int columnIndex, SQLXML xmlObject)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateSQLXML(String columnLabel, SQLXML xmlObject)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateShort(int columnIndex, short x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateShort(String columnLabel, short x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateString(int columnIndex, String x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateString(String columnLabel, String x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateTime(int columnIndex, Time x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateTime(String columnLabel, Time x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateTimestamp(int columnIndex, Timestamp x)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void updateTimestamp(String columnLabel, Timestamp x)
-            throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public boolean wasNull() throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean isWrapperFor(Class<?> iface) throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public <T> T unwrap(Class<T> iface) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-}
diff --git a/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/driver/Statement.java b/modules/jdbc-pool/test/org/apache/tomcat/jdbc/test/driver/Statement.java
deleted file mode 100644 (file)
index d7d5f9e..0000000
+++ /dev/null
@@ -1,1293 +0,0 @@
-/*
- *  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.driver;
-
-import java.io.InputStream;
-import java.io.Reader;
-import java.math.BigDecimal;
-import java.net.URL;
-import java.sql.Array;
-import java.sql.Blob;
-import java.sql.CallableStatement;
-import java.sql.Clob;
-import java.sql.Connection;
-import java.sql.Date;
-import java.sql.NClob;
-import java.sql.ParameterMetaData;
-import java.sql.Ref;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.RowId;
-import java.sql.SQLException;
-import java.sql.SQLWarning;
-import java.sql.SQLXML;
-import java.sql.Time;
-import java.sql.Timestamp;
-import java.util.Calendar;
-import java.util.Map;
-
-public class Statement implements CallableStatement {
-
-    @Override
-    public Array getArray(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Array getArray(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public BigDecimal getBigDecimal(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public BigDecimal getBigDecimal(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public BigDecimal getBigDecimal(int parameterIndex, int scale) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Blob getBlob(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Blob getBlob(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public boolean getBoolean(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean getBoolean(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public byte getByte(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public byte getByte(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public byte[] getBytes(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public byte[] getBytes(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Reader getCharacterStream(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Reader getCharacterStream(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Clob getClob(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Clob getClob(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Date getDate(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Date getDate(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Date getDate(int parameterIndex, Calendar cal) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Date getDate(String parameterName, Calendar cal) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public double getDouble(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public double getDouble(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public float getFloat(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public float getFloat(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public int getInt(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public int getInt(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public long getLong(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public long getLong(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public Reader getNCharacterStream(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Reader getNCharacterStream(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public NClob getNClob(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public NClob getNClob(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public String getNString(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public String getNString(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Object getObject(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Object getObject(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Object getObject(int parameterIndex, Map<String, Class<?>> map) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Object getObject(String parameterName, Map<String, Class<?>> map) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Ref getRef(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Ref getRef(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public RowId getRowId(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public RowId getRowId(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public SQLXML getSQLXML(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public SQLXML getSQLXML(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public short getShort(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public short getShort(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public String getString(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public String getString(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Time getTime(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Time getTime(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Time getTime(int parameterIndex, Calendar cal) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Time getTime(String parameterName, Calendar cal) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Timestamp getTimestamp(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Timestamp getTimestamp(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Timestamp getTimestamp(int parameterIndex, Calendar cal) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public Timestamp getTimestamp(String parameterName, Calendar cal) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public URL getURL(int parameterIndex) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public URL getURL(String parameterName) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void registerOutParameter(String parameterName, int sqlType) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void registerOutParameter(int parameterIndex, int sqlType, int scale) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void registerOutParameter(int parameterIndex, int sqlType, String typeName) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void registerOutParameter(String parameterName, int sqlType, int scale) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void registerOutParameter(String parameterName, int sqlType, String typeName) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setAsciiStream(String parameterName, InputStream x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setAsciiStream(String parameterName, InputStream x, int length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setAsciiStream(String parameterName, InputStream x, long length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setBinaryStream(String parameterName, InputStream x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setBinaryStream(String parameterName, InputStream x, int length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setBinaryStream(String parameterName, InputStream x, long length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setBlob(String parameterName, Blob x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setBlob(String parameterName, InputStream inputStream) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setBlob(String parameterName, InputStream inputStream, long length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setBoolean(String parameterName, boolean x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setByte(String parameterName, byte x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setBytes(String parameterName, byte[] x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setCharacterStream(String parameterName, Reader reader) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setCharacterStream(String parameterName, Reader reader, int length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setCharacterStream(String parameterName, Reader reader, long length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setClob(String parameterName, Clob x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setClob(String parameterName, Reader reader) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setClob(String parameterName, Reader reader, long length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setDate(String parameterName, Date x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setDate(String parameterName, Date x, Calendar cal) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setDouble(String parameterName, double x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setFloat(String parameterName, float x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setInt(String parameterName, int x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setLong(String parameterName, long x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setNCharacterStream(String parameterName, Reader value) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setNCharacterStream(String parameterName, Reader value, long length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setNClob(String parameterName, NClob value) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setNClob(String parameterName, Reader reader) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setNClob(String parameterName, Reader reader, long length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setNString(String parameterName, String value) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setNull(String parameterName, int sqlType) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setNull(String parameterName, int sqlType, String typeName) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setObject(String parameterName, Object x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setObject(String parameterName, Object x, int targetSqlType) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setObject(String parameterName, Object x, int targetSqlType, int scale) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setRowId(String parameterName, RowId x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setShort(String parameterName, short x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setString(String parameterName, String x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setTime(String parameterName, Time x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setTime(String parameterName, Time x, Calendar cal) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setTimestamp(String parameterName, Timestamp x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setTimestamp(String parameterName, Timestamp x, Calendar cal) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setURL(String parameterName, URL val) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public boolean wasNull() throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public void addBatch() throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void clearParameters() throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public boolean execute() throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public ResultSet executeQuery() throws SQLException {
-        // TODO Auto-generated method stub
-        return new org.apache.tomcat.jdbc.test.driver.ResultSet();
-    }
-
-    @Override
-    public int executeUpdate() throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public ResultSetMetaData getMetaData() throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public ParameterMetaData getParameterMetaData() throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public void setArray(int parameterIndex, Array x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setBlob(int parameterIndex, Blob x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setBoolean(int parameterIndex, boolean x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setByte(int parameterIndex, byte x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setBytes(int parameterIndex, byte[] x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setClob(int parameterIndex, Clob x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setClob(int parameterIndex, Reader reader) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setClob(int parameterIndex, Reader reader, long length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setDate(int parameterIndex, Date x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setDouble(int parameterIndex, double x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setFloat(int parameterIndex, float x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setInt(int parameterIndex, int x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setLong(int parameterIndex, long x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setNClob(int parameterIndex, NClob value) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setNClob(int parameterIndex, Reader reader) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setNString(int parameterIndex, String value) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setNull(int parameterIndex, int sqlType) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setObject(int parameterIndex, Object x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setRef(int parameterIndex, Ref x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setRowId(int parameterIndex, RowId x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setShort(int parameterIndex, short x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setString(int parameterIndex, String x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setTime(int parameterIndex, Time x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setURL(int parameterIndex, URL x) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void addBatch(String sql) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void cancel() throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void clearBatch() throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void clearWarnings() throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void close() throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public boolean execute(String sql) throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean execute(String sql, int autoGeneratedKeys) throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean execute(String sql, int[] columnIndexes) throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean execute(String sql, String[] columnNames) throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public int[] executeBatch() throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public ResultSet executeQuery(String sql) throws SQLException {
-        // TODO Auto-generated method stub
-        return new org.apache.tomcat.jdbc.test.driver.ResultSet();
-    }
-
-    @Override
-    public int executeUpdate(String sql) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public int executeUpdate(String sql, int[] columnIndexes) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public int executeUpdate(String sql, String[] columnNames) throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public Connection getConnection() throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public int getFetchDirection() throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public int getFetchSize() throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public ResultSet getGeneratedKeys() throws SQLException {
-        // TODO Auto-generated method stub
-        return new org.apache.tomcat.jdbc.test.driver.ResultSet();
-    }
-
-    @Override
-    public int getMaxFieldSize() throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public int getMaxRows() throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public boolean getMoreResults() throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean getMoreResults(int current) throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public int getQueryTimeout() throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public ResultSet getResultSet() throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public int getResultSetConcurrency() throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public int getResultSetHoldability() throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public int getResultSetType() throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public int getUpdateCount() throws SQLException {
-        // TODO Auto-generated method stub
-        return 0;
-    }
-
-    @Override
-    public SQLWarning getWarnings() throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @Override
-    public boolean isClosed() throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public boolean isPoolable() throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public void setCursorName(String name) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setEscapeProcessing(boolean enable) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setFetchDirection(int direction) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setFetchSize(int rows) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setMaxFieldSize(int max) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setMaxRows(int max) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setPoolable(boolean poolable) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void setQueryTimeout(int seconds) throws SQLException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public boolean isWrapperFor(Class<?> iface) throws SQLException {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    @Override
-    public <T> T unwrap(Class<T> iface) throws SQLException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-}