<property name="cometd.war" value="${tomcat.extras}/cometd.war"/>
<property name="tomcat-bayeux-samples.jar" value="${tomcat.extras}/tomcat-bayeux-samples.jar"/>
- <property name="tomcat-jdbc.jar" value="${tomcat.extras}/tomcat-jdbc.jar"/>
-
<property name="catalina-jmx-remote.jar" value="${tomcat.extras}/catalina-jmx-remote.jar"/>
<!-- Classpath -->
</echo>
</target>
- <target name="conpool">
- <mkdir dir="${tomcat.extras}"/>
- <path id="tomcat.jdbc.classpath">
- <pathelement path="${tomcat.classpath}"/>
- </path>
-
- <!-- compile org.apache.tomcat.jdbc-->
- <javac srcdir="java" destdir="${tomcat.classes}"
- debug="${compile.debug}"
- deprecation="${compile.deprecation}"
- source="${compile.source}"
- optimize="${compile.optimize}">
- <classpath refid="tomcat.jdbc.classpath"/>
- <include name="org/apache/tomcat/jdbc/**" />
- </javac>
-
- <!-- Cometd API JAR File -->
- <jar jarfile="${tomcat-jdbc.jar}">
- <fileset dir="${tomcat.classes}">
- <include name="org/apache/tomcat/jdbc/**" />
- </fileset>
- </jar>
- <!-- create checksums -->
- <checksum file="${tomcat-jdbc.jar}" forceOverwrite="yes" fileext=".md5" />
- </target>
<target name="jmx-remote" >
+++ /dev/null
-/*\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.pool;\r
-\r
-import java.lang.management.ManagementFactory;\r
-import java.lang.reflect.Constructor;\r
-import java.lang.reflect.InvocationHandler;\r
-import java.lang.reflect.Proxy;\r
-import java.sql.Connection;\r
-import java.sql.SQLException;\r
-import java.util.ConcurrentModificationException;\r
-import java.util.Iterator;\r
-import java.util.Queue;\r
-import java.util.concurrent.ArrayBlockingQueue;\r
-import java.util.concurrent.BlockingQueue;\r
-import java.util.concurrent.TimeUnit;\r
-\r
-import org.apache.juli.logging.Log;\r
-import org.apache.juli.logging.LogFactory;\r
-\r
-import org.apache.tomcat.jdbc.pool.jmx.ConnectionPoolMBean;\r
-\r
-import java.util.concurrent.atomic.AtomicInteger;\r
-\r
-import javax.management.InstanceAlreadyExistsException;\r
-import javax.management.MBeanRegistrationException;\r
-import javax.management.MBeanServer;\r
-import javax.management.MalformedObjectNameException;\r
-import javax.management.NotCompliantMBeanException;\r
-import javax.management.ObjectName;\r
-\r
-/**\r
- * @author Filip Hanik\r
- * @version 1.0\r
- */\r
-\r
-public class ConnectionPool {\r
-\r
- //logger\r
- protected static Log log = LogFactory.getLog(ConnectionPool.class);\r
-\r
- //===============================================================================\r
- // INSTANCE/QUICK ACCESS VARIABLE\r
- //===============================================================================\r
-\r
- /**\r
- * All the information about the connection pool\r
- */\r
- protected PoolProperties poolProperties;\r
-\r
- /**\r
- * Contains all the connections that are in use\r
- */\r
- protected BlockingQueue<PooledConnection> busy;\r
-\r
- /**\r
- * Contains all the idle connections\r
- */\r
- protected BlockingQueue<PooledConnection> idle;\r
-\r
- /**\r
- * The thread that is responsible for checking abandoned and idle threads\r
- */\r
- protected PoolCleaner poolCleaner;\r
-\r
- /**\r
- * Pool closed flag\r
- */\r
- protected boolean closed = false;\r
-\r
- /**\r
- * Size of the pool\r
- */\r
- protected AtomicInteger size = new AtomicInteger(0);\r
-\r
- /**\r
- * Since newProxyInstance performs the same operation, over and over\r
- * again, it is much more optimized if we simply store the constructor ourselves.\r
- */\r
- protected Constructor proxyClassConstructor;\r
-\r
-\r
- //===============================================================================\r
- // PUBLIC METHODS\r
- //===============================================================================\r
-\r
- /**\r
- * Instantiate a connection pool. This will create connections if initialSize is larger than 0\r
- * @param prop PoolProperties - all the properties for this connection pool\r
- * @throws SQLException\r
- */\r
- public ConnectionPool(PoolProperties prop) throws SQLException {\r
- //setup quick access variables and pools\r
- init(prop);\r
- }\r
-\r
- /**\r
- * Borrows a connection from the pool\r
- * @return Connection - a java.sql.Connection reflection proxy, wrapping the underlying object.\r
- * @throws SQLException\r
- */\r
- public Connection getConnection() throws SQLException {\r
- //check out a connection\r
- PooledConnection con = (PooledConnection)borrowConnection();\r
- JdbcInterceptor handler = con.getHandler();\r
- if (handler==null) {\r
- //build the proxy handler\r
- handler = new ProxyConnection(this,con);\r
- //set up the interceptor chain\r
- String[] proxies = getPoolProperties().getJdbcInterceptorsAsArray();\r
- for (int i=proxies.length-1; i>=0; i--) {\r
- try {\r
- JdbcInterceptor interceptor =\r
- (JdbcInterceptor) Class.forName(proxies[i], true,\r
- Thread.currentThread().getContextClassLoader()).newInstance();\r
- interceptor.setNext(handler);\r
- handler = interceptor;\r
- }catch(Exception x) {\r
- SQLException sx = new SQLException("Unable to instantiate interceptor chain.");\r
- sx.initCause(x);\r
- throw sx;\r
- }\r
- }\r
- //cache handler for the next iteration\r
- con.setHandler(handler);\r
- } else {\r
- JdbcInterceptor next = handler;\r
- //we have a cached handler, reset it\r
- while (next!=null) {\r
- next.reset(this, con);\r
- next = next.getNext();\r
- }\r
- }\r
-\r
- try {\r
- //cache the constructor\r
- if (proxyClassConstructor == null ) {\r
- Class proxyClass = Proxy.getProxyClass(ConnectionPool.class.getClassLoader(), new Class[] {java.sql.Connection.class});\r
- proxyClassConstructor = proxyClass.getConstructor(new Class[] { InvocationHandler.class });\r
- }\r
- //create the proxy\r
- //TODO possible optimization, keep track if this connection was returned properly, and don't generate a new facade\r
- Connection connection = (Connection)proxyClassConstructor.newInstance(new Object[] { handler });\r
- //return the connection\r
- return connection;\r
- }catch (Exception x) {\r
- throw new SQLException();\r
- }\r
- }\r
-\r
- /**\r
- * Returns the name of this pool\r
- * @return String\r
- */\r
- public String getName() {\r
- return getPoolProperties().getPoolName();\r
- }\r
-\r
- /**\r
- * Returns the pool properties associated with this connection pool\r
- * @return PoolProperties\r
- */\r
- public PoolProperties getPoolProperties() {\r
- return this.poolProperties;\r
- }\r
-\r
- /**\r
- * Returns the total size of this pool, this includes both busy and idle connections\r
- * @return int\r
- */\r
- public int getSize() {\r
- return idle.size()+busy.size();\r
- }\r
-\r
- /**\r
- * Returns the number of connections that are in use\r
- * @return int\r
- */\r
- public int getActive() {\r
- return busy.size();\r
- }\r
-\r
- public int getIdle() {\r
- return idle.size();\r
- }\r
-\r
- /**\r
- * Returns true if {@link #close close} has been called, and the connection pool is unusable\r
- * @return boolean\r
- */\r
- public boolean isClosed() {\r
- return this.closed;\r
- }\r
-\r
- @Override\r
- protected void finalize() throws Throwable {\r
- close(true);\r
- }\r
-\r
- /**\r
- * Closes the pool and all disconnects all idle connections\r
- * Active connections will be closed upon the {@link java.sql.Connection#close close} method is called\r
- * on the underlying connection instead of being returned to the pool\r
- * @param force - true to even close the active connections\r
- */\r
- protected void close(boolean force) {\r
- //are we already closed\r
- if (this.closed) return;\r
- //prevent other threads from entering\r
- this.closed = true;\r
- //stop background thread\r
- if (poolCleaner!=null) {\r
- poolCleaner.stopRunning();\r
- }\r
-\r
- /* release all idle connections */\r
- BlockingQueue<PooledConnection> pool = (idle.size()>0)?idle:(force?busy:idle);\r
- while (pool.size()>0) {\r
- try {\r
- //retrieve the next connection\r
- PooledConnection con = pool.poll(1000, TimeUnit.MILLISECONDS);\r
- //close it and retrieve the next one, if one is available\r
- while (con != null) {\r
- //close the connection\r
- if (pool==idle)\r
- release(con);\r
- else\r
- abandon(con);\r
- con = pool.poll(1000, TimeUnit.MILLISECONDS);\r
- } //while\r
- } catch (InterruptedException ex) {\r
- Thread.currentThread().interrupted();\r
- }\r
- if (pool.size()==0 && force && pool!=busy) pool = busy;\r
- }\r
- size.set(0);\r
- if (this.getPoolProperties().isJmxEnabled()) stopJmx();\r
- } //closePool\r
-\r
-\r
- //===============================================================================\r
- // PROTECTED METHODS\r
- //===============================================================================\r
- /**\r
- * Initialize the connection pool - called from the constructor\r
- * @param properties PoolProperties - properties used to initialize the pool with\r
- * @throws SQLException\r
- */\r
- protected void init (PoolProperties properties) throws SQLException {\r
- poolProperties = properties;\r
- //make space for 10 extra in case we flow over a bit\r
- busy = new ArrayBlockingQueue<PooledConnection>(properties.getMaxActive(),false);\r
- //make space for 10 extra in case we flow over a bit\r
- idle = new ArrayBlockingQueue<PooledConnection>(properties.getMaxActive(),false);\r
-\r
- //if the evictor thread is supposed to run, start it now\r
- if (properties.isPoolSweeperEnabled()) {\r
- poolCleaner = new PoolCleaner("[Pool-Cleaner]:" + properties.getName(), this, properties.getTimeBetweenEvictionRunsMillis());\r
- poolCleaner.start();\r
- } //end if\r
-\r
- if (properties.getMaxActive()<properties.getInitialSize()) {\r
- log.warn("initialSize is larger than maxActive, setting initialSize to: "+properties.getMaxActive());\r
- properties.setInitialSize(properties.getMaxActive());\r
- }\r
- if (properties.getMinIdle()>properties.getMaxActive()) {\r
- log.warn("minIdle is larger than maxActive, setting minIdle to: "+properties.getMaxActive());\r
- properties.setMinIdle(properties.getMaxActive());\r
- }\r
- if (properties.getMaxIdle()>properties.getMaxActive()) {\r
- log.warn("maxIdle is larger than maxActive, setting maxIdle to: "+properties.getMaxActive());\r
- properties.setMaxIdle(properties.getMaxActive());\r
- }\r
- if (properties.getMaxIdle()<properties.getMinIdle()) {\r
- log.warn("maxIdle is smaller than minIdle, setting maxIdle to: "+properties.getMinIdle());\r
- properties.setMaxIdle(properties.getMinIdle());\r
- }\r
-\r
-\r
- //initialize the pool with its initial set of members\r
- PooledConnection[] initialPool = new PooledConnection[poolProperties.getInitialSize()];\r
- try {\r
- for (int i = 0; i < initialPool.length; i++) {\r
- initialPool[i] = this.borrowConnection();\r
- } //for\r
-\r
- } catch (SQLException x) {\r
- close(true);\r
- throw x;\r
- } finally {\r
- //return the members as idle to the pool\r
- for (int i = 0; i < initialPool.length; i++) {\r
- if (initialPool[i] != null) {\r
- try {this.returnConnection(initialPool[i]);}catch(Exception x){}\r
- } //end if\r
- } //for\r
- } //catch\r
- if (this.getPoolProperties().isJmxEnabled()) startJmx();\r
- closed = false;\r
- }\r
-\r
-\r
-//===============================================================================\r
-// CONNECTION POOLING IMPL\r
-//===============================================================================\r
-\r
- /**\r
- * thread safe way to abandon a connection\r
- * signals a connection to be abandoned.\r
- * this will disconnect the connection, and log the stack trace if logAbanded=true\r
- * @param con PooledConnection\r
- */\r
- protected void abandon(PooledConnection con) {\r
- if (con == null)\r
- return;\r
- try {\r
- con.lock();\r
- if (getPoolProperties().isLogAbandoned()) {\r
- log.warn("Connection has been abandoned" + con + ":" +con.getStackTrace());\r
- }\r
- con.abandon();\r
- } finally {\r
- con.unlock();\r
- }\r
- }\r
-\r
- /**\r
- * thread safe way to release a connection\r
- * @param con PooledConnection\r
- */\r
- protected void release(PooledConnection con) {\r
- if (con == null)\r
- return;\r
- try {\r
- con.lock();\r
- con.release();\r
- } finally {\r
- con.unlock();\r
- }\r
- }\r
-\r
- /**\r
- * Thread safe way to retrieve a connection from the pool\r
- * @return PooledConnection\r
- * @throws SQLException\r
- */\r
- protected PooledConnection borrowConnection() throws SQLException {\r
-\r
- if (isClosed()) {\r
- throw new SQLException("Connection pool closed.");\r
- } //end if\r
-\r
- //get the current time stamp\r
- long now = System.currentTimeMillis();\r
- //see if there is one available immediately\r
- PooledConnection con = idle.poll();\r
-\r
- while (true) {\r
- if (con!=null) {\r
- PooledConnection result = borrowConnection(now, con);\r
- //validation might have failed, in which case null is returned\r
- if (result!=null) return result;\r
- }\r
- if (size.get() < getPoolProperties().getMaxActive()) {\r
- if (size.addAndGet(1) <= getPoolProperties().getMaxActive()) {\r
- return createConnection(now, con);\r
- } else {\r
- size.addAndGet(-1); //restore the value, we didn't create a connection\r
- }\r
- } //end if\r
-\r
- //calculate wait time for this iteration\r
- long maxWait = (getPoolProperties().getMaxWait()<=0)?Long.MAX_VALUE:getPoolProperties().getMaxWait();\r
- long timetowait = Math.max(1, maxWait - (System.currentTimeMillis() - now));\r
- try {\r
- //retrieve an existing connection\r
- con = idle.poll(timetowait, TimeUnit.MILLISECONDS);\r
- } catch (InterruptedException ex) {\r
- Thread.currentThread().interrupted();\r
- }\r
- //we didn't get a connection, lets see if we timed out\r
- if (con == null) {\r
- if ((System.currentTimeMillis() - now) >= maxWait) {\r
- throw new SQLException(\r
- "Pool empty. Unable to fetch a connection in " + (maxWait / 1000) +\r
- " seconds, none available["+busy.size()+" in use].");\r
- } else {\r
- //no timeout, lets try again\r
- continue;\r
- }\r
- }\r
- } //while\r
- }\r
-\r
- protected PooledConnection createConnection(long now, PooledConnection con) {\r
- //no connections where available we'll create one\r
- boolean error = false;\r
- try {\r
- //connect and validate the connection\r
- con = create();\r
- con.lock();\r
- if (!busy.offer(con)) {\r
- log.debug("Connection doesn't fit into busy array, connection will not be traceable.");\r
- }\r
- con.connect();\r
- if (con.validate(PooledConnection.VALIDATE_INIT)) {\r
- //no need to lock a new one, its not contented\r
- con.setTimestamp(now);\r
- if (getPoolProperties().isLogAbandoned()) {\r
- con.setStackTrace(getThreadDump());\r
- }\r
- return con;\r
- } //end if\r
- } catch (Exception e) {\r
- error = true;\r
- log.error("Unable to create a new JDBC connection.", e);\r
- } finally {\r
- if (error ) {\r
- release(con);\r
- busy.remove(con);\r
- }\r
- con.unlock();\r
- }//catch\r
- return null;\r
- }\r
-\r
- protected PooledConnection borrowConnection(long now, PooledConnection con) {\r
- //we have a connection, lets set it up\r
- boolean setToNull = false;\r
- try {\r
- con.lock();\r
- if (con.isDiscarded()) {\r
- //connection has already been disconnected\r
- setToNull = true;\r
- } else if (con.validate(PooledConnection.VALIDATE_BORROW)) {\r
- //set the timestamp\r
- con.setTimestamp(now);\r
- if (getPoolProperties().isLogAbandoned()) {\r
- //set the stack trace for this pool\r
- con.setStackTrace(getThreadDump());\r
- }\r
- if (!busy.offer(con)) {\r
- log.debug("Connection doesn't fit into busy array, connection will not be traceable.");\r
- }\r
- return con;\r
- } else {\r
- /*if the object wasn't validated, we may as well remove it*/\r
- release(con);\r
- setToNull = true;\r
- } //end if\r
- } finally {\r
- con.unlock();\r
- if (setToNull) {\r
- con = null;\r
- }\r
- }\r
- return con;\r
- }\r
-\r
- /**\r
- * Returns a connection to the pool\r
- * @param con PooledConnection\r
- */\r
- protected void returnConnection(PooledConnection con) {\r
- if (isClosed()) {\r
- //if the connection pool is closed\r
- //close the connection instead of returning it\r
- release(con);\r
- return;\r
- } //end if\r
-\r
- if (con != null) {\r
- try {\r
- con.lock();\r
-\r
- if (busy.remove(con)) {\r
- if ((!con.isDiscarded()) && (!isClosed()) &&\r
- con.validate(PooledConnection.VALIDATE_RETURN)) {\r
- con.setStackTrace(null);\r
- con.setTimestamp(System.currentTimeMillis());\r
- if (!idle.offer(con)) {\r
- if (log.isDebugEnabled()) {\r
- log.debug("Connection ["+con+"] will be closed and not returned to the pool, idle.offer failed.");\r
- }\r
- release(con);\r
- }\r
- } else {\r
- if (log.isDebugEnabled()) {\r
- log.debug("Connection ["+con+"] will be closed and not returned to the pool.");\r
- }\r
- release(con);\r
- } //end if\r
- } else {\r
- if (log.isDebugEnabled()) {\r
- log.debug("Connection ["+con+"] will be closed and not returned to the pool, busy.remove failed.");\r
- }\r
- release(con);\r
- }\r
- } finally {\r
- con.unlock();\r
- }\r
- } //end if\r
- } //checkIn\r
-\r
- public void checkAbandoned() {\r
- try {\r
- long now = System.currentTimeMillis();\r
- Iterator<PooledConnection> locked = busy.iterator();\r
- while (locked.hasNext()) {\r
- PooledConnection con = locked.next();\r
- boolean setToNull = false;\r
- try {\r
- con.lock();\r
- //the con has been returned to the pool\r
- //ignore it\r
- if (idle.contains(con))\r
- continue;\r
- long time = con.getTimestamp();\r
- if ((now - time) > con.getAbandonTimeout()) {\r
- busy.remove(con);\r
- abandon(con);\r
- release(con);\r
- setToNull = true;\r
- } else {\r
- //do nothing\r
- } //end if\r
- } finally {\r
- con.unlock();\r
- if (setToNull)\r
- con = null;\r
- }\r
- } //while\r
- } catch (ConcurrentModificationException e) {\r
- log.debug("checkAbandoned failed." ,e);\r
- } catch (Exception e) {\r
- log.warn("checkAbandoned failed, it will be retried.",e);\r
- }\r
- }\r
-\r
- public void checkIdle() {\r
- try {\r
- long now = System.currentTimeMillis();\r
- Iterator<PooledConnection> unlocked = idle.iterator();\r
- while ( (idle.size()>=getPoolProperties().getMinIdle()) && unlocked.hasNext()) {\r
- PooledConnection con = unlocked.next();\r
- boolean setToNull = false;\r
- try {\r
- con.lock();\r
- //the con been taken out, we can't clean it up\r
- if (busy.contains(con))\r
- continue;\r
- long time = con.getTimestamp();\r
- if (((now - time) > con.getReleaseTime()) && (getSize()>getPoolProperties().getMinIdle())) {\r
- release(con);\r
- idle.remove(con);\r
- setToNull = true;\r
- } else {\r
- //do nothing\r
- } //end if\r
- } finally {\r
- con.unlock();\r
- if (setToNull)\r
- con = null;\r
- }\r
- } //while\r
- } catch (ConcurrentModificationException e) {\r
- log.debug("checkIdle failed." ,e);\r
- } catch (Exception e) {\r
- log.warn("checkIdle failed, it will be retried.",e);\r
- }\r
-\r
- }\r
-\r
- public void testAllIdle() {\r
- try {\r
- Iterator<PooledConnection> unlocked = idle.iterator();\r
- while (unlocked.hasNext()) {\r
- PooledConnection con = unlocked.next();\r
- try {\r
- con.lock();\r
- //the con been taken out, we can't clean it up\r
- if (busy.contains(con))\r
- continue;\r
- if (!con.validate(PooledConnection.VALIDATE_IDLE)) {\r
- idle.remove(con);\r
- con.release();\r
- }\r
- } finally {\r
- con.unlock();\r
- }\r
- } //while\r
- } catch (ConcurrentModificationException e) {\r
- log.debug("testAllIdle failed." ,e);\r
- } catch (Exception e) {\r
- log.warn("testAllIdle failed, it will be retried.",e);\r
- }\r
-\r
- }\r
-\r
-\r
- protected static String getThreadDump() {\r
- Exception x = new Exception();\r
- x.fillInStackTrace();\r
- return getStackTrace(x);\r
- }\r
-\r
- protected static String getStackTrace(Exception x) {\r
- if (x == null) {\r
- return null;\r
- } else {\r
- java.io.ByteArrayOutputStream bout = new java.io.ByteArrayOutputStream();\r
- java.io.PrintStream writer = new java.io.PrintStream(bout);\r
- x.printStackTrace(writer);\r
- String result = bout.toString();\r
- return result;\r
- } //end if\r
- }\r
-\r
-\r
- protected PooledConnection create() throws java.lang.Exception {\r
- PooledConnection con = new PooledConnection(getPoolProperties(), this);\r
- return con;\r
- }\r
-\r
- protected void finalize(PooledConnection con) {\r
- size.addAndGet(-1);\r
- }\r
-\r
- public void startJmx() {\r
- try {\r
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();\r
- ObjectName name = new ObjectName("org.apache.tomcat.jdbc.pool.jmx:type=ConnectionPool,name="+getName());\r
- mbs.registerMBean(new org.apache.tomcat.jdbc.pool.jmx.ConnectionPool(this), name);\r
- } catch (Exception x) {\r
- log.warn("Unable to start JMX integration for connection pool. Instance["+getName()+"] can't be monitored.",x);\r
- }\r
- }\r
-\r
- public void stopJmx() {\r
- try {\r
- MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();\r
- ObjectName name = new ObjectName("org.apache.tomcat.jdbc.pool.jmx:type=ConnectionPool,name="+getName());\r
- mbs.unregisterMBean(name);\r
- }catch (Exception x) {\r
- log.warn("Unable to stop JMX integration for connection pool. Instance["+getName()+"].",x);\r
- }\r
- }\r
-\r
-\r
- protected class PoolCleaner extends Thread {\r
- protected ConnectionPool pool;\r
- protected long sleepTime;\r
- protected boolean run = true;\r
- PoolCleaner(String name, ConnectionPool pool, long sleepTime) {\r
- super(name);\r
- this.setDaemon(true);\r
- this.pool = pool;\r
- this.sleepTime = sleepTime;\r
- if (sleepTime <= 0) {\r
- pool.log.warn("Database connection pool evicter thread interval is set to 0, defaulting to 30 seconds");\r
- this.sleepTime = 1000 * 30;\r
- } else if (sleepTime < 1000) {\r
- pool.log.warn("Database connection pool evicter thread interval is set to lower than 1 second.");\r
- }\r
- }\r
-\r
- public void run() {\r
- while (run) {\r
- try {\r
- sleep(sleepTime);\r
- } catch (InterruptedException e) {\r
- // ignore it\r
- Thread.currentThread().interrupted();\r
- continue;\r
- } //catch\r
-\r
- if (pool.isClosed()) {\r
- if (pool.getSize() <= 0) {\r
- run = false;\r
- }\r
- } else {\r
- try {\r
- if (pool.getPoolProperties().isRemoveAbandoned())\r
- pool.checkAbandoned();\r
- if (pool.getPoolProperties().getMaxIdle()<pool.idle.size())\r
- pool.checkIdle();\r
- if (pool.getPoolProperties().isTestWhileIdle())\r
- pool.testAllIdle();\r
- } catch (Exception x) {\r
- pool.log.error("", x);\r
- } //catch\r
- } //end if\r
- } //while\r
- } //run\r
-\r
- public void stopRunning() {\r
- run = false;\r
- interrupt();\r
- }\r
- }\r
-}\r
+++ /dev/null
-/*\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.pool;\r
-\r
-\r
-/**\r
- * A DataSource that can be instantiated through IoC and implements the DataSource interface\r
- * since the DataSourceProxy is used as a generic proxy\r
- * @author Filip Hanik\r
- * @version 1.0\r
- */\r
-public class DataSource extends DataSourceProxy implements javax.sql.DataSource {\r
-\r
-}\r
+++ /dev/null
-/*\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.pool;\r
-\r
-\r
-import java.io.ByteArrayInputStream;\r
-import java.lang.reflect.InvocationHandler;\r
-import java.lang.reflect.Method;\r
-import java.lang.reflect.Proxy;\r
-import java.sql.Connection;\r
-import java.util.HashMap;\r
-import java.util.Hashtable;\r
-import java.util.Properties;\r
-\r
-import javax.naming.Context;\r
-import javax.naming.Name;\r
-import javax.naming.RefAddr;\r
-import javax.naming.Reference;\r
-import javax.naming.spi.ObjectFactory;\r
-import javax.sql.DataSource;\r
-\r
-import org.apache.juli.logging.Log;\r
-import org.apache.juli.logging.LogFactory;\r
-\r
-/**\r
- * <p>JNDI object factory that creates an instance of\r
- * <code>BasicDataSource</code> that has been configured based on the\r
- * <code>RefAddr</code> values of the specified <code>Reference</code>,\r
- * which must match the names and data types of the\r
- * <code>BasicDataSource</code> bean properties.</p>\r
- * <br/>\r
- * Properties available for configuration:<br/>\r
- * <a href="http://commons.apache.org/dbcp/configuration.html">Commons DBCP properties</a><br/>\r
- *<ol>\r
- * <li>initSQL - A query that gets executed once, right after the connection is established.</li>\r
- * <li>testOnConnect - run validationQuery after connection has been established.</li>\r
- * <li>validationInterval - avoid excess validation, only run validation at most at this frequency - time in milliseconds.</li>\r
- * <li>jdbcInterceptors - a semicolon separated list of classnames extending {@link JdbcInterceptor} class.</li>\r
- * <li>jmxEnabled - true of false, whether to register the pool with JMX.</li>\r
- *</ol>\r
- * @author Craig R. McClanahan\r
- * @author Dirk Verbeeck\r
- * @author Filip Hanik\r
- */\r
-public class DataSourceFactory implements ObjectFactory {\r
- protected static Log log = LogFactory.getLog(DataSourceFactory.class);\r
-\r
- protected final static String PROP_DEFAULTAUTOCOMMIT = "defaultAutoCommit";\r
- protected final static String PROP_DEFAULTREADONLY = "defaultReadOnly";\r
- protected final static String PROP_DEFAULTTRANSACTIONISOLATION = "defaultTransactionIsolation";\r
- protected final static String PROP_DEFAULTCATALOG = "defaultCatalog";\r
- \r
- protected final static String PROP_DRIVERCLASSNAME = "driverClassName";\r
- protected final static String PROP_PASSWORD = "password";\r
- protected final static String PROP_URL = "url";\r
- protected final static String PROP_USERNAME = "username";\r
-\r
- protected final static String PROP_MAXACTIVE = "maxActive";\r
- protected final static String PROP_MAXIDLE = "maxIdle";\r
- protected final static String PROP_MINIDLE = "minIdle";\r
- protected final static String PROP_INITIALSIZE = "initialSize";\r
- protected final static String PROP_MAXWAIT = "maxWait";\r
- \r
- protected final static String PROP_TESTONBORROW = "testOnBorrow";\r
- protected final static String PROP_TESTONRETURN = "testOnReturn";\r
- protected final static String PROP_TESTWHILEIDLE = "testWhileIdle";\r
- protected final static String PROP_TESTONCONNECT = "testOnConnect";\r
- protected final static String PROP_VALIDATIONQUERY = "validationQuery";\r
- \r
- protected final static String PROP_TIMEBETWEENEVICTIONRUNSMILLIS = "timeBetweenEvictionRunsMillis";\r
- protected final static String PROP_NUMTESTSPEREVICTIONRUN = "numTestsPerEvictionRun";\r
- protected final static String PROP_MINEVICTABLEIDLETIMEMILLIS = "minEvictableIdleTimeMillis";\r
- \r
- protected final static String PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED = "accessToUnderlyingConnectionAllowed";\r
- \r
- protected final static String PROP_REMOVEABANDONED = "removeAbandoned";\r
- protected final static String PROP_REMOVEABANDONEDTIMEOUT = "removeAbandonedTimeout";\r
- protected final static String PROP_LOGABANDONED = "logAbandoned";\r
- \r
- protected final static String PROP_POOLPREPAREDSTATEMENTS = "poolPreparedStatements";\r
- protected final static String PROP_MAXOPENPREPAREDSTATEMENTS = "maxOpenPreparedStatements";\r
- protected final static String PROP_CONNECTIONPROPERTIES = "connectionProperties";\r
- \r
- protected final static String PROP_INITSQL = "initSQL";\r
- protected final static String PROP_INTERCEPTORS = "jdbcInterceptors";\r
- protected final static String PROP_VALIDATIONINTERVAL = "validationInterval";\r
- protected final static String PROP_JMX_ENABLED = "jmxEnabled";\r
- \r
- public static final int UNKNOWN_TRANSACTIONISOLATION = -1;\r
-\r
-\r
- protected final static String[] ALL_PROPERTIES = {\r
- PROP_DEFAULTAUTOCOMMIT,\r
- PROP_DEFAULTREADONLY,\r
- PROP_DEFAULTTRANSACTIONISOLATION,\r
- PROP_DEFAULTCATALOG,\r
- PROP_DRIVERCLASSNAME,\r
- PROP_MAXACTIVE,\r
- PROP_MAXIDLE,\r
- PROP_MINIDLE,\r
- PROP_INITIALSIZE,\r
- PROP_MAXWAIT,\r
- PROP_TESTONBORROW,\r
- PROP_TESTONRETURN,\r
- PROP_TIMEBETWEENEVICTIONRUNSMILLIS,\r
- PROP_NUMTESTSPEREVICTIONRUN,\r
- PROP_MINEVICTABLEIDLETIMEMILLIS,\r
- PROP_TESTWHILEIDLE,\r
- PROP_TESTONCONNECT,\r
- PROP_PASSWORD,\r
- PROP_URL,\r
- PROP_USERNAME,\r
- PROP_VALIDATIONQUERY,\r
- PROP_VALIDATIONINTERVAL,\r
- PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED,\r
- PROP_REMOVEABANDONED,\r
- PROP_REMOVEABANDONEDTIMEOUT,\r
- PROP_LOGABANDONED,\r
- PROP_POOLPREPAREDSTATEMENTS,\r
- PROP_MAXOPENPREPAREDSTATEMENTS,\r
- PROP_CONNECTIONPROPERTIES,\r
- PROP_INITSQL,\r
- PROP_INTERCEPTORS,\r
- PROP_JMX_ENABLED\r
- };\r
-\r
- // -------------------------------------------------- ObjectFactory Methods\r
-\r
- /**\r
- * <p>Create and return a new <code>BasicDataSource</code> instance. If no\r
- * instance can be created, return <code>null</code> instead.</p>\r
- *\r
- * @param obj The possibly null object containing location or\r
- * reference information that can be used in creating an object\r
- * @param name The name of this object relative to <code>nameCtx</code>\r
- * @param nameCtx The context relative to which the <code>name</code>\r
- * parameter is specified, or <code>null</code> if <code>name</code>\r
- * is relative to the default initial context\r
- * @param environment The possibly null environment that is used in\r
- * creating this object\r
- *\r
- * @exception Exception if an exception occurs creating the instance\r
- */\r
- public Object getObjectInstance(Object obj, Name name, Context nameCtx,\r
- Hashtable environment) throws Exception {\r
-\r
- // We only know how to deal with <code>javax.naming.Reference</code>s\r
- // that specify a class name of "javax.sql.DataSource"\r
- if ((obj == null) || !(obj instanceof Reference)) {\r
- return null;\r
- }\r
- Reference ref = (Reference) obj;\r
- if (!"javax.sql.DataSource".equals(ref.getClassName())) {\r
- return null;\r
- }\r
-\r
- Properties properties = new Properties();\r
- for (int i = 0; i < ALL_PROPERTIES.length; i++) {\r
- String propertyName = ALL_PROPERTIES[i];\r
- RefAddr ra = ref.get(propertyName);\r
- if (ra != null) {\r
- String propertyValue = ra.getContent().toString();\r
- properties.setProperty(propertyName, propertyValue);\r
- }\r
- }\r
-\r
- return createDataSource(properties);\r
- }\r
-\r
- /**\r
- * Creates and configures a {@link BasicDataSource} instance based on the\r
- * given properties.\r
- *\r
- * @param properties the datasource configuration properties\r
- * @throws Exception if an error occurs creating the data source\r
- */\r
- public static DataSource createDataSource(Properties properties) throws Exception {\r
- org.apache.tomcat.jdbc.pool.DataSourceProxy dataSource = new org.apache.tomcat.jdbc.pool.DataSourceProxy();\r
-\r
- String value = null;\r
-\r
- value = properties.getProperty(PROP_DEFAULTAUTOCOMMIT);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setDefaultAutoCommit(Boolean.valueOf(value));\r
- }\r
-\r
- value = properties.getProperty(PROP_DEFAULTREADONLY);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setDefaultReadOnly(Boolean.valueOf(value));\r
- }\r
-\r
- value = properties.getProperty(PROP_DEFAULTTRANSACTIONISOLATION);\r
- if (value != null) {\r
- int level = UNKNOWN_TRANSACTIONISOLATION;\r
- if ("NONE".equalsIgnoreCase(value)) {\r
- level = Connection.TRANSACTION_NONE;\r
- } else if ("READ_COMMITTED".equalsIgnoreCase(value)) {\r
- level = Connection.TRANSACTION_READ_COMMITTED;\r
- } else if ("READ_UNCOMMITTED".equalsIgnoreCase(value)) {\r
- level = Connection.TRANSACTION_READ_UNCOMMITTED;\r
- } else if ("REPEATABLE_READ".equalsIgnoreCase(value)) {\r
- level = Connection.TRANSACTION_REPEATABLE_READ;\r
- } else if ("SERIALIZABLE".equalsIgnoreCase(value)) {\r
- level = Connection.TRANSACTION_SERIALIZABLE;\r
- } else {\r
- try {\r
- level = Integer.parseInt(value);\r
- } catch (NumberFormatException e) {\r
- System.err.println("Could not parse defaultTransactionIsolation: " + value);\r
- System.err.println("WARNING: defaultTransactionIsolation not set");\r
- System.err.println("using default value of database driver");\r
- level = UNKNOWN_TRANSACTIONISOLATION;\r
- }\r
- }\r
- dataSource.getPoolProperties().setDefaultTransactionIsolation(level);\r
- }\r
-\r
- value = properties.getProperty(PROP_DEFAULTCATALOG);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setDefaultCatalog(value);\r
- }\r
-\r
- value = properties.getProperty(PROP_DRIVERCLASSNAME);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setDriverClassName(value);\r
- }\r
-\r
- value = properties.getProperty(PROP_MAXACTIVE);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setMaxActive(Integer.parseInt(value));\r
- }\r
-\r
- value = properties.getProperty(PROP_MAXIDLE);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setMaxIdle(Integer.parseInt(value));\r
- }\r
-\r
- value = properties.getProperty(PROP_MINIDLE);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setMinIdle(Integer.parseInt(value));\r
- }\r
-\r
- value = properties.getProperty(PROP_INITIALSIZE);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setInitialSize(Integer.parseInt(value));\r
- }\r
-\r
- value = properties.getProperty(PROP_MAXWAIT);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setMaxWait(Integer.parseInt(value));\r
- }\r
-\r
- value = properties.getProperty(PROP_TESTONBORROW);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setTestOnBorrow(Boolean.valueOf(value).booleanValue());\r
- }\r
-\r
- value = properties.getProperty(PROP_TESTONRETURN);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setTestOnReturn(Boolean.valueOf(value).booleanValue());\r
- }\r
-\r
- value = properties.getProperty(PROP_TESTONCONNECT);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setTestOnConnect(Boolean.valueOf(value).booleanValue());\r
- }\r
-\r
- value = properties.getProperty(PROP_TIMEBETWEENEVICTIONRUNSMILLIS);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setTimeBetweenEvictionRunsMillis(Integer.parseInt(value));\r
- }\r
-\r
- value = properties.getProperty(PROP_NUMTESTSPEREVICTIONRUN);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setNumTestsPerEvictionRun(Integer.parseInt(value));\r
- }\r
-\r
- value = properties.getProperty(PROP_MINEVICTABLEIDLETIMEMILLIS);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setMinEvictableIdleTimeMillis(Integer.parseInt(value));\r
- }\r
-\r
- value = properties.getProperty(PROP_TESTWHILEIDLE);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setTestWhileIdle(Boolean.valueOf(value).booleanValue());\r
- }\r
-\r
- value = properties.getProperty(PROP_PASSWORD);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setPassword(value);\r
- }\r
-\r
- value = properties.getProperty(PROP_URL);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setUrl(value);\r
- }\r
-\r
- value = properties.getProperty(PROP_USERNAME);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setUsername(value);\r
- }\r
-\r
- value = properties.getProperty(PROP_VALIDATIONQUERY);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setValidationQuery(value);\r
- }\r
-\r
- value = properties.getProperty(PROP_VALIDATIONINTERVAL);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setValidationInterval(Long.parseLong(value));\r
- }\r
-\r
- value = properties.getProperty(PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED);\r
- if (value != null) {\r
- dataSource.getPoolProperties().\r
- setAccessToUnderlyingConnectionAllowed(Boolean.valueOf(value).booleanValue());\r
- }\r
-\r
- value = properties.getProperty(PROP_REMOVEABANDONED);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setRemoveAbandoned(Boolean.valueOf(value).booleanValue());\r
- }\r
-\r
- value = properties.getProperty(PROP_REMOVEABANDONEDTIMEOUT);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setRemoveAbandonedTimeout(Integer.parseInt(value));\r
- }\r
-\r
- value = properties.getProperty(PROP_LOGABANDONED);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setLogAbandoned(Boolean.valueOf(value).booleanValue());\r
- }\r
-\r
- value = properties.getProperty(PROP_POOLPREPAREDSTATEMENTS);\r
- if (value != null) {\r
- log.warn(PROP_POOLPREPAREDSTATEMENTS + " is not a valid setting, it will have no effect.");\r
- }\r
-\r
- value = properties.getProperty(PROP_MAXOPENPREPAREDSTATEMENTS);\r
- if (value != null) {\r
- log.warn(PROP_MAXOPENPREPAREDSTATEMENTS + " is not a valid setting, it will have no effect.");\r
- }\r
-\r
- value = properties.getProperty(PROP_CONNECTIONPROPERTIES);\r
- if (value != null) {\r
- Properties p = getProperties(value);\r
- dataSource.getPoolProperties().setDbProperties(p);\r
- } else {\r
- dataSource.getPoolProperties().setDbProperties(new Properties());\r
- }\r
-\r
- dataSource.getPoolProperties().getDbProperties().setProperty("user",dataSource.getPoolProperties().getUsername());\r
- dataSource.getPoolProperties().getDbProperties().setProperty("password",dataSource.getPoolProperties().getPassword());\r
-\r
- value = properties.getProperty(PROP_INITSQL);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setInitSQL(value);\r
- }\r
-\r
- value = properties.getProperty(PROP_INTERCEPTORS);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setJdbcInterceptors(value);\r
- }\r
-\r
- value = properties.getProperty(PROP_JMX_ENABLED);\r
- if (value != null) {\r
- dataSource.getPoolProperties().setJmxEnabled(Boolean.parseBoolean(value));\r
- }\r
-\r
- // Return the configured DataSource instance\r
- DataSource ds = getDataSource(dataSource);\r
- return ds;\r
- }\r
-\r
- public static DataSource getDataSource(org.apache.tomcat.jdbc.pool.DataSourceProxy dataSource) {\r
- DataSourceHandler handler = new DataSourceHandler(dataSource);\r
- DataSource ds = (DataSource)Proxy.newProxyInstance(DataSourceFactory.class.getClassLoader(), new Class[] {javax.sql.DataSource.class}, handler);\r
- return ds;\r
- }\r
-\r
- /**\r
- * <p>Parse properties from the string. Format of the string must be [propertyName=property;]*<p>\r
- * @param propText\r
- * @return Properties\r
- * @throws Exception\r
- */\r
- static protected Properties getProperties(String propText) throws Exception {\r
- Properties p = new Properties();\r
- if (propText != null) {\r
- p.load(new ByteArrayInputStream(propText.replace(';', '\n').\r
- getBytes()));\r
- }\r
- return p;\r
- }\r
-\r
- protected static class DataSourceHandler implements InvocationHandler {\r
- protected org.apache.tomcat.jdbc.pool.DataSourceProxy datasource = null;\r
- protected static HashMap<Method,Method> methods = new HashMap<Method,Method>();\r
- public DataSourceHandler(org.apache.tomcat.jdbc.pool.DataSourceProxy ds) {\r
- this.datasource = ds;\r
- }\r
-\r
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\r
- Method m = methods.get(method);\r
- if (m==null) {\r
- m = datasource.getClass().getMethod(method.getName(), method.getParameterTypes());\r
- methods.put(method, m);\r
- }\r
- return m.invoke(datasource, args);\r
- }\r
-\r
- }\r
-}\r
+++ /dev/null
-/*\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.pool;\r
-\r
-import java.io.PrintWriter;\r
-import java.sql.Connection;\r
-import java.sql.SQLException;\r
-import java.util.Iterator;\r
-\r
-import org.apache.juli.logging.Log;\r
-import org.apache.juli.logging.LogFactory;\r
-\r
-/**\r
- *\r
- * <p>Title: Uber Pool</p>\r
- *\r
- * <p>Description: A simple, yet efficient and powerful connection pool</p>\r
- *\r
- * <p>Copyright: Copyright (c) 2008 Filip Hanik</p>\r
- *\r
- * <p> </p>\r
- *\r
- * @author Filip Hanik\r
- * @version 1.0\r
- */\r
-\r
-public class DataSourceProxy {\r
- protected static Log log = LogFactory.getLog(DataSourceProxy.class);\r
- \r
- protected Driver driver;\r
- protected PoolProperties poolProperties = new PoolProperties();\r
-\r
- public DataSourceProxy() {\r
- }\r
-\r
-\r
- public boolean isWrapperFor(Class<?> iface) throws SQLException {\r
- // we are not a wrapper of anything\r
- return false;\r
- }\r
-\r
-\r
- public <T> T unwrap(Class<T> iface) throws SQLException {\r
- //we can't unwrap anything\r
- return null;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- public Connection getConnection(String username, String password) throws SQLException {\r
- return getConnection();\r
- }\r
-\r
- public PoolProperties getPoolProperties() {\r
- return poolProperties;\r
- }\r
-\r
- /**\r
- * Sets up the connection pool, by creating a pooling driver.\r
- * @return Driver\r
- * @throws SQLException\r
- */\r
- public synchronized Driver createDriver() throws SQLException {\r
- if (driver != null) {\r
- return driver;\r
- } else {\r
- driver = new org.apache.tomcat.jdbc.pool.Driver(getPoolProperties());\r
- return driver;\r
- }\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
-\r
- public Connection getConnection() throws SQLException {\r
- if (driver == null)\r
- driver = createDriver();\r
- return driver.connect(poolProperties.getPoolName(), null);\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- public PooledConnection getPooledConnection() throws SQLException {\r
- return (PooledConnection) getConnection();\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- public PooledConnection getPooledConnection(String username,\r
- String password) throws SQLException {\r
- return (PooledConnection) getConnection();\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- public PrintWriter getLogWriter() throws SQLException {\r
- return null;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- public void setLogWriter(PrintWriter out) throws SQLException {\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- public int getLoginTimeout() {\r
- if (poolProperties == null) {\r
- return 0;\r
- } else {\r
- return poolProperties.getMaxWait() / 1000;\r
- }\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- public void setLoginTimeout(int i) {\r
- if (poolProperties == null) {\r
- return;\r
- } else {\r
- poolProperties.setMaxWait(1000 * i);\r
- }\r
-\r
- }\r
-\r
-\r
- public void close() {\r
- close(false);\r
- }\r
- public void close(boolean all) {\r
- try {\r
- if (driver != null) {\r
- Driver d = driver;\r
- driver = null;\r
- d.closePool(poolProperties.getPoolName(), all);\r
- }\r
- }catch (Exception x) {\r
- x.printStackTrace();\r
- }\r
- }\r
-\r
- protected void finalize() throws Throwable {\r
- //terminate the pool?\r
- close(true);\r
- }\r
-\r
- public int getPoolSize() throws SQLException{\r
- if (driver == null)\r
- driver = createDriver();\r
- return driver.getPool(getPoolProperties().getPoolName()).getSize();\r
- }\r
-\r
- public String toString() {\r
- return super.toString()+"{"+getPoolProperties()+"}";\r
- }\r
-\r
-/*-----------------------------------------------------------------------*/\r
-// PROPERTIES WHEN NOT USED WITH FACTORY\r
-/*------------------------------------------------------------------------*/\r
- public void setPoolProperties(PoolProperties poolProperties) {\r
- this.poolProperties = poolProperties;\r
- }\r
-\r
- public void setDriverClassName(String driverClassName) {\r
- this.poolProperties.setDriverClassName(driverClassName);\r
- }\r
-\r
- public void setInitialSize(int initialSize) {\r
- this.poolProperties.setInitialSize(initialSize);\r
- }\r
-\r
- public void setInitSQL(String initSQL) {\r
- this.poolProperties.setInitSQL(initSQL);\r
- }\r
-\r
- public void setLogAbandoned(boolean logAbandoned) {\r
- this.poolProperties.setLogAbandoned(logAbandoned);\r
- }\r
-\r
- public void setMaxActive(int maxActive) {\r
- this.poolProperties.setMaxIdle(maxActive);\r
- }\r
-\r
- public void setMaxIdle(int maxIdle) {\r
- this.poolProperties.setMaxIdle(maxIdle);\r
- }\r
-\r
- public void setMaxWait(int maxWait) {\r
- this.poolProperties.setMaxWait(maxWait);\r
- }\r
-\r
- public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) {\r
- this.poolProperties.setMinEvictableIdleTimeMillis(\r
- minEvictableIdleTimeMillis);\r
- }\r
-\r
- public void setMinIdle(int minIdle) {\r
- this.setMinIdle(minIdle);\r
- }\r
-\r
- public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {\r
- this.poolProperties.setNumTestsPerEvictionRun(numTestsPerEvictionRun);\r
- }\r
-\r
- public void setPassword(String password) {\r
- this.poolProperties.setPassword(password);\r
- this.poolProperties.getDbProperties().setProperty("password",this.poolProperties.getPassword());\r
- }\r
-\r
- public void setRemoveAbandoned(boolean removeAbandoned) {\r
- this.poolProperties.setRemoveAbandoned(removeAbandoned);\r
- }\r
-\r
- public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) {\r
- this.poolProperties.setRemoveAbandonedTimeout(removeAbandonedTimeout);\r
- }\r
-\r
- public void setTestOnBorrow(boolean testOnBorrow) {\r
- this.poolProperties.setTestOnBorrow(testOnBorrow);\r
- }\r
-\r
- public void setTestOnConnect(boolean testOnConnect) {\r
- this.poolProperties.setTestOnConnect(testOnConnect);\r
- }\r
-\r
- public void setTestOnReturn(boolean testOnReturn) {\r
- this.poolProperties.setTestOnReturn(testOnReturn);\r
- }\r
-\r
- public void setTestWhileIdle(boolean testWhileIdle) {\r
- this.poolProperties.setTestWhileIdle(testWhileIdle);\r
- }\r
-\r
- public void setTimeBetweenEvictionRunsMillis(int\r
- timeBetweenEvictionRunsMillis) {\r
- this.poolProperties.setTimeBetweenEvictionRunsMillis(\r
- timeBetweenEvictionRunsMillis);\r
- }\r
-\r
- public void setUrl(String url) {\r
- this.poolProperties.setUrl(url);\r
- }\r
-\r
- public void setUsername(String username) {\r
- this.poolProperties.setUsername(username);\r
- this.poolProperties.getDbProperties().setProperty("user",getPoolProperties().getUsername());\r
- }\r
-\r
- public void setValidationInterval(long validationInterval) {\r
- this.poolProperties.setValidationInterval(validationInterval);\r
- }\r
-\r
- public void setValidationQuery(String validationQuery) {\r
- this.poolProperties.setValidationQuery(validationQuery);\r
- }\r
-\r
- public void setJdbcInterceptors(String interceptors) {\r
- this.getPoolProperties().setJdbcInterceptors(interceptors);\r
- }\r
-\r
- public void setJmxEnabled(boolean enabled) {\r
- this.getPoolProperties().setJmxEnabled(enabled);\r
- }\r
- \r
- public void setConnectionProperties(String properties) {\r
- try {\r
- java.util.Properties prop = DataSourceFactory.getProperties(properties);\r
- Iterator i = prop.keySet().iterator();\r
- while (i.hasNext()) {\r
- String key = (String)i.next();\r
- String value = prop.getProperty(key);\r
- getPoolProperties().getDbProperties().setProperty(key, value);\r
- }\r
- \r
- }catch (Exception x) {\r
- log.error("Unable to parse connection properties.", x);\r
- throw new RuntimeException(x);\r
- }\r
- }\r
-\r
-\r
-}\r
+++ /dev/null
-/*\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.pool;\r
-\r
-\r
-import java.sql.Connection;\r
-import java.sql.DriverPropertyInfo;\r
-import java.sql.SQLException;\r
-import java.util.HashMap;\r
-import java.util.Properties;\r
-\r
-import org.apache.juli.logging.Log;\r
-import org.apache.juli.logging.LogFactory;\r
-/**\r
- * @author Filip Hanik\r
- * @version 1.0\r
- */\r
-public class Driver implements java.sql.Driver {\r
-\r
- protected static Log log = LogFactory.getLog(Driver.class);\r
-\r
- protected static HashMap pooltable = new HashMap(11);\r
-\r
- public Driver() throws SQLException {\r
- }\r
-\r
- public Driver(PoolProperties properties) throws SQLException {\r
- init(properties);\r
- } //Driver\r
-\r
- public void init(PoolProperties properties) throws SQLException {\r
- if (pooltable.get(properties.getPoolName()) != null)\r
- throw new SQLException("Pool identified by:" + properties.getPoolName() + " already exists.");\r
- ConnectionPool pool = new ConnectionPool(properties);\r
- pooltable.put(properties.getPoolName(), pool);\r
- }\r
-\r
- public void closePool(String url, boolean all) throws SQLException {\r
- ConnectionPool pool = (ConnectionPool) pooltable.get(url);\r
- if (pool == null) {\r
- throw new SQLException("No connection pool established for URL:" + url);\r
- } else {\r
- pool.close(all);\r
- }\r
- pooltable.remove(url);\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- public Connection connect(String url, Properties info) throws SQLException {\r
- ConnectionPool pool = (ConnectionPool) pooltable.get(url);\r
- if (pool == null) {\r
- throw new SQLException("No connection pool established for URL:" + url);\r
- } else {\r
- try {\r
- return pool.getConnection();\r
- } catch (SQLException forward) {\r
- throw forward;\r
- } catch (Exception e) {\r
- throw new SQLException("Unknow pool exception:" + ConnectionPool.getStackTrace(e));\r
- } //catch\r
- } //end if\r
- } //connect\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- public boolean acceptsURL(String url) throws SQLException {\r
- /* check if the driver has a connection pool with that name */\r
- return (pooltable.get(url) != null ? true : false);\r
- } //acceptsUrl\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws\r
- SQLException {\r
- return new DriverPropertyInfo[0];\r
- } //getPropertyInfo\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- public int getMajorVersion() {\r
- return 1;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- public int getMinorVersion() {\r
- return 0;\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- public boolean jdbcCompliant() {\r
- return true;\r
- }\r
-\r
- public ConnectionPool getPool(String url) throws SQLException {\r
- return (ConnectionPool) pooltable.get(url);\r
- }\r
-\r
-} //class\r
+++ /dev/null
-/*\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.pool;\r
-\r
-import java.lang.reflect.InvocationHandler;\r
-import java.lang.reflect.Method;\r
-\r
-/**\r
- * @author Filip Hanik\r
- * @version 1.0\r
- */\r
-public abstract class JdbcInterceptor implements InvocationHandler {\r
- public static final String CLOSE_VAL = "close";\r
-\r
- private JdbcInterceptor next = null;\r
-\r
- public JdbcInterceptor() {\r
- }\r
-\r
- /**\r
- * {@inheritDoc}\r
- */\r
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\r
- if (getNext()!=null) return getNext().invoke(this,method,args);\r
- else throw new NullPointerException();\r
- }\r
-\r
- public JdbcInterceptor getNext() {\r
- return next;\r
- }\r
-\r
- public void setNext(JdbcInterceptor next) {\r
- this.next = next;\r
- }\r
-\r
- public abstract void reset(ConnectionPool parent, PooledConnection con);\r
-}\r
+++ /dev/null
-/*\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.pool;\r
-\r
-\r
-import java.lang.reflect.Method;\r
-import java.util.Properties;\r
-/**\r
- * @author Filip Hanik\r
- *\r
- */\r
-public class PoolProperties {\r
- protected static volatile int poolCounter = 1;\r
- protected Properties dbProperties = new Properties();\r
- protected String url = null;\r
- protected String driverClassName = null;\r
- protected Boolean defaultAutoCommit = null;\r
- protected Boolean defaultReadOnly = null;\r
- protected int defaultTransactionIsolation = DataSourceFactory.UNKNOWN_TRANSACTIONISOLATION;\r
- protected String defaultCatalog = null;\r
- protected String connectionProperties;\r
- protected int initialSize = 10;\r
- protected int maxActive = 100;\r
- protected int maxIdle = maxActive;\r
- protected int minIdle = initialSize;\r
- protected int maxWait = 30000;\r
- protected String validationQuery;\r
- protected boolean testOnBorrow = false;\r
- protected boolean testOnReturn = false;\r
- protected boolean testWhileIdle = false;\r
- protected int timeBetweenEvictionRunsMillis = 5000;\r
- protected int numTestsPerEvictionRun;\r
- protected int minEvictableIdleTimeMillis = 60000;\r
- protected boolean accessToUnderlyingConnectionAllowed;\r
- protected boolean removeAbandoned = false;\r
- protected int removeAbandonedTimeout = 60;\r
- protected boolean logAbandoned = false;\r
- protected int loginTimeout = 10000;\r
- protected String name = "Filip Connection Pool["+(poolCounter++)+"]";\r
- protected String password;\r
- protected String username;\r
- protected long validationInterval = 30000;\r
- protected boolean jmxEnabled = true;\r
- protected String initSQL;\r
- protected boolean testOnConnect =false;\r
- private String jdbcInterceptors=null;\r
-\r
- public boolean isAccessToUnderlyingConnectionAllowed() {\r
- return accessToUnderlyingConnectionAllowed;\r
- }\r
-\r
- public String getConnectionProperties() {\r
- return connectionProperties;\r
- }\r
-\r
- public Properties getDbProperties() {\r
- return dbProperties;\r
- }\r
-\r
- public boolean isDefaultAutoCommit() {\r
- return defaultAutoCommit;\r
- }\r
-\r
- public String getDefaultCatalog() {\r
- return defaultCatalog;\r
- }\r
-\r
- public boolean isDefaultReadOnly() {\r
- return defaultReadOnly;\r
- }\r
-\r
- public int getDefaultTransactionIsolation() {\r
- return defaultTransactionIsolation;\r
- }\r
-\r
- public String getDriverClassName() {\r
- return driverClassName;\r
- }\r
-\r
- public int getInitialSize() {\r
- return initialSize;\r
- }\r
-\r
- public boolean isLogAbandoned() {\r
- return logAbandoned;\r
- }\r
-\r
- public int getLoginTimeout() {\r
- return loginTimeout;\r
- }\r
-\r
- public int getMaxActive() {\r
- return maxActive;\r
- }\r
-\r
- public int getMaxIdle() {\r
- return maxIdle;\r
- }\r
-\r
- public int getMaxWait() {\r
- return maxWait;\r
- }\r
-\r
- public int getMinEvictableIdleTimeMillis() {\r
- return minEvictableIdleTimeMillis;\r
- }\r
-\r
- public int getMinIdle() {\r
- return minIdle;\r
- }\r
-\r
- public String getName() {\r
- return name;\r
- }\r
-\r
- public int getNumTestsPerEvictionRun() {\r
- return numTestsPerEvictionRun;\r
- }\r
-\r
- public String getPassword() {\r
- return password;\r
- }\r
-\r
- public String getPoolName() {\r
- return getName();\r
- }\r
-\r
- public boolean isRemoveAbandoned() {\r
- return removeAbandoned;\r
- }\r
-\r
- public int getRemoveAbandonedTimeout() {\r
- return removeAbandonedTimeout;\r
- }\r
-\r
- public boolean isTestOnBorrow() {\r
- return testOnBorrow;\r
- }\r
-\r
- public boolean isTestOnReturn() {\r
- return testOnReturn;\r
- }\r
-\r
- public boolean isTestWhileIdle() {\r
- return testWhileIdle;\r
- }\r
-\r
- public int getTimeBetweenEvictionRunsMillis() {\r
- return timeBetweenEvictionRunsMillis;\r
- }\r
-\r
- public String getUrl() {\r
- return url;\r
- }\r
-\r
- public String getUsername() {\r
- return username;\r
- }\r
-\r
- public String getValidationQuery() {\r
- return validationQuery;\r
- }\r
-\r
- public long getValidationInterval() {\r
- return validationInterval;\r
- }\r
-\r
- public String getInitSQL() {\r
- return initSQL;\r
- }\r
-\r
- public boolean isTestOnConnect() {\r
- return testOnConnect;\r
- }\r
-\r
- public String getJdbcInterceptors() {\r
- return jdbcInterceptors;\r
- }\r
-\r
- public String[] getJdbcInterceptorsAsArray() {\r
- if (jdbcInterceptors==null) return new String[0];\r
- else {\r
- return jdbcInterceptors.split(";");\r
- }\r
- }\r
-\r
- public void setAccessToUnderlyingConnectionAllowed(boolean\r
- accessToUnderlyingConnectionAllowed) {\r
- this.accessToUnderlyingConnectionAllowed =\r
- accessToUnderlyingConnectionAllowed;\r
- }\r
-\r
- public void setConnectionProperties(String connectionProperties) {\r
- this.connectionProperties = connectionProperties;\r
- }\r
-\r
- public void setDbProperties(Properties dbProperties) {\r
- this.dbProperties = dbProperties;\r
- }\r
-\r
- public void setDefaultAutoCommit(Boolean defaultAutoCommit) {\r
- this.defaultAutoCommit = defaultAutoCommit;\r
- }\r
-\r
- public void setDefaultCatalog(String defaultCatalog) {\r
- this.defaultCatalog = defaultCatalog;\r
- }\r
-\r
- public void setDefaultReadOnly(Boolean defaultReadOnly) {\r
- this.defaultReadOnly = defaultReadOnly;\r
- }\r
-\r
- public void setDefaultTransactionIsolation(int defaultTransactionIsolation) {\r
- this.defaultTransactionIsolation = defaultTransactionIsolation;\r
- }\r
-\r
- public void setDriverClassName(String driverClassName) {\r
- this.driverClassName = driverClassName;\r
- }\r
-\r
- public void setInitialSize(int initialSize) {\r
- this.initialSize = initialSize;\r
- }\r
-\r
- public void setLogAbandoned(boolean logAbandoned) {\r
- this.logAbandoned = logAbandoned;\r
- }\r
-\r
- public void setLoginTimeout(int loginTimeout) {\r
- this.loginTimeout = loginTimeout;\r
- }\r
-\r
- public void setMaxActive(int maxActive) {\r
- this.maxActive = maxActive;\r
- }\r
-\r
- public void setMaxIdle(int maxIdle) {\r
- this.maxIdle = maxIdle;\r
- }\r
-\r
- public void setMaxWait(int maxWait) {\r
- this.maxWait = maxWait;\r
- }\r
-\r
- public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) {\r
- this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;\r
- }\r
-\r
- public void setMinIdle(int minIdle) {\r
- this.minIdle = minIdle;\r
- }\r
-\r
- public void setName(String name) {\r
- this.name = name;\r
- }\r
-\r
- public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {\r
- this.numTestsPerEvictionRun = numTestsPerEvictionRun;\r
- }\r
-\r
- public void setPassword(String password) {\r
- this.password = password;\r
- }\r
-\r
- public void setRemoveAbandoned(boolean removeAbandoned) {\r
- this.removeAbandoned = removeAbandoned;\r
- }\r
-\r
- public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) {\r
- this.removeAbandonedTimeout = removeAbandonedTimeout;\r
- }\r
-\r
- public void setTestOnBorrow(boolean testOnBorrow) {\r
- this.testOnBorrow = testOnBorrow;\r
- }\r
-\r
- public void setTestWhileIdle(boolean testWhileIdle) {\r
- this.testWhileIdle = testWhileIdle;\r
- }\r
-\r
- public void setTestOnReturn(boolean testOnReturn) {\r
- this.testOnReturn = testOnReturn;\r
- }\r
-\r
- public void setTimeBetweenEvictionRunsMillis(int\r
- timeBetweenEvictionRunsMillis) {\r
- this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;\r
- }\r
-\r
- public void setUrl(String url) {\r
- this.url = url;\r
- }\r
-\r
- public void setUsername(String username) {\r
- this.username = username;\r
- }\r
-\r
- public void setValidationInterval(long validationInterval) {\r
- this.validationInterval = validationInterval;\r
- }\r
-\r
- public void setValidationQuery(String validationQuery) {\r
- this.validationQuery = validationQuery;\r
- }\r
-\r
- public void setInitSQL(String initSQL) {\r
- this.initSQL = initSQL;\r
- }\r
-\r
- public void setTestOnConnect(boolean testOnConnect) {\r
- this.testOnConnect = testOnConnect;\r
- }\r
-\r
- public void setJdbcInterceptors(String jdbcInterceptors) {\r
- this.jdbcInterceptors = jdbcInterceptors;\r
- }\r
-\r
- public String toString() {\r
- StringBuffer buf = new StringBuffer("ConnectionPool[");\r
- try {\r
- String[] fields = DataSourceFactory.ALL_PROPERTIES;\r
- for (int i=0; i<fields.length; i++) {\r
- final String[] prefix = new String[] {"get","is"};\r
- for (int j=0; j<prefix.length; j++) {\r
-\r
- String name = prefix[j] + fields[i].substring(0, 1).toUpperCase() +\r
- fields[i].substring(1);\r
- Method m = null;\r
- try {\r
- m = getClass().getMethod(name);\r
- }catch (NoSuchMethodException nm) {\r
- continue;\r
- }\r
- buf.append(fields[i]);\r
- buf.append("=");\r
- buf.append(m.invoke(this, new Object[0]));\r
- buf.append("; ");\r
- break;\r
- }\r
- }\r
- }catch (Exception x) {\r
- //shouldn;t happen\r
- x.printStackTrace();\r
- }\r
- return buf.toString();\r
- }\r
-\r
- public static int getPoolCounter() {\r
- return poolCounter;\r
- }\r
-\r
- public boolean isJmxEnabled() {\r
- return jmxEnabled;\r
- }\r
-\r
- public void setJmxEnabled(boolean jmxEnabled) {\r
- this.jmxEnabled = jmxEnabled;\r
- }\r
-\r
- public Boolean getDefaultAutoCommit() {\r
- return defaultAutoCommit;\r
- }\r
-\r
- public Boolean getDefaultReadOnly() {\r
- return defaultReadOnly;\r
- }\r
- \r
- public boolean isPoolSweeperEnabled() {\r
- boolean result = getTimeBetweenEvictionRunsMillis()>0;\r
- result = result && (isRemoveAbandoned() && getRemoveAbandonedTimeout()>0);\r
- result = result && (isTestWhileIdle() && getValidationQuery()!=null);\r
- return result;\r
- }\r
-}\r
+++ /dev/null
-/*\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.pool;\r
-\r
-\r
-import java.lang.ref.WeakReference;\r
-import java.sql.SQLException;\r
-import java.sql.Statement;\r
-import java.util.concurrent.locks.ReentrantReadWriteLock;\r
-\r
-import org.apache.juli.logging.Log;\r
-import org.apache.juli.logging.LogFactory;\r
-import java.util.concurrent.atomic.AtomicInteger;\r
-\r
-/**\r
- * @author Filip Hanik\r
- * @version 1.0\r
- */\r
-public class PooledConnection {\r
-\r
- public static final int VALIDATE_BORROW = 1;\r
- public static final int VALIDATE_RETURN = 2;\r
- public static final int VALIDATE_IDLE = 3;\r
- public static final int VALIDATE_INIT = 4;\r
-\r
- protected static Log log = LogFactory.getLog(PooledConnection.class);\r
- protected static volatile int counter = 1;\r
-\r
- protected PoolProperties poolProperties;\r
- protected java.sql.Connection connection;\r
- protected String abandonTrace = null;\r
- protected long timestamp;\r
- protected ReentrantReadWriteLock lock = new ReentrantReadWriteLock(false);\r
- protected boolean discarded = false;\r
- protected long lastValidated = System.currentTimeMillis();\r
- protected int instanceCount = 0;\r
- protected ConnectionPool parent;\r
-\r
- protected WeakReference<JdbcInterceptor> handler = null;\r
-\r
- public PooledConnection(PoolProperties prop, ConnectionPool parent) throws SQLException {\r
- instanceCount = counter++;\r
- poolProperties = prop;\r
- this.parent = parent;\r
- }\r
-\r
- protected void connect() throws SQLException {\r
- if (connection != null) {\r
- try {\r
- this.disconnect();\r
- } catch (Exception x) {\r
- log.error("Unable to disconnect previous connection.", x);\r
- } //catch\r
- } //end if\r
- java.sql.Driver driver = null;\r
- try {\r
- driver = (java.sql.Driver) Class.forName(poolProperties.getDriverClassName(),\r
- true, PooledConnection.class.getClassLoader()).newInstance();\r
- } catch (java.lang.Exception cn) {\r
- log.error("Unable to instantiate JDBC driver.", cn);\r
- throw new SQLException(cn.getMessage());\r
- }\r
- String driverURL = poolProperties.getUrl();\r
- String usr = poolProperties.getUsername();\r
- String pwd = poolProperties.getPassword();\r
- poolProperties.getDbProperties().setProperty("user", usr);\r
- poolProperties.getDbProperties().setProperty("password", pwd);\r
- connection = driver.connect(driverURL, poolProperties.getDbProperties());\r
- //set up the default state\r
- if (poolProperties.getDefaultReadOnly()!=null) connection.setReadOnly(poolProperties.getDefaultReadOnly().booleanValue());\r
- if (poolProperties.getDefaultAutoCommit()!=null) connection.setAutoCommit(poolProperties.getDefaultAutoCommit().booleanValue());\r
- if (poolProperties.getDefaultCatalog()!=null) connection.setCatalog(poolProperties.getDefaultCatalog());\r
- if (poolProperties.getDefaultTransactionIsolation()!=DataSourceFactory.UNKNOWN_TRANSACTIONISOLATION) connection.setTransactionIsolation(poolProperties.getDefaultTransactionIsolation());\r
- \r
- this.discarded = false;\r
- }\r
-\r
- protected void reconnect() throws SQLException {\r
- this.disconnect();\r
- this.connect();\r
- } //reconnect\r
-\r
- protected synchronized void disconnect() throws SQLException {\r
- if (isDiscarded()) {\r
- return;\r
- }\r
- setDiscarded(true);\r
- if (connection != null) {\r
- connection.close();\r
- }\r
- connection = null;\r
- parent.finalize(this);\r
- }\r
-\r
-\r
-//============================================================================\r
-// com.filip.util.IPoolObject methods\r
-//============================================================================\r
-\r
- public long getAbandonTimeout() {\r
- if (poolProperties.getRemoveAbandonedTimeout() <= 0) {\r
- return Long.MAX_VALUE;\r
- } else {\r
- return poolProperties.getRemoveAbandonedTimeout()*1000;\r
- } //end if\r
- }\r
-\r
- public boolean abandon() {\r
- try {\r
- disconnect();\r
- } catch (SQLException x) {\r
- log.error("", x);\r
- } //catch\r
- return false;\r
- }\r
-\r
- protected boolean doValidate(int action) {\r
- if (action == PooledConnection.VALIDATE_BORROW &&\r
- poolProperties.isTestOnBorrow())\r
- return true;\r
- else if (action == PooledConnection.VALIDATE_RETURN &&\r
- poolProperties.isTestOnReturn())\r
- return true;\r
- else if (action == PooledConnection.VALIDATE_IDLE &&\r
- poolProperties.isTestWhileIdle())\r
- return true;\r
- else if (action == PooledConnection.VALIDATE_INIT &&\r
- poolProperties.isTestOnConnect())\r
- return true;\r
- else if (action == PooledConnection.VALIDATE_INIT &&\r
- poolProperties.getInitSQL()!=null)\r
- return true;\r
- else\r
- return false;\r
- }\r
-\r
- /**Returns true if the object is still valid. if not\r
- * the pool will call the getExpiredAction() and follow up with one\r
- * of the four expired methods\r
- */\r
- public boolean validate(int validateAction) {\r
- return validate(validateAction,null);\r
- }\r
-\r
- public boolean validate(int validateAction,String sql) {\r
- if (!doValidate(validateAction)) {\r
- //no validation required, no init sql and props not set\r
- return true;\r
- }\r
-\r
- String query = (VALIDATE_INIT==validateAction && (poolProperties.getInitSQL()!=null))?poolProperties.getInitSQL():sql;\r
-\r
- if (query==null) query = poolProperties.getValidationQuery();\r
-\r
- if (query == null) {\r
- //no validation possible\r
- return true;\r
- }\r
- long now = System.currentTimeMillis();\r
- if (this.poolProperties.getValidationInterval() > 0 &&\r
- (now - this.lastValidated) <\r
- this.poolProperties.getValidationInterval()) {\r
- return true;\r
- }\r
- try {\r
- Statement stmt = connection.createStatement();\r
- boolean exec = stmt.execute(query);\r
- stmt.close();\r
- this.lastValidated = now;\r
- return true;\r
- } catch (Exception ignore) {\r
- if (log.isDebugEnabled())\r
- log.debug("Unable to validate object:",ignore);\r
- }\r
- return false;\r
- } //validate\r
-\r
- /**\r
- * The time limit for how long the object\r
- * can remain unused before it is released\r
- */\r
- public long getReleaseTime() {\r
- return this.poolProperties.getMinEvictableIdleTimeMillis();\r
- }\r
-\r
- /**\r
- * This method is called if (Now - timeCheckedIn > getReleaseTime())\r
- */\r
- public void release() {\r
- try {\r
- disconnect();\r
- } catch (SQLException x) {\r
- //TODO\r
- }\r
-\r
- }\r
-\r
- /**\r
- * The pool will set the stack trace when it is check out and\r
- * checked in\r
- */\r
-\r
- public void setStackTrace(String trace) {\r
- abandonTrace = trace;\r
- }\r
-\r
- public String getStackTrace() {\r
- return abandonTrace;\r
- }\r
-\r
- public void setTimestamp(long timestamp) {\r
- this.timestamp = timestamp;\r
- }\r
-\r
- public void setDiscarded(boolean discarded) {\r
- if (this.discarded && !discarded) throw new IllegalStateException("Unable to change the state once the connection has been discarded");\r
- this.discarded = discarded;\r
- }\r
-\r
- public void setLastValidated(long lastValidated) {\r
- this.lastValidated = lastValidated;\r
- }\r
-\r
- public void setPoolProperties(PoolProperties poolProperties) {\r
- this.poolProperties = poolProperties;\r
- }\r
-\r
- public long getTimestamp() {\r
- return timestamp;\r
- }\r
-\r
- public boolean isDiscarded() {\r
- return discarded;\r
- }\r
-\r
- public long getLastValidated() {\r
- return lastValidated;\r
- }\r
-\r
- public PoolProperties getPoolProperties() {\r
- return poolProperties;\r
- }\r
-\r
- public void lock() {\r
- if (this.poolProperties.isPoolSweeperEnabled()) {\r
- //optimized, only use a lock when there is concurrency\r
- lock.writeLock().lock();\r
- }\r
- }\r
-\r
- public void unlock() {\r
- if (this.poolProperties.isPoolSweeperEnabled()) {\r
- //optimized, only use a lock when there is concurrency\r
- lock.writeLock().unlock();\r
- }\r
- }\r
-\r
- public java.sql.Connection getConnection() {\r
- return this.connection;\r
- }\r
-\r
- public JdbcInterceptor getHandler() {\r
- return (handler!=null)?handler.get():null;\r
- }\r
-\r
- public void setHandler(JdbcInterceptor handler) {\r
- if (handler==null) {\r
- if (this.handler!=null) this.handler.clear();\r
- } else if (this.handler==null) {\r
- this.handler = new WeakReference<JdbcInterceptor>(handler);\r
- } else if (this.handler.get()==null) {\r
- this.handler.clear();\r
- this.handler = new WeakReference<JdbcInterceptor>(handler);\r
- } else if (this.handler.get()!=handler) {\r
- this.handler.clear();\r
- this.handler = new WeakReference<JdbcInterceptor>(handler);\r
- }\r
- }\r
-\r
-}\r
+++ /dev/null
-/*\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.pool;\r
-\r
-import java.lang.reflect.Method;\r
-import java.sql.Connection;\r
-import java.sql.SQLException;\r
-/**\r
- * @author Filip Hanik\r
- */\r
-public class ProxyConnection extends JdbcInterceptor {\r
-\r
- protected PooledConnection connection = null;\r
-\r
- protected ConnectionPool pool = null;\r
-\r
- public PooledConnection getConnection() {\r
- return connection;\r
- }\r
-\r
- public void setConnection(PooledConnection connection) {\r
- this.connection = connection;\r
- }\r
-\r
- public ConnectionPool getPool() {\r
- return pool;\r
- }\r
-\r
- public void setPool(ConnectionPool pool) {\r
- this.pool = pool;\r
- }\r
-\r
- protected ProxyConnection(ConnectionPool parent, PooledConnection con) throws SQLException {\r
- pool = parent;\r
- connection = con;\r
- }\r
-\r
- public void reset(ConnectionPool parent, PooledConnection con) {\r
- this.pool = parent;\r
- this.connection = con;\r
- }\r
-\r
- public boolean isWrapperFor(Class<?> iface) throws SQLException {\r
- return (iface.isInstance(connection.getConnection()));\r
- }\r
-\r
-\r
- public Object unwrap(Class iface) throws SQLException {\r
- if (isWrapperFor(iface)) {\r
- return connection.getConnection();\r
- } else {\r
- throw new SQLException("Not a wrapper of "+iface.getName());\r
- }\r
- }\r
-\r
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\r
- if (isClosed()) throw new SQLException("Connection has already been closed.");\r
- if (CLOSE_VAL==method.getName()) {\r
- PooledConnection poolc = this.connection;\r
- this.connection = null;\r
- pool.returnConnection(poolc);\r
- return null;\r
- }\r
- return method.invoke(connection.getConnection(),args);\r
- }\r
-\r
- public boolean isClosed() {\r
- return connection==null || connection.isDiscarded();\r
- }\r
-\r
- public PooledConnection getDelegateConnection() {\r
- return connection;\r
- }\r
-\r
- public ConnectionPool getParentPool() {\r
- return pool;\r
- }\r
-\r
-}\r
+++ /dev/null
-/*\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.pool.interceptor;\r
-\r
-import java.lang.reflect.Method;\r
-\r
-import org.apache.tomcat.jdbc.pool.ConnectionPool;\r
-import org.apache.tomcat.jdbc.pool.DataSourceFactory;\r
-import org.apache.tomcat.jdbc.pool.JdbcInterceptor;\r
-import org.apache.tomcat.jdbc.pool.PooledConnection;\r
-\r
-/**\r
- * Interceptor that keep track of connection state to avoid roundtrips to the database\r
- * @author fhanik\r
- *\r
- */\r
-\r
-public class ConnectionState extends JdbcInterceptor {\r
-\r
- protected final String[] readState = {"getAutoCommit","getTransactionIsolation","isReadOnly"};\r
- protected final String[] writeState = {"setAutoCommit","setTransactionIsolation","setReadOnly"};\r
-\r
- protected Boolean autoCommit = null;\r
- protected Integer transactionIsolation = null;\r
- protected Boolean readOnly = null;\r
-\r
- public void reset(ConnectionPool parent, PooledConnection con) {\r
- autoCommit = null;\r
- transactionIsolation = null;\r
- readOnly = null;\r
- }\r
-\r
- @Override\r
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\r
- String name = method.getName();\r
- boolean read = false;\r
- int index = -1;\r
- for (int i=0; (!read) && i<readState.length; i++) {\r
- read = name==readState[i];\r
- if (read) index = i;\r
- }\r
- boolean write = false;\r
- for (int i=0; (!write) && (!read) && i<writeState.length; i++) {\r
- write = name==writeState[i];\r
- if (write) index = i;\r
- }\r
- Object result = null;\r
- if (read) {\r
- switch (index) {\r
- case 0:{result = autoCommit; break;}\r
- case 1:{result = transactionIsolation; break;}\r
- case 2:{result = readOnly; break;}\r
- default: result = null;\r
- }\r
- //return cached result, if we have it\r
- if (result!=null) return result;\r
- }\r
-\r
- result = super.invoke(proxy, method, args);\r
- if (read || write) {\r
- switch (index) {\r
- case 0:{autoCommit = (Boolean) (read?result:args[0]); break;}\r
- case 1:{transactionIsolation = (Integer)(read?result:args[0]); break;}\r
- case 2:{readOnly = (Boolean)(read?result:args[0]); break;}\r
- }\r
- }\r
- return result;\r
- }\r
-\r
-}\r
+++ /dev/null
-/*\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.pool.interceptor;\r
-\r
-import java.lang.reflect.InvocationHandler;\r
-import java.lang.reflect.Method;\r
-import java.lang.reflect.Proxy;\r
-import java.sql.CallableStatement;\r
-import java.sql.SQLException;\r
-\r
-import org.apache.tomcat.jdbc.pool.ConnectionPool;\r
-import org.apache.tomcat.jdbc.pool.JdbcInterceptor;\r
-import org.apache.tomcat.jdbc.pool.PooledConnection;\r
-\r
-/**\r
- * @author Filip Hanik\r
- * @version 1.0\r
- */\r
-public class SlowQueryReport extends JdbcInterceptor {\r
- protected final String[] statements = {"createStatement","prepareStatement","prepareCall"};\r
- protected final String[] executes = {"execute","executeQuery","executeUpdate","executeBatch"};\r
-\r
- public SlowQueryReport() {\r
- super();\r
- }\r
-\r
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\r
- boolean process = false;\r
- process = process(statements, method, process);\r
- if (process) {\r
- Object statement = super.invoke(proxy,method,args);\r
- CallableStatement measuredStatement =\r
- (CallableStatement)Proxy.newProxyInstance(SlowQueryReport.class.getClassLoader(),\r
- new Class[] {java.sql.CallableStatement.class,\r
- java.sql.PreparedStatement.class,\r
- java.sql.Statement.class},\r
- new StatementProxy(statement, args));\r
-\r
- return measuredStatement;\r
- } else {\r
- return super.invoke(proxy,method,args);\r
- }\r
- }\r
-\r
- protected boolean process(String[] names, Method method, boolean process) {\r
- for (int i=0; (!process) && i<names.length; i++) {\r
- process = (method.getName()==names[i]);\r
- }\r
- return process;\r
- }\r
-\r
- protected class StatementProxy implements InvocationHandler {\r
- protected Object parent;\r
- protected Object[] args;\r
- public StatementProxy(Object parent, Object[] args) {\r
- this.parent = parent;\r
- this.args = args;\r
- }\r
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\r
- if (this.parent == null ) throw new SQLException("Statement has been closed.");\r
- boolean process = false;\r
- process = process(executes, method, process);\r
- long start = (process)?System.currentTimeMillis():0;\r
- //execute the query\r
- Object result = method.invoke(parent,args);\r
- long delta = (process)?(System.currentTimeMillis()-start):0;\r
- if (delta>10) {\r
- StringBuffer out = new StringBuffer("\n\tType:");\r
- out.append(parent.getClass().getName());\r
- out.append("\n\tCreate/Prepare args:");\r
- for (int i=0; this.args!=null && i<this.args.length;i++) {\r
- out.append(this.args[i]!=null?this.args[i]:"null");\r
- out.append("; ");\r
- }\r
- out.append("\n\tExecute args:");\r
- for (int i=0; args!=null && i<args.length;i++) {\r
- out.append(args[i]!=null?args[i]:"null");\r
- out.append("; ");\r
- }\r
- System.out.println("Slow query:"+out+"\nTime to execute:"+(delta)+" ms.");\r
- }\r
- if (JdbcInterceptor.CLOSE_VAL==method.getName()) {\r
- this.parent = null;\r
- this.args = null;\r
- }\r
- return result;\r
- }\r
- }\r
-\r
- public void reset(ConnectionPool parent, PooledConnection con) {\r
-\r
- }\r
-}\r
+++ /dev/null
-/* 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.pool.jmx;\r
-/**\r
- * @author Filip Hanik\r
- */\r
-import java.util.Properties;\r
-\r
-import javax.management.DynamicMBean;\r
-\r
-import org.apache.tomcat.jdbc.pool.JdbcInterceptor;\r
-\r
-public class ConnectionPool implements ConnectionPoolMBean {\r
- protected org.apache.tomcat.jdbc.pool.ConnectionPool pool = null;\r
-\r
- public ConnectionPool(org.apache.tomcat.jdbc.pool.ConnectionPool pool) {\r
- this.pool = pool;\r
- }\r
-\r
- public org.apache.tomcat.jdbc.pool.ConnectionPool getPool() {\r
- return pool;\r
- }\r
-\r
- //=================================================================\r
- // POOL STATS\r
- //=================================================================\r
-\r
- public int getSize() {\r
- return pool.getSize();\r
- }\r
-\r
- public int getIdle() {\r
- return pool.getIdle();\r
- }\r
-\r
- public int getActive() {\r
- return pool.getActive();\r
- }\r
- \r
- public boolean isPoolSweeperEnabled() {\r
- return pool.getPoolProperties().isPoolSweeperEnabled();\r
- }\r
-\r
- //=================================================================\r
- // POOL OPERATIONS\r
- //=================================================================\r
- public void checkIdle() {\r
- pool.checkIdle();\r
- }\r
-\r
- public void checkAbandoned() {\r
- pool.checkAbandoned();\r
- }\r
-\r
- public void testIdle() {\r
- pool.testAllIdle();\r
- }\r
- //=================================================================\r
- // POOL PROPERTIES\r
- //=================================================================\r
- public Properties getDbProperties() {\r
- return pool.getPoolProperties().getDbProperties();\r
- }\r
- public String getUrl() {\r
- return pool.getPoolProperties().getUrl();\r
- }\r
- public String getDriverClassName() {\r
- return pool.getPoolProperties().getDriverClassName();\r
- }\r
- public boolean isDefaultAutoCommit() {\r
- return pool.getPoolProperties().isDefaultAutoCommit();\r
- }\r
- public boolean isDefaultReadOnly() {\r
- return pool.getPoolProperties().isDefaultReadOnly();\r
- }\r
- public int getDefaultTransactionIsolation() {\r
- return pool.getPoolProperties().getDefaultTransactionIsolation();\r
- }\r
- public String getConnectionProperties() {\r
- return pool.getPoolProperties().getConnectionProperties();\r
- }\r
- public String getDefaultCatalog() {\r
- return pool.getPoolProperties().getDefaultCatalog();\r
- }\r
- public int getInitialSize() {\r
- return pool.getPoolProperties().getInitialSize();\r
- }\r
- public int getMaxActive() {\r
- return pool.getPoolProperties().getMaxActive();\r
- }\r
- public int getMaxIdle() {\r
- return pool.getPoolProperties().getMaxIdle();\r
- }\r
- public int getMinIdle() {\r
- return pool.getPoolProperties().getMinIdle();\r
- }\r
- public int getMaxWait() {\r
- return pool.getPoolProperties().getMaxWait();\r
- }\r
- public String getValidationQuery() {\r
- return pool.getPoolProperties().getValidationQuery();\r
- }\r
- public boolean isTestOnBorrow() {\r
- return pool.getPoolProperties().isTestOnBorrow();\r
- }\r
- public boolean isTestOnReturn() {\r
- return pool.getPoolProperties().isTestOnReturn();\r
- }\r
- public boolean isTestWhileIdle() {\r
- return pool.getPoolProperties().isTestWhileIdle();\r
- }\r
- public int getTimeBetweenEvictionRunsMillis() {\r
- return pool.getPoolProperties().getTimeBetweenEvictionRunsMillis();\r
- }\r
- public int getNumTestsPerEvictionRun() {\r
- return pool.getPoolProperties().getNumTestsPerEvictionRun();\r
- }\r
- public int getMinEvictableIdleTimeMillis() {\r
- return pool.getPoolProperties().getMinEvictableIdleTimeMillis();\r
- }\r
- public boolean isAccessToUnderlyingConnectionAllowed() {\r
- return pool.getPoolProperties().isAccessToUnderlyingConnectionAllowed();\r
- }\r
- public boolean isRemoveAbandoned() {\r
- return pool.getPoolProperties().isRemoveAbandoned();\r
- }\r
- public int getRemoveAbandonedTimeout() {\r
- return pool.getPoolProperties().getRemoveAbandonedTimeout();\r
- }\r
- public boolean isLogAbandoned() {\r
- return pool.getPoolProperties().isLogAbandoned();\r
- }\r
- public int getLoginTimeout() {\r
- return pool.getPoolProperties().getLoginTimeout();\r
- }\r
- public String getName() {\r
- return pool.getPoolProperties().getName();\r
- }\r
- public String getPassword() {\r
- return pool.getPoolProperties().getPassword();\r
- }\r
- public String getUsername() {\r
- return pool.getPoolProperties().getUsername();\r
- }\r
- public long getValidationInterval() {\r
- return pool.getPoolProperties().getValidationInterval();\r
- }\r
- public String getInitSQL() {\r
- return pool.getPoolProperties().getInitSQL();\r
- }\r
- public boolean isTestOnConnect() {\r
- return pool.getPoolProperties().isTestOnConnect();\r
- }\r
- public String getJdbcInterceptors() {\r
- return pool.getPoolProperties().getJdbcInterceptors();\r
- }\r
-\r
-}\r
+++ /dev/null
-/* 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.pool.jmx;\r
-\r
-import java.util.Properties;\r
-\r
-import javax.management.DynamicMBean;\r
-\r
-import org.apache.tomcat.jdbc.pool.ConnectionPool;\r
-import org.apache.tomcat.jdbc.pool.JdbcInterceptor;\r
-\r
-public interface ConnectionPoolMBean {\r
-\r
- //=================================================================\r
- // POOL STATS\r
- //=================================================================\r
-\r
- public int getSize();\r
-\r
- public int getIdle();\r
-\r
- public int getActive();\r
- \r
- public boolean isPoolSweeperEnabled();\r
-\r
- //=================================================================\r
- // POOL OPERATIONS\r
- //=================================================================\r
- public void checkIdle();\r
-\r
- public void checkAbandoned();\r
-\r
- public void testIdle();\r
-\r
- //=================================================================\r
- // POOL PROPERTIES\r
- //=================================================================\r
- public Properties getDbProperties();\r
-\r
- public String getUrl();\r
-\r
- public String getDriverClassName();\r
-\r
- public boolean isDefaultAutoCommit();\r
-\r
- public boolean isDefaultReadOnly();\r
-\r
- public int getDefaultTransactionIsolation();\r
-\r
- public String getConnectionProperties();\r
-\r
- public String getDefaultCatalog();\r
-\r
- public int getInitialSize();\r
-\r
- public int getMaxActive();\r
-\r
- public int getMaxIdle();\r
-\r
- public int getMinIdle();\r
-\r
- public int getMaxWait();\r
-\r
- public String getValidationQuery();\r
-\r
- public boolean isTestOnBorrow();\r
-\r
- public boolean isTestOnReturn();\r
-\r
- public boolean isTestWhileIdle();\r
-\r
- public int getTimeBetweenEvictionRunsMillis();\r
-\r
- public int getNumTestsPerEvictionRun();\r
-\r
- public int getMinEvictableIdleTimeMillis();\r
-\r
- public boolean isAccessToUnderlyingConnectionAllowed();\r
-\r
- public boolean isRemoveAbandoned();\r
-\r
- public int getRemoveAbandonedTimeout();\r
-\r
- public boolean isLogAbandoned();\r
-\r
- public int getLoginTimeout();\r
-\r
- public String getName();\r
-\r
- public String getPassword();\r
-\r
- public String getUsername();\r
-\r
- public long getValidationInterval();\r
-\r
- public String getInitSQL();\r
-\r
- public boolean isTestOnConnect();\r
-\r
- public String getJdbcInterceptors();\r
-\r
-}\r
--- /dev/null
+<?xml version="1.0"?>\r
+<!--\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
+<project name="Tomcat Trunk" default="conpool" basedir="../..">\r
+\r
+\r
+ <!-- ===================== Initialize Property Values =================== -->\r
+\r
+ <!-- See "build.properties.sample" in the top level directory for all -->\r
+ <!-- property values you must customize for successful building!!! -->\r
+ <property file="${user.home}/build.properties"/>\r
+ <property file="${basedir}/build.properties"/>\r
+\r
+ <property file="${basedir}/build.properties.default"/>\r
+\r
+ <!-- Project Properties -->\r
+ <property name="name" value="Apache Tomcat" />\r
+ <property name="year" value="2007" />\r
+ <property name="version.major" value="6" />\r
+ <property name="version.minor" value="0" />\r
+ <property name="version.build" value="0" />\r
+ <property name="version.patch" value="0" />\r
+ <property name="version" value="6.0.0-dev" />\r
+ <property name="version.number" value="${version.major}.${version.minor}.${version.build}.${version.patch}" />\r
+\r
+ <property name="project" value="apache-tomcat" />\r
+ <property name="final.name" value="${project}-${version}" />\r
+ <property name="final-src.name" value="${project}-${version}-src" />\r
+\r
+ <!-- Build Defaults -->\r
+ <property name="tomcat.build" value="${basedir}/output/build"/>\r
+ <property name="tomcat.classes" value="${basedir}/output/classes"/>\r
+ <property name="tomcat.dist" value="${basedir}/output/dist"/>\r
+ <property name="tomcat.extras" value="${basedir}/output/extras"/>\r
+ <property name="tomcat.deployer" value="${basedir}/output/deployer"/>\r
+ <property name="tomcat.release" value="${basedir}/output/release"/>\r
+ <property name="test.failonerror" value="true"/>\r
+ <property name="test.runner" value="junit.textui.TestRunner"/>\r
+\r
+ <!-- Can't be lower - jsp uses templates -->\r
+ <property name="compile.source" value="1.5"/>\r
+\r
+ <!-- JAR artifacts -->\r
+ <property name="bootstrap.jar" value="${tomcat.build}/bin/bootstrap.jar"/>\r
+\r
+ <property name="annotations-api.jar" value="${tomcat.build}/lib/annotations-api.jar"/>\r
+ <property name="servlet-api.jar" value="${tomcat.build}/lib/servlet-api.jar"/>\r
+ <property name="jsp-api.jar" value="${tomcat.build}/lib/jsp-api.jar"/>\r
+ <property name="el-api.jar" value="${tomcat.build}/lib/el-api.jar"/>\r
+ <property name="catalina.jar" value="${tomcat.build}/lib/catalina.jar"/>\r
+ <property name="catalina-ant.jar" value="${tomcat.build}/lib/catalina-ant.jar"/>\r
+ <property name="tomcat-coyote.jar" value="${tomcat.build}/lib/tomcat-coyote.jar"/>\r
+\r
+ <property name="jasper.jar" value="${tomcat.build}/lib/jasper.jar"/>\r
+ <property name="jasper-el.jar" value="${tomcat.build}/lib/jasper-el.jar"/>\r
+\r
+ <property name="tomcat-dbcp.home" value="${base.path}/tomcat6-deps/dbcp" />\r
+ <property name="jasper-jdt.home" value="${base.path}/tomcat6-deps/jdt" />\r
+ <property name="tomcat-dbcp.jar" value="${tomcat-dbcp.home}/tomcat-dbcp.jar"/>\r
+ <property name="jasper-jdt.jar" value="${jasper-jdt.home}/jasper-jdt.jar"/>\r
+\r
+ <property name="tomcat-juli.jar" value="${tomcat.extras}/tomcat-juli.jar"/>\r
+ <property name="tomcat-juli-adapters.jar" value="${tomcat.extras}/tomcat-juli-adapters.jar"/>\r
+ <property name="catalina-ws.jar" value="${tomcat.extras}/catalina-ws.jar"/>\r
+\r
+ <property name="cometd-api.jar" value="${tomcat.extras}/cometd-api.jar"/>\r
+ <property name="tomcat-bayeux.jar" value="${tomcat.extras}/tomcat-bayeux.jar"/>\r
+ <property name="cometd.war" value="${tomcat.extras}/cometd.war"/>\r
+ <property name="tomcat-bayeux-samples.jar" value="${tomcat.extras}/tomcat-bayeux-samples.jar"/>\r
+\r
+ <property name="tomcat-jdbc.jar" value="${tomcat.extras}/tomcat-jdbc.jar"/>\r
+\r
+ <property name="catalina-jmx-remote.jar" value="${tomcat.extras}/catalina-jmx-remote.jar"/>\r
+ \r
+ <!-- Classpath -->\r
+ <path id="tomcat.classpath">\r
+ <pathelement location="${tomcat.classes}"/>\r
+ </path>\r
+\r
+ <target name="prepare">\r
+ <mkdir dir="${tomcat.extras}"/>\r
+ </target>\r
+\r
+ <target name="conpool">\r
+ <mkdir dir="${tomcat.extras}"/>\r
+ <path id="tomcat.jdbc.classpath">\r
+ <pathelement path="${tomcat.classpath}"/>\r
+ </path>\r
+\r
+ <!-- compile org.apache.tomcat.jdbc-->\r
+ <javac srcdir="${basedir}/modules/jdbc-pool/java" destdir="${tomcat.classes}"\r
+ debug="${compile.debug}"\r
+ deprecation="${compile.deprecation}"\r
+ source="${compile.source}"\r
+ optimize="${compile.optimize}">\r
+ <classpath refid="tomcat.jdbc.classpath"/>\r
+ <include name="org/apache/tomcat/jdbc/**" />\r
+ </javac>\r
+ \r
+ <!-- connection pool JAR File -->\r
+ <jar jarfile="${tomcat-jdbc.jar}">\r
+ <fileset dir="${tomcat.classes}">\r
+ <include name="org/apache/tomcat/jdbc/**" />\r
+ </fileset>\r
+ </jar>\r
+ <!-- create checksums -->\r
+ <checksum file="${tomcat-jdbc.jar}" forceOverwrite="yes" fileext=".md5" />\r
+ </target>\r
+\r
+ <target name="clean"> \r
+ <delete file="${tomcat-jdbc.jar}"/>\r
+ <delete file="${tomcat-jdbc.jar}.md5"/>\r
+ <delete includeemptydirs="true">\r
+ <fileset dir="${tomcat.classes}">\r
+ <include name="org/apache/tomcat/jdbc/**"/>\r
+ </fileset>\r
+ </delete>\r
+ </target>\r
+ \r
+ <!-- Download and dependency building -->\r
+ <target name="proxyflags">\r
+ <!-- check proxy parameters. -->\r
+ <condition property="useproxy">\r
+ <equals arg1="${proxy.use}" arg2="on" />\r
+ </condition>\r
+ </target>\r
+\r
+ <target name="setproxy" depends="proxyflags" if="useproxy">\r
+ <taskdef name="setproxy"\r
+ classname="org.apache.tools.ant.taskdefs.optional.net.SetProxy" />\r
+ <setproxy proxyhost="${proxy.host}" proxyport="${proxy.port}"\r
+ proxyuser="${proxy.user}" proxypassword="${proxy.password}" />\r
+ <echo message="Using ${proxy.host}:${proxy.port} to download ${sourcefile}"/>\r
+ </target>\r
+\r
+ <target name="testexist">\r
+ <echo message="Testing for ${destfile}"/>\r
+ <available file="${destfile}" property="exist"/>\r
+ </target>\r
+\r
+ <target name="downloadfile" unless="exist" depends="setproxy,testexist">\r
+ <!-- Download extract the file -->\r
+ <mkdir dir="${destdir}" />\r
+ <get src="${sourcefile}" dest="${destfile}" />\r
+ </target>\r
+ \r
+ <target name="downloadgz" unless="exist" depends="setproxy,testexist">\r
+ <!-- Download and extract the package -->\r
+ <get src="${sourcefile}" dest="${base.path}/file.tar.gz" />\r
+ <gunzip src="${base.path}/file.tar.gz" dest="${base.path}/file.tar"/>\r
+ <untar src="${base.path}/file.tar" dest="${base.path}"/>\r
+ <delete file="${base.path}/file.tar"/>\r
+ <delete file="${base.path}/file.tar.gz"/>\r
+ </target>\r
+\r
+</project>\r
--- /dev/null
+/*\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.pool;\r
+\r
+import java.lang.management.ManagementFactory;\r
+import java.lang.reflect.Constructor;\r
+import java.lang.reflect.InvocationHandler;\r
+import java.lang.reflect.Proxy;\r
+import java.sql.Connection;\r
+import java.sql.SQLException;\r
+import java.util.ConcurrentModificationException;\r
+import java.util.Iterator;\r
+import java.util.Queue;\r
+import java.util.concurrent.ArrayBlockingQueue;\r
+import java.util.concurrent.BlockingQueue;\r
+import java.util.concurrent.TimeUnit;\r
+\r
+import org.apache.juli.logging.Log;\r
+import org.apache.juli.logging.LogFactory;\r
+\r
+import org.apache.tomcat.jdbc.pool.jmx.ConnectionPoolMBean;\r
+\r
+import java.util.concurrent.atomic.AtomicInteger;\r
+\r
+import javax.management.InstanceAlreadyExistsException;\r
+import javax.management.MBeanRegistrationException;\r
+import javax.management.MBeanServer;\r
+import javax.management.MalformedObjectNameException;\r
+import javax.management.NotCompliantMBeanException;\r
+import javax.management.ObjectName;\r
+\r
+/**\r
+ * @author Filip Hanik\r
+ * @version 1.0\r
+ */\r
+\r
+public class ConnectionPool {\r
+\r
+ //logger\r
+ protected static Log log = LogFactory.getLog(ConnectionPool.class);\r
+\r
+ //===============================================================================\r
+ // INSTANCE/QUICK ACCESS VARIABLE\r
+ //===============================================================================\r
+\r
+ /**\r
+ * All the information about the connection pool\r
+ */\r
+ protected PoolProperties poolProperties;\r
+\r
+ /**\r
+ * Contains all the connections that are in use\r
+ */\r
+ protected BlockingQueue<PooledConnection> busy;\r
+\r
+ /**\r
+ * Contains all the idle connections\r
+ */\r
+ protected BlockingQueue<PooledConnection> idle;\r
+\r
+ /**\r
+ * The thread that is responsible for checking abandoned and idle threads\r
+ */\r
+ protected PoolCleaner poolCleaner;\r
+\r
+ /**\r
+ * Pool closed flag\r
+ */\r
+ protected boolean closed = false;\r
+\r
+ /**\r
+ * Size of the pool\r
+ */\r
+ protected AtomicInteger size = new AtomicInteger(0);\r
+\r
+ /**\r
+ * Since newProxyInstance performs the same operation, over and over\r
+ * again, it is much more optimized if we simply store the constructor ourselves.\r
+ */\r
+ protected Constructor proxyClassConstructor;\r
+\r
+\r
+ //===============================================================================\r
+ // PUBLIC METHODS\r
+ //===============================================================================\r
+\r
+ /**\r
+ * Instantiate a connection pool. This will create connections if initialSize is larger than 0\r
+ * @param prop PoolProperties - all the properties for this connection pool\r
+ * @throws SQLException\r
+ */\r
+ public ConnectionPool(PoolProperties prop) throws SQLException {\r
+ //setup quick access variables and pools\r
+ init(prop);\r
+ }\r
+\r
+ /**\r
+ * Borrows a connection from the pool\r
+ * @return Connection - a java.sql.Connection reflection proxy, wrapping the underlying object.\r
+ * @throws SQLException\r
+ */\r
+ public Connection getConnection() throws SQLException {\r
+ //check out a connection\r
+ PooledConnection con = (PooledConnection)borrowConnection();\r
+ JdbcInterceptor handler = con.getHandler();\r
+ if (handler==null) {\r
+ //build the proxy handler\r
+ handler = new ProxyConnection(this,con);\r
+ //set up the interceptor chain\r
+ String[] proxies = getPoolProperties().getJdbcInterceptorsAsArray();\r
+ for (int i=proxies.length-1; i>=0; i--) {\r
+ try {\r
+ JdbcInterceptor interceptor =\r
+ (JdbcInterceptor) Class.forName(proxies[i], true,\r
+ Thread.currentThread().getContextClassLoader()).newInstance();\r
+ interceptor.setNext(handler);\r
+ handler = interceptor;\r
+ }catch(Exception x) {\r
+ SQLException sx = new SQLException("Unable to instantiate interceptor chain.");\r
+ sx.initCause(x);\r
+ throw sx;\r
+ }\r
+ }\r
+ //cache handler for the next iteration\r
+ con.setHandler(handler);\r
+ } else {\r
+ JdbcInterceptor next = handler;\r
+ //we have a cached handler, reset it\r
+ while (next!=null) {\r
+ next.reset(this, con);\r
+ next = next.getNext();\r
+ }\r
+ }\r
+\r
+ try {\r
+ //cache the constructor\r
+ if (proxyClassConstructor == null ) {\r
+ Class proxyClass = Proxy.getProxyClass(ConnectionPool.class.getClassLoader(), new Class[] {java.sql.Connection.class});\r
+ proxyClassConstructor = proxyClass.getConstructor(new Class[] { InvocationHandler.class });\r
+ }\r
+ //create the proxy\r
+ //TODO possible optimization, keep track if this connection was returned properly, and don't generate a new facade\r
+ Connection connection = (Connection)proxyClassConstructor.newInstance(new Object[] { handler });\r
+ //return the connection\r
+ return connection;\r
+ }catch (Exception x) {\r
+ throw new SQLException();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Returns the name of this pool\r
+ * @return String\r
+ */\r
+ public String getName() {\r
+ return getPoolProperties().getPoolName();\r
+ }\r
+\r
+ /**\r
+ * Returns the pool properties associated with this connection pool\r
+ * @return PoolProperties\r
+ */\r
+ public PoolProperties getPoolProperties() {\r
+ return this.poolProperties;\r
+ }\r
+\r
+ /**\r
+ * Returns the total size of this pool, this includes both busy and idle connections\r
+ * @return int\r
+ */\r
+ public int getSize() {\r
+ return idle.size()+busy.size();\r
+ }\r
+\r
+ /**\r
+ * Returns the number of connections that are in use\r
+ * @return int\r
+ */\r
+ public int getActive() {\r
+ return busy.size();\r
+ }\r
+\r
+ public int getIdle() {\r
+ return idle.size();\r
+ }\r
+\r
+ /**\r
+ * Returns true if {@link #close close} has been called, and the connection pool is unusable\r
+ * @return boolean\r
+ */\r
+ public boolean isClosed() {\r
+ return this.closed;\r
+ }\r
+\r
+ @Override\r
+ protected void finalize() throws Throwable {\r
+ close(true);\r
+ }\r
+\r
+ /**\r
+ * Closes the pool and all disconnects all idle connections\r
+ * Active connections will be closed upon the {@link java.sql.Connection#close close} method is called\r
+ * on the underlying connection instead of being returned to the pool\r
+ * @param force - true to even close the active connections\r
+ */\r
+ protected void close(boolean force) {\r
+ //are we already closed\r
+ if (this.closed) return;\r
+ //prevent other threads from entering\r
+ this.closed = true;\r
+ //stop background thread\r
+ if (poolCleaner!=null) {\r
+ poolCleaner.stopRunning();\r
+ }\r
+\r
+ /* release all idle connections */\r
+ BlockingQueue<PooledConnection> pool = (idle.size()>0)?idle:(force?busy:idle);\r
+ while (pool.size()>0) {\r
+ try {\r
+ //retrieve the next connection\r
+ PooledConnection con = pool.poll(1000, TimeUnit.MILLISECONDS);\r
+ //close it and retrieve the next one, if one is available\r
+ while (con != null) {\r
+ //close the connection\r
+ if (pool==idle)\r
+ release(con);\r
+ else\r
+ abandon(con);\r
+ con = pool.poll(1000, TimeUnit.MILLISECONDS);\r
+ } //while\r
+ } catch (InterruptedException ex) {\r
+ Thread.currentThread().interrupted();\r
+ }\r
+ if (pool.size()==0 && force && pool!=busy) pool = busy;\r
+ }\r
+ size.set(0);\r
+ if (this.getPoolProperties().isJmxEnabled()) stopJmx();\r
+ } //closePool\r
+\r
+\r
+ //===============================================================================\r
+ // PROTECTED METHODS\r
+ //===============================================================================\r
+ /**\r
+ * Initialize the connection pool - called from the constructor\r
+ * @param properties PoolProperties - properties used to initialize the pool with\r
+ * @throws SQLException\r
+ */\r
+ protected void init (PoolProperties properties) throws SQLException {\r
+ poolProperties = properties;\r
+ //make space for 10 extra in case we flow over a bit\r
+ busy = new ArrayBlockingQueue<PooledConnection>(properties.getMaxActive(),false);\r
+ //make space for 10 extra in case we flow over a bit\r
+ idle = new ArrayBlockingQueue<PooledConnection>(properties.getMaxActive(),false);\r
+\r
+ //if the evictor thread is supposed to run, start it now\r
+ if (properties.isPoolSweeperEnabled()) {\r
+ poolCleaner = new PoolCleaner("[Pool-Cleaner]:" + properties.getName(), this, properties.getTimeBetweenEvictionRunsMillis());\r
+ poolCleaner.start();\r
+ } //end if\r
+\r
+ if (properties.getMaxActive()<properties.getInitialSize()) {\r
+ log.warn("initialSize is larger than maxActive, setting initialSize to: "+properties.getMaxActive());\r
+ properties.setInitialSize(properties.getMaxActive());\r
+ }\r
+ if (properties.getMinIdle()>properties.getMaxActive()) {\r
+ log.warn("minIdle is larger than maxActive, setting minIdle to: "+properties.getMaxActive());\r
+ properties.setMinIdle(properties.getMaxActive());\r
+ }\r
+ if (properties.getMaxIdle()>properties.getMaxActive()) {\r
+ log.warn("maxIdle is larger than maxActive, setting maxIdle to: "+properties.getMaxActive());\r
+ properties.setMaxIdle(properties.getMaxActive());\r
+ }\r
+ if (properties.getMaxIdle()<properties.getMinIdle()) {\r
+ log.warn("maxIdle is smaller than minIdle, setting maxIdle to: "+properties.getMinIdle());\r
+ properties.setMaxIdle(properties.getMinIdle());\r
+ }\r
+\r
+\r
+ //initialize the pool with its initial set of members\r
+ PooledConnection[] initialPool = new PooledConnection[poolProperties.getInitialSize()];\r
+ try {\r
+ for (int i = 0; i < initialPool.length; i++) {\r
+ initialPool[i] = this.borrowConnection();\r
+ } //for\r
+\r
+ } catch (SQLException x) {\r
+ close(true);\r
+ throw x;\r
+ } finally {\r
+ //return the members as idle to the pool\r
+ for (int i = 0; i < initialPool.length; i++) {\r
+ if (initialPool[i] != null) {\r
+ try {this.returnConnection(initialPool[i]);}catch(Exception x){}\r
+ } //end if\r
+ } //for\r
+ } //catch\r
+ if (this.getPoolProperties().isJmxEnabled()) startJmx();\r
+ closed = false;\r
+ }\r
+\r
+\r
+//===============================================================================\r
+// CONNECTION POOLING IMPL\r
+//===============================================================================\r
+\r
+ /**\r
+ * thread safe way to abandon a connection\r
+ * signals a connection to be abandoned.\r
+ * this will disconnect the connection, and log the stack trace if logAbanded=true\r
+ * @param con PooledConnection\r
+ */\r
+ protected void abandon(PooledConnection con) {\r
+ if (con == null)\r
+ return;\r
+ try {\r
+ con.lock();\r
+ if (getPoolProperties().isLogAbandoned()) {\r
+ log.warn("Connection has been abandoned" + con + ":" +con.getStackTrace());\r
+ }\r
+ con.abandon();\r
+ } finally {\r
+ con.unlock();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * thread safe way to release a connection\r
+ * @param con PooledConnection\r
+ */\r
+ protected void release(PooledConnection con) {\r
+ if (con == null)\r
+ return;\r
+ try {\r
+ con.lock();\r
+ con.release();\r
+ } finally {\r
+ con.unlock();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Thread safe way to retrieve a connection from the pool\r
+ * @return PooledConnection\r
+ * @throws SQLException\r
+ */\r
+ protected PooledConnection borrowConnection() throws SQLException {\r
+\r
+ if (isClosed()) {\r
+ throw new SQLException("Connection pool closed.");\r
+ } //end if\r
+\r
+ //get the current time stamp\r
+ long now = System.currentTimeMillis();\r
+ //see if there is one available immediately\r
+ PooledConnection con = idle.poll();\r
+\r
+ while (true) {\r
+ if (con!=null) {\r
+ PooledConnection result = borrowConnection(now, con);\r
+ //validation might have failed, in which case null is returned\r
+ if (result!=null) return result;\r
+ }\r
+ if (size.get() < getPoolProperties().getMaxActive()) {\r
+ if (size.addAndGet(1) <= getPoolProperties().getMaxActive()) {\r
+ return createConnection(now, con);\r
+ } else {\r
+ size.addAndGet(-1); //restore the value, we didn't create a connection\r
+ }\r
+ } //end if\r
+\r
+ //calculate wait time for this iteration\r
+ long maxWait = (getPoolProperties().getMaxWait()<=0)?Long.MAX_VALUE:getPoolProperties().getMaxWait();\r
+ long timetowait = Math.max(1, maxWait - (System.currentTimeMillis() - now));\r
+ try {\r
+ //retrieve an existing connection\r
+ con = idle.poll(timetowait, TimeUnit.MILLISECONDS);\r
+ } catch (InterruptedException ex) {\r
+ Thread.currentThread().interrupted();\r
+ }\r
+ //we didn't get a connection, lets see if we timed out\r
+ if (con == null) {\r
+ if ((System.currentTimeMillis() - now) >= maxWait) {\r
+ throw new SQLException(\r
+ "Pool empty. Unable to fetch a connection in " + (maxWait / 1000) +\r
+ " seconds, none available["+busy.size()+" in use].");\r
+ } else {\r
+ //no timeout, lets try again\r
+ continue;\r
+ }\r
+ }\r
+ } //while\r
+ }\r
+\r
+ protected PooledConnection createConnection(long now, PooledConnection con) {\r
+ //no connections where available we'll create one\r
+ boolean error = false;\r
+ try {\r
+ //connect and validate the connection\r
+ con = create();\r
+ con.lock();\r
+ if (!busy.offer(con)) {\r
+ log.debug("Connection doesn't fit into busy array, connection will not be traceable.");\r
+ }\r
+ con.connect();\r
+ if (con.validate(PooledConnection.VALIDATE_INIT)) {\r
+ //no need to lock a new one, its not contented\r
+ con.setTimestamp(now);\r
+ if (getPoolProperties().isLogAbandoned()) {\r
+ con.setStackTrace(getThreadDump());\r
+ }\r
+ return con;\r
+ } //end if\r
+ } catch (Exception e) {\r
+ error = true;\r
+ log.error("Unable to create a new JDBC connection.", e);\r
+ } finally {\r
+ if (error ) {\r
+ release(con);\r
+ busy.remove(con);\r
+ }\r
+ con.unlock();\r
+ }//catch\r
+ return null;\r
+ }\r
+\r
+ protected PooledConnection borrowConnection(long now, PooledConnection con) {\r
+ //we have a connection, lets set it up\r
+ boolean setToNull = false;\r
+ try {\r
+ con.lock();\r
+ if (con.isDiscarded()) {\r
+ //connection has already been disconnected\r
+ setToNull = true;\r
+ } else if (con.validate(PooledConnection.VALIDATE_BORROW)) {\r
+ //set the timestamp\r
+ con.setTimestamp(now);\r
+ if (getPoolProperties().isLogAbandoned()) {\r
+ //set the stack trace for this pool\r
+ con.setStackTrace(getThreadDump());\r
+ }\r
+ if (!busy.offer(con)) {\r
+ log.debug("Connection doesn't fit into busy array, connection will not be traceable.");\r
+ }\r
+ return con;\r
+ } else {\r
+ /*if the object wasn't validated, we may as well remove it*/\r
+ release(con);\r
+ setToNull = true;\r
+ } //end if\r
+ } finally {\r
+ con.unlock();\r
+ if (setToNull) {\r
+ con = null;\r
+ }\r
+ }\r
+ return con;\r
+ }\r
+\r
+ /**\r
+ * Returns a connection to the pool\r
+ * @param con PooledConnection\r
+ */\r
+ protected void returnConnection(PooledConnection con) {\r
+ if (isClosed()) {\r
+ //if the connection pool is closed\r
+ //close the connection instead of returning it\r
+ release(con);\r
+ return;\r
+ } //end if\r
+\r
+ if (con != null) {\r
+ try {\r
+ con.lock();\r
+\r
+ if (busy.remove(con)) {\r
+ if ((!con.isDiscarded()) && (!isClosed()) &&\r
+ con.validate(PooledConnection.VALIDATE_RETURN)) {\r
+ con.setStackTrace(null);\r
+ con.setTimestamp(System.currentTimeMillis());\r
+ if (!idle.offer(con)) {\r
+ if (log.isDebugEnabled()) {\r
+ log.debug("Connection ["+con+"] will be closed and not returned to the pool, idle.offer failed.");\r
+ }\r
+ release(con);\r
+ }\r
+ } else {\r
+ if (log.isDebugEnabled()) {\r
+ log.debug("Connection ["+con+"] will be closed and not returned to the pool.");\r
+ }\r
+ release(con);\r
+ } //end if\r
+ } else {\r
+ if (log.isDebugEnabled()) {\r
+ log.debug("Connection ["+con+"] will be closed and not returned to the pool, busy.remove failed.");\r
+ }\r
+ release(con);\r
+ }\r
+ } finally {\r
+ con.unlock();\r
+ }\r
+ } //end if\r
+ } //checkIn\r
+\r
+ public void checkAbandoned() {\r
+ try {\r
+ long now = System.currentTimeMillis();\r
+ Iterator<PooledConnection> locked = busy.iterator();\r
+ while (locked.hasNext()) {\r
+ PooledConnection con = locked.next();\r
+ boolean setToNull = false;\r
+ try {\r
+ con.lock();\r
+ //the con has been returned to the pool\r
+ //ignore it\r
+ if (idle.contains(con))\r
+ continue;\r
+ long time = con.getTimestamp();\r
+ if ((now - time) > con.getAbandonTimeout()) {\r
+ busy.remove(con);\r
+ abandon(con);\r
+ release(con);\r
+ setToNull = true;\r
+ } else {\r
+ //do nothing\r
+ } //end if\r
+ } finally {\r
+ con.unlock();\r
+ if (setToNull)\r
+ con = null;\r
+ }\r
+ } //while\r
+ } catch (ConcurrentModificationException e) {\r
+ log.debug("checkAbandoned failed." ,e);\r
+ } catch (Exception e) {\r
+ log.warn("checkAbandoned failed, it will be retried.",e);\r
+ }\r
+ }\r
+\r
+ public void checkIdle() {\r
+ try {\r
+ long now = System.currentTimeMillis();\r
+ Iterator<PooledConnection> unlocked = idle.iterator();\r
+ while ( (idle.size()>=getPoolProperties().getMinIdle()) && unlocked.hasNext()) {\r
+ PooledConnection con = unlocked.next();\r
+ boolean setToNull = false;\r
+ try {\r
+ con.lock();\r
+ //the con been taken out, we can't clean it up\r
+ if (busy.contains(con))\r
+ continue;\r
+ long time = con.getTimestamp();\r
+ if (((now - time) > con.getReleaseTime()) && (getSize()>getPoolProperties().getMinIdle())) {\r
+ release(con);\r
+ idle.remove(con);\r
+ setToNull = true;\r
+ } else {\r
+ //do nothing\r
+ } //end if\r
+ } finally {\r
+ con.unlock();\r
+ if (setToNull)\r
+ con = null;\r
+ }\r
+ } //while\r
+ } catch (ConcurrentModificationException e) {\r
+ log.debug("checkIdle failed." ,e);\r
+ } catch (Exception e) {\r
+ log.warn("checkIdle failed, it will be retried.",e);\r
+ }\r
+\r
+ }\r
+\r
+ public void testAllIdle() {\r
+ try {\r
+ Iterator<PooledConnection> unlocked = idle.iterator();\r
+ while (unlocked.hasNext()) {\r
+ PooledConnection con = unlocked.next();\r
+ try {\r
+ con.lock();\r
+ //the con been taken out, we can't clean it up\r
+ if (busy.contains(con))\r
+ continue;\r
+ if (!con.validate(PooledConnection.VALIDATE_IDLE)) {\r
+ idle.remove(con);\r
+ con.release();\r
+ }\r
+ } finally {\r
+ con.unlock();\r
+ }\r
+ } //while\r
+ } catch (ConcurrentModificationException e) {\r
+ log.debug("testAllIdle failed." ,e);\r
+ } catch (Exception e) {\r
+ log.warn("testAllIdle failed, it will be retried.",e);\r
+ }\r
+\r
+ }\r
+\r
+\r
+ protected static String getThreadDump() {\r
+ Exception x = new Exception();\r
+ x.fillInStackTrace();\r
+ return getStackTrace(x);\r
+ }\r
+\r
+ protected static String getStackTrace(Exception x) {\r
+ if (x == null) {\r
+ return null;\r
+ } else {\r
+ java.io.ByteArrayOutputStream bout = new java.io.ByteArrayOutputStream();\r
+ java.io.PrintStream writer = new java.io.PrintStream(bout);\r
+ x.printStackTrace(writer);\r
+ String result = bout.toString();\r
+ return result;\r
+ } //end if\r
+ }\r
+\r
+\r
+ protected PooledConnection create() throws java.lang.Exception {\r
+ PooledConnection con = new PooledConnection(getPoolProperties(), this);\r
+ return con;\r
+ }\r
+\r
+ protected void finalize(PooledConnection con) {\r
+ size.addAndGet(-1);\r
+ }\r
+\r
+ public void startJmx() {\r
+ try {\r
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();\r
+ ObjectName name = new ObjectName("org.apache.tomcat.jdbc.pool.jmx:type=ConnectionPool,name="+getName());\r
+ mbs.registerMBean(new org.apache.tomcat.jdbc.pool.jmx.ConnectionPool(this), name);\r
+ } catch (Exception x) {\r
+ log.warn("Unable to start JMX integration for connection pool. Instance["+getName()+"] can't be monitored.",x);\r
+ }\r
+ }\r
+\r
+ public void stopJmx() {\r
+ try {\r
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();\r
+ ObjectName name = new ObjectName("org.apache.tomcat.jdbc.pool.jmx:type=ConnectionPool,name="+getName());\r
+ mbs.unregisterMBean(name);\r
+ }catch (Exception x) {\r
+ log.warn("Unable to stop JMX integration for connection pool. Instance["+getName()+"].",x);\r
+ }\r
+ }\r
+\r
+\r
+ protected class PoolCleaner extends Thread {\r
+ protected ConnectionPool pool;\r
+ protected long sleepTime;\r
+ protected boolean run = true;\r
+ PoolCleaner(String name, ConnectionPool pool, long sleepTime) {\r
+ super(name);\r
+ this.setDaemon(true);\r
+ this.pool = pool;\r
+ this.sleepTime = sleepTime;\r
+ if (sleepTime <= 0) {\r
+ pool.log.warn("Database connection pool evicter thread interval is set to 0, defaulting to 30 seconds");\r
+ this.sleepTime = 1000 * 30;\r
+ } else if (sleepTime < 1000) {\r
+ pool.log.warn("Database connection pool evicter thread interval is set to lower than 1 second.");\r
+ }\r
+ }\r
+\r
+ public void run() {\r
+ while (run) {\r
+ try {\r
+ sleep(sleepTime);\r
+ } catch (InterruptedException e) {\r
+ // ignore it\r
+ Thread.currentThread().interrupted();\r
+ continue;\r
+ } //catch\r
+\r
+ if (pool.isClosed()) {\r
+ if (pool.getSize() <= 0) {\r
+ run = false;\r
+ }\r
+ } else {\r
+ try {\r
+ if (pool.getPoolProperties().isRemoveAbandoned())\r
+ pool.checkAbandoned();\r
+ if (pool.getPoolProperties().getMaxIdle()<pool.idle.size())\r
+ pool.checkIdle();\r
+ if (pool.getPoolProperties().isTestWhileIdle())\r
+ pool.testAllIdle();\r
+ } catch (Exception x) {\r
+ pool.log.error("", x);\r
+ } //catch\r
+ } //end if\r
+ } //while\r
+ } //run\r
+\r
+ public void stopRunning() {\r
+ run = false;\r
+ interrupt();\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/*\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.pool;\r
+\r
+\r
+/**\r
+ * A DataSource that can be instantiated through IoC and implements the DataSource interface\r
+ * since the DataSourceProxy is used as a generic proxy\r
+ * @author Filip Hanik\r
+ * @version 1.0\r
+ */\r
+public class DataSource extends DataSourceProxy implements javax.sql.DataSource {\r
+\r
+}\r
--- /dev/null
+/*\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.pool;\r
+\r
+\r
+import java.io.ByteArrayInputStream;\r
+import java.lang.reflect.InvocationHandler;\r
+import java.lang.reflect.Method;\r
+import java.lang.reflect.Proxy;\r
+import java.sql.Connection;\r
+import java.util.HashMap;\r
+import java.util.Hashtable;\r
+import java.util.Properties;\r
+\r
+import javax.naming.Context;\r
+import javax.naming.Name;\r
+import javax.naming.RefAddr;\r
+import javax.naming.Reference;\r
+import javax.naming.spi.ObjectFactory;\r
+import javax.sql.DataSource;\r
+\r
+import org.apache.juli.logging.Log;\r
+import org.apache.juli.logging.LogFactory;\r
+\r
+/**\r
+ * <p>JNDI object factory that creates an instance of\r
+ * <code>BasicDataSource</code> that has been configured based on the\r
+ * <code>RefAddr</code> values of the specified <code>Reference</code>,\r
+ * which must match the names and data types of the\r
+ * <code>BasicDataSource</code> bean properties.</p>\r
+ * <br/>\r
+ * Properties available for configuration:<br/>\r
+ * <a href="http://commons.apache.org/dbcp/configuration.html">Commons DBCP properties</a><br/>\r
+ *<ol>\r
+ * <li>initSQL - A query that gets executed once, right after the connection is established.</li>\r
+ * <li>testOnConnect - run validationQuery after connection has been established.</li>\r
+ * <li>validationInterval - avoid excess validation, only run validation at most at this frequency - time in milliseconds.</li>\r
+ * <li>jdbcInterceptors - a semicolon separated list of classnames extending {@link JdbcInterceptor} class.</li>\r
+ * <li>jmxEnabled - true of false, whether to register the pool with JMX.</li>\r
+ *</ol>\r
+ * @author Craig R. McClanahan\r
+ * @author Dirk Verbeeck\r
+ * @author Filip Hanik\r
+ */\r
+public class DataSourceFactory implements ObjectFactory {\r
+ protected static Log log = LogFactory.getLog(DataSourceFactory.class);\r
+\r
+ protected final static String PROP_DEFAULTAUTOCOMMIT = "defaultAutoCommit";\r
+ protected final static String PROP_DEFAULTREADONLY = "defaultReadOnly";\r
+ protected final static String PROP_DEFAULTTRANSACTIONISOLATION = "defaultTransactionIsolation";\r
+ protected final static String PROP_DEFAULTCATALOG = "defaultCatalog";\r
+ \r
+ protected final static String PROP_DRIVERCLASSNAME = "driverClassName";\r
+ protected final static String PROP_PASSWORD = "password";\r
+ protected final static String PROP_URL = "url";\r
+ protected final static String PROP_USERNAME = "username";\r
+\r
+ protected final static String PROP_MAXACTIVE = "maxActive";\r
+ protected final static String PROP_MAXIDLE = "maxIdle";\r
+ protected final static String PROP_MINIDLE = "minIdle";\r
+ protected final static String PROP_INITIALSIZE = "initialSize";\r
+ protected final static String PROP_MAXWAIT = "maxWait";\r
+ \r
+ protected final static String PROP_TESTONBORROW = "testOnBorrow";\r
+ protected final static String PROP_TESTONRETURN = "testOnReturn";\r
+ protected final static String PROP_TESTWHILEIDLE = "testWhileIdle";\r
+ protected final static String PROP_TESTONCONNECT = "testOnConnect";\r
+ protected final static String PROP_VALIDATIONQUERY = "validationQuery";\r
+ \r
+ protected final static String PROP_TIMEBETWEENEVICTIONRUNSMILLIS = "timeBetweenEvictionRunsMillis";\r
+ protected final static String PROP_NUMTESTSPEREVICTIONRUN = "numTestsPerEvictionRun";\r
+ protected final static String PROP_MINEVICTABLEIDLETIMEMILLIS = "minEvictableIdleTimeMillis";\r
+ \r
+ protected final static String PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED = "accessToUnderlyingConnectionAllowed";\r
+ \r
+ protected final static String PROP_REMOVEABANDONED = "removeAbandoned";\r
+ protected final static String PROP_REMOVEABANDONEDTIMEOUT = "removeAbandonedTimeout";\r
+ protected final static String PROP_LOGABANDONED = "logAbandoned";\r
+ \r
+ protected final static String PROP_POOLPREPAREDSTATEMENTS = "poolPreparedStatements";\r
+ protected final static String PROP_MAXOPENPREPAREDSTATEMENTS = "maxOpenPreparedStatements";\r
+ protected final static String PROP_CONNECTIONPROPERTIES = "connectionProperties";\r
+ \r
+ protected final static String PROP_INITSQL = "initSQL";\r
+ protected final static String PROP_INTERCEPTORS = "jdbcInterceptors";\r
+ protected final static String PROP_VALIDATIONINTERVAL = "validationInterval";\r
+ protected final static String PROP_JMX_ENABLED = "jmxEnabled";\r
+ \r
+ public static final int UNKNOWN_TRANSACTIONISOLATION = -1;\r
+\r
+\r
+ protected final static String[] ALL_PROPERTIES = {\r
+ PROP_DEFAULTAUTOCOMMIT,\r
+ PROP_DEFAULTREADONLY,\r
+ PROP_DEFAULTTRANSACTIONISOLATION,\r
+ PROP_DEFAULTCATALOG,\r
+ PROP_DRIVERCLASSNAME,\r
+ PROP_MAXACTIVE,\r
+ PROP_MAXIDLE,\r
+ PROP_MINIDLE,\r
+ PROP_INITIALSIZE,\r
+ PROP_MAXWAIT,\r
+ PROP_TESTONBORROW,\r
+ PROP_TESTONRETURN,\r
+ PROP_TIMEBETWEENEVICTIONRUNSMILLIS,\r
+ PROP_NUMTESTSPEREVICTIONRUN,\r
+ PROP_MINEVICTABLEIDLETIMEMILLIS,\r
+ PROP_TESTWHILEIDLE,\r
+ PROP_TESTONCONNECT,\r
+ PROP_PASSWORD,\r
+ PROP_URL,\r
+ PROP_USERNAME,\r
+ PROP_VALIDATIONQUERY,\r
+ PROP_VALIDATIONINTERVAL,\r
+ PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED,\r
+ PROP_REMOVEABANDONED,\r
+ PROP_REMOVEABANDONEDTIMEOUT,\r
+ PROP_LOGABANDONED,\r
+ PROP_POOLPREPAREDSTATEMENTS,\r
+ PROP_MAXOPENPREPAREDSTATEMENTS,\r
+ PROP_CONNECTIONPROPERTIES,\r
+ PROP_INITSQL,\r
+ PROP_INTERCEPTORS,\r
+ PROP_JMX_ENABLED\r
+ };\r
+\r
+ // -------------------------------------------------- ObjectFactory Methods\r
+\r
+ /**\r
+ * <p>Create and return a new <code>BasicDataSource</code> instance. If no\r
+ * instance can be created, return <code>null</code> instead.</p>\r
+ *\r
+ * @param obj The possibly null object containing location or\r
+ * reference information that can be used in creating an object\r
+ * @param name The name of this object relative to <code>nameCtx</code>\r
+ * @param nameCtx The context relative to which the <code>name</code>\r
+ * parameter is specified, or <code>null</code> if <code>name</code>\r
+ * is relative to the default initial context\r
+ * @param environment The possibly null environment that is used in\r
+ * creating this object\r
+ *\r
+ * @exception Exception if an exception occurs creating the instance\r
+ */\r
+ public Object getObjectInstance(Object obj, Name name, Context nameCtx,\r
+ Hashtable environment) throws Exception {\r
+\r
+ // We only know how to deal with <code>javax.naming.Reference</code>s\r
+ // that specify a class name of "javax.sql.DataSource"\r
+ if ((obj == null) || !(obj instanceof Reference)) {\r
+ return null;\r
+ }\r
+ Reference ref = (Reference) obj;\r
+ if (!"javax.sql.DataSource".equals(ref.getClassName())) {\r
+ return null;\r
+ }\r
+\r
+ Properties properties = new Properties();\r
+ for (int i = 0; i < ALL_PROPERTIES.length; i++) {\r
+ String propertyName = ALL_PROPERTIES[i];\r
+ RefAddr ra = ref.get(propertyName);\r
+ if (ra != null) {\r
+ String propertyValue = ra.getContent().toString();\r
+ properties.setProperty(propertyName, propertyValue);\r
+ }\r
+ }\r
+\r
+ return createDataSource(properties);\r
+ }\r
+\r
+ /**\r
+ * Creates and configures a {@link BasicDataSource} instance based on the\r
+ * given properties.\r
+ *\r
+ * @param properties the datasource configuration properties\r
+ * @throws Exception if an error occurs creating the data source\r
+ */\r
+ public static DataSource createDataSource(Properties properties) throws Exception {\r
+ org.apache.tomcat.jdbc.pool.DataSourceProxy dataSource = new org.apache.tomcat.jdbc.pool.DataSourceProxy();\r
+\r
+ String value = null;\r
+\r
+ value = properties.getProperty(PROP_DEFAULTAUTOCOMMIT);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setDefaultAutoCommit(Boolean.valueOf(value));\r
+ }\r
+\r
+ value = properties.getProperty(PROP_DEFAULTREADONLY);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setDefaultReadOnly(Boolean.valueOf(value));\r
+ }\r
+\r
+ value = properties.getProperty(PROP_DEFAULTTRANSACTIONISOLATION);\r
+ if (value != null) {\r
+ int level = UNKNOWN_TRANSACTIONISOLATION;\r
+ if ("NONE".equalsIgnoreCase(value)) {\r
+ level = Connection.TRANSACTION_NONE;\r
+ } else if ("READ_COMMITTED".equalsIgnoreCase(value)) {\r
+ level = Connection.TRANSACTION_READ_COMMITTED;\r
+ } else if ("READ_UNCOMMITTED".equalsIgnoreCase(value)) {\r
+ level = Connection.TRANSACTION_READ_UNCOMMITTED;\r
+ } else if ("REPEATABLE_READ".equalsIgnoreCase(value)) {\r
+ level = Connection.TRANSACTION_REPEATABLE_READ;\r
+ } else if ("SERIALIZABLE".equalsIgnoreCase(value)) {\r
+ level = Connection.TRANSACTION_SERIALIZABLE;\r
+ } else {\r
+ try {\r
+ level = Integer.parseInt(value);\r
+ } catch (NumberFormatException e) {\r
+ System.err.println("Could not parse defaultTransactionIsolation: " + value);\r
+ System.err.println("WARNING: defaultTransactionIsolation not set");\r
+ System.err.println("using default value of database driver");\r
+ level = UNKNOWN_TRANSACTIONISOLATION;\r
+ }\r
+ }\r
+ dataSource.getPoolProperties().setDefaultTransactionIsolation(level);\r
+ }\r
+\r
+ value = properties.getProperty(PROP_DEFAULTCATALOG);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setDefaultCatalog(value);\r
+ }\r
+\r
+ value = properties.getProperty(PROP_DRIVERCLASSNAME);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setDriverClassName(value);\r
+ }\r
+\r
+ value = properties.getProperty(PROP_MAXACTIVE);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setMaxActive(Integer.parseInt(value));\r
+ }\r
+\r
+ value = properties.getProperty(PROP_MAXIDLE);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setMaxIdle(Integer.parseInt(value));\r
+ }\r
+\r
+ value = properties.getProperty(PROP_MINIDLE);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setMinIdle(Integer.parseInt(value));\r
+ }\r
+\r
+ value = properties.getProperty(PROP_INITIALSIZE);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setInitialSize(Integer.parseInt(value));\r
+ }\r
+\r
+ value = properties.getProperty(PROP_MAXWAIT);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setMaxWait(Integer.parseInt(value));\r
+ }\r
+\r
+ value = properties.getProperty(PROP_TESTONBORROW);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setTestOnBorrow(Boolean.valueOf(value).booleanValue());\r
+ }\r
+\r
+ value = properties.getProperty(PROP_TESTONRETURN);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setTestOnReturn(Boolean.valueOf(value).booleanValue());\r
+ }\r
+\r
+ value = properties.getProperty(PROP_TESTONCONNECT);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setTestOnConnect(Boolean.valueOf(value).booleanValue());\r
+ }\r
+\r
+ value = properties.getProperty(PROP_TIMEBETWEENEVICTIONRUNSMILLIS);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setTimeBetweenEvictionRunsMillis(Integer.parseInt(value));\r
+ }\r
+\r
+ value = properties.getProperty(PROP_NUMTESTSPEREVICTIONRUN);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setNumTestsPerEvictionRun(Integer.parseInt(value));\r
+ }\r
+\r
+ value = properties.getProperty(PROP_MINEVICTABLEIDLETIMEMILLIS);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setMinEvictableIdleTimeMillis(Integer.parseInt(value));\r
+ }\r
+\r
+ value = properties.getProperty(PROP_TESTWHILEIDLE);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setTestWhileIdle(Boolean.valueOf(value).booleanValue());\r
+ }\r
+\r
+ value = properties.getProperty(PROP_PASSWORD);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setPassword(value);\r
+ }\r
+\r
+ value = properties.getProperty(PROP_URL);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setUrl(value);\r
+ }\r
+\r
+ value = properties.getProperty(PROP_USERNAME);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setUsername(value);\r
+ }\r
+\r
+ value = properties.getProperty(PROP_VALIDATIONQUERY);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setValidationQuery(value);\r
+ }\r
+\r
+ value = properties.getProperty(PROP_VALIDATIONINTERVAL);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setValidationInterval(Long.parseLong(value));\r
+ }\r
+\r
+ value = properties.getProperty(PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().\r
+ setAccessToUnderlyingConnectionAllowed(Boolean.valueOf(value).booleanValue());\r
+ }\r
+\r
+ value = properties.getProperty(PROP_REMOVEABANDONED);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setRemoveAbandoned(Boolean.valueOf(value).booleanValue());\r
+ }\r
+\r
+ value = properties.getProperty(PROP_REMOVEABANDONEDTIMEOUT);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setRemoveAbandonedTimeout(Integer.parseInt(value));\r
+ }\r
+\r
+ value = properties.getProperty(PROP_LOGABANDONED);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setLogAbandoned(Boolean.valueOf(value).booleanValue());\r
+ }\r
+\r
+ value = properties.getProperty(PROP_POOLPREPAREDSTATEMENTS);\r
+ if (value != null) {\r
+ log.warn(PROP_POOLPREPAREDSTATEMENTS + " is not a valid setting, it will have no effect.");\r
+ }\r
+\r
+ value = properties.getProperty(PROP_MAXOPENPREPAREDSTATEMENTS);\r
+ if (value != null) {\r
+ log.warn(PROP_MAXOPENPREPAREDSTATEMENTS + " is not a valid setting, it will have no effect.");\r
+ }\r
+\r
+ value = properties.getProperty(PROP_CONNECTIONPROPERTIES);\r
+ if (value != null) {\r
+ Properties p = getProperties(value);\r
+ dataSource.getPoolProperties().setDbProperties(p);\r
+ } else {\r
+ dataSource.getPoolProperties().setDbProperties(new Properties());\r
+ }\r
+\r
+ dataSource.getPoolProperties().getDbProperties().setProperty("user",dataSource.getPoolProperties().getUsername());\r
+ dataSource.getPoolProperties().getDbProperties().setProperty("password",dataSource.getPoolProperties().getPassword());\r
+\r
+ value = properties.getProperty(PROP_INITSQL);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setInitSQL(value);\r
+ }\r
+\r
+ value = properties.getProperty(PROP_INTERCEPTORS);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setJdbcInterceptors(value);\r
+ }\r
+\r
+ value = properties.getProperty(PROP_JMX_ENABLED);\r
+ if (value != null) {\r
+ dataSource.getPoolProperties().setJmxEnabled(Boolean.parseBoolean(value));\r
+ }\r
+\r
+ // Return the configured DataSource instance\r
+ DataSource ds = getDataSource(dataSource);\r
+ return ds;\r
+ }\r
+\r
+ public static DataSource getDataSource(org.apache.tomcat.jdbc.pool.DataSourceProxy dataSource) {\r
+ DataSourceHandler handler = new DataSourceHandler(dataSource);\r
+ DataSource ds = (DataSource)Proxy.newProxyInstance(DataSourceFactory.class.getClassLoader(), new Class[] {javax.sql.DataSource.class}, handler);\r
+ return ds;\r
+ }\r
+\r
+ /**\r
+ * <p>Parse properties from the string. Format of the string must be [propertyName=property;]*<p>\r
+ * @param propText\r
+ * @return Properties\r
+ * @throws Exception\r
+ */\r
+ static protected Properties getProperties(String propText) throws Exception {\r
+ Properties p = new Properties();\r
+ if (propText != null) {\r
+ p.load(new ByteArrayInputStream(propText.replace(';', '\n').\r
+ getBytes()));\r
+ }\r
+ return p;\r
+ }\r
+\r
+ protected static class DataSourceHandler implements InvocationHandler {\r
+ protected org.apache.tomcat.jdbc.pool.DataSourceProxy datasource = null;\r
+ protected static HashMap<Method,Method> methods = new HashMap<Method,Method>();\r
+ public DataSourceHandler(org.apache.tomcat.jdbc.pool.DataSourceProxy ds) {\r
+ this.datasource = ds;\r
+ }\r
+\r
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\r
+ Method m = methods.get(method);\r
+ if (m==null) {\r
+ m = datasource.getClass().getMethod(method.getName(), method.getParameterTypes());\r
+ methods.put(method, m);\r
+ }\r
+ return m.invoke(datasource, args);\r
+ }\r
+\r
+ }\r
+}\r
--- /dev/null
+/*\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.pool;\r
+\r
+import java.io.PrintWriter;\r
+import java.sql.Connection;\r
+import java.sql.SQLException;\r
+import java.util.Iterator;\r
+\r
+import org.apache.juli.logging.Log;\r
+import org.apache.juli.logging.LogFactory;\r
+\r
+/**\r
+ *\r
+ * <p>Title: Uber Pool</p>\r
+ *\r
+ * <p>Description: A simple, yet efficient and powerful connection pool</p>\r
+ *\r
+ * <p>Copyright: Copyright (c) 2008 Filip Hanik</p>\r
+ *\r
+ * <p> </p>\r
+ *\r
+ * @author Filip Hanik\r
+ * @version 1.0\r
+ */\r
+\r
+public class DataSourceProxy {\r
+ protected static Log log = LogFactory.getLog(DataSourceProxy.class);\r
+ \r
+ protected Driver driver;\r
+ protected PoolProperties poolProperties = new PoolProperties();\r
+\r
+ public DataSourceProxy() {\r
+ }\r
+\r
+\r
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {\r
+ // we are not a wrapper of anything\r
+ return false;\r
+ }\r
+\r
+\r
+ public <T> T unwrap(Class<T> iface) throws SQLException {\r
+ //we can't unwrap anything\r
+ return null;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ public Connection getConnection(String username, String password) throws SQLException {\r
+ return getConnection();\r
+ }\r
+\r
+ public PoolProperties getPoolProperties() {\r
+ return poolProperties;\r
+ }\r
+\r
+ /**\r
+ * Sets up the connection pool, by creating a pooling driver.\r
+ * @return Driver\r
+ * @throws SQLException\r
+ */\r
+ public synchronized Driver createDriver() throws SQLException {\r
+ if (driver != null) {\r
+ return driver;\r
+ } else {\r
+ driver = new org.apache.tomcat.jdbc.pool.Driver(getPoolProperties());\r
+ return driver;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+\r
+ public Connection getConnection() throws SQLException {\r
+ if (driver == null)\r
+ driver = createDriver();\r
+ return driver.connect(poolProperties.getPoolName(), null);\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ public PooledConnection getPooledConnection() throws SQLException {\r
+ return (PooledConnection) getConnection();\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ public PooledConnection getPooledConnection(String username,\r
+ String password) throws SQLException {\r
+ return (PooledConnection) getConnection();\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ public PrintWriter getLogWriter() throws SQLException {\r
+ return null;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ public void setLogWriter(PrintWriter out) throws SQLException {\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ public int getLoginTimeout() {\r
+ if (poolProperties == null) {\r
+ return 0;\r
+ } else {\r
+ return poolProperties.getMaxWait() / 1000;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ public void setLoginTimeout(int i) {\r
+ if (poolProperties == null) {\r
+ return;\r
+ } else {\r
+ poolProperties.setMaxWait(1000 * i);\r
+ }\r
+\r
+ }\r
+\r
+\r
+ public void close() {\r
+ close(false);\r
+ }\r
+ public void close(boolean all) {\r
+ try {\r
+ if (driver != null) {\r
+ Driver d = driver;\r
+ driver = null;\r
+ d.closePool(poolProperties.getPoolName(), all);\r
+ }\r
+ }catch (Exception x) {\r
+ x.printStackTrace();\r
+ }\r
+ }\r
+\r
+ protected void finalize() throws Throwable {\r
+ //terminate the pool?\r
+ close(true);\r
+ }\r
+\r
+ public int getPoolSize() throws SQLException{\r
+ if (driver == null)\r
+ driver = createDriver();\r
+ return driver.getPool(getPoolProperties().getPoolName()).getSize();\r
+ }\r
+\r
+ public String toString() {\r
+ return super.toString()+"{"+getPoolProperties()+"}";\r
+ }\r
+\r
+/*-----------------------------------------------------------------------*/\r
+// PROPERTIES WHEN NOT USED WITH FACTORY\r
+/*------------------------------------------------------------------------*/\r
+ public void setPoolProperties(PoolProperties poolProperties) {\r
+ this.poolProperties = poolProperties;\r
+ }\r
+\r
+ public void setDriverClassName(String driverClassName) {\r
+ this.poolProperties.setDriverClassName(driverClassName);\r
+ }\r
+\r
+ public void setInitialSize(int initialSize) {\r
+ this.poolProperties.setInitialSize(initialSize);\r
+ }\r
+\r
+ public void setInitSQL(String initSQL) {\r
+ this.poolProperties.setInitSQL(initSQL);\r
+ }\r
+\r
+ public void setLogAbandoned(boolean logAbandoned) {\r
+ this.poolProperties.setLogAbandoned(logAbandoned);\r
+ }\r
+\r
+ public void setMaxActive(int maxActive) {\r
+ this.poolProperties.setMaxIdle(maxActive);\r
+ }\r
+\r
+ public void setMaxIdle(int maxIdle) {\r
+ this.poolProperties.setMaxIdle(maxIdle);\r
+ }\r
+\r
+ public void setMaxWait(int maxWait) {\r
+ this.poolProperties.setMaxWait(maxWait);\r
+ }\r
+\r
+ public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) {\r
+ this.poolProperties.setMinEvictableIdleTimeMillis(\r
+ minEvictableIdleTimeMillis);\r
+ }\r
+\r
+ public void setMinIdle(int minIdle) {\r
+ this.setMinIdle(minIdle);\r
+ }\r
+\r
+ public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {\r
+ this.poolProperties.setNumTestsPerEvictionRun(numTestsPerEvictionRun);\r
+ }\r
+\r
+ public void setPassword(String password) {\r
+ this.poolProperties.setPassword(password);\r
+ this.poolProperties.getDbProperties().setProperty("password",this.poolProperties.getPassword());\r
+ }\r
+\r
+ public void setRemoveAbandoned(boolean removeAbandoned) {\r
+ this.poolProperties.setRemoveAbandoned(removeAbandoned);\r
+ }\r
+\r
+ public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) {\r
+ this.poolProperties.setRemoveAbandonedTimeout(removeAbandonedTimeout);\r
+ }\r
+\r
+ public void setTestOnBorrow(boolean testOnBorrow) {\r
+ this.poolProperties.setTestOnBorrow(testOnBorrow);\r
+ }\r
+\r
+ public void setTestOnConnect(boolean testOnConnect) {\r
+ this.poolProperties.setTestOnConnect(testOnConnect);\r
+ }\r
+\r
+ public void setTestOnReturn(boolean testOnReturn) {\r
+ this.poolProperties.setTestOnReturn(testOnReturn);\r
+ }\r
+\r
+ public void setTestWhileIdle(boolean testWhileIdle) {\r
+ this.poolProperties.setTestWhileIdle(testWhileIdle);\r
+ }\r
+\r
+ public void setTimeBetweenEvictionRunsMillis(int\r
+ timeBetweenEvictionRunsMillis) {\r
+ this.poolProperties.setTimeBetweenEvictionRunsMillis(\r
+ timeBetweenEvictionRunsMillis);\r
+ }\r
+\r
+ public void setUrl(String url) {\r
+ this.poolProperties.setUrl(url);\r
+ }\r
+\r
+ public void setUsername(String username) {\r
+ this.poolProperties.setUsername(username);\r
+ this.poolProperties.getDbProperties().setProperty("user",getPoolProperties().getUsername());\r
+ }\r
+\r
+ public void setValidationInterval(long validationInterval) {\r
+ this.poolProperties.setValidationInterval(validationInterval);\r
+ }\r
+\r
+ public void setValidationQuery(String validationQuery) {\r
+ this.poolProperties.setValidationQuery(validationQuery);\r
+ }\r
+\r
+ public void setJdbcInterceptors(String interceptors) {\r
+ this.getPoolProperties().setJdbcInterceptors(interceptors);\r
+ }\r
+\r
+ public void setJmxEnabled(boolean enabled) {\r
+ this.getPoolProperties().setJmxEnabled(enabled);\r
+ }\r
+ \r
+ public void setConnectionProperties(String properties) {\r
+ try {\r
+ java.util.Properties prop = DataSourceFactory.getProperties(properties);\r
+ Iterator i = prop.keySet().iterator();\r
+ while (i.hasNext()) {\r
+ String key = (String)i.next();\r
+ String value = prop.getProperty(key);\r
+ getPoolProperties().getDbProperties().setProperty(key, value);\r
+ }\r
+ \r
+ }catch (Exception x) {\r
+ log.error("Unable to parse connection properties.", x);\r
+ throw new RuntimeException(x);\r
+ }\r
+ }\r
+\r
+\r
+}\r
--- /dev/null
+/*\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.pool;\r
+\r
+\r
+import java.sql.Connection;\r
+import java.sql.DriverPropertyInfo;\r
+import java.sql.SQLException;\r
+import java.util.HashMap;\r
+import java.util.Properties;\r
+\r
+import org.apache.juli.logging.Log;\r
+import org.apache.juli.logging.LogFactory;\r
+/**\r
+ * @author Filip Hanik\r
+ * @version 1.0\r
+ */\r
+public class Driver implements java.sql.Driver {\r
+\r
+ protected static Log log = LogFactory.getLog(Driver.class);\r
+\r
+ protected static HashMap pooltable = new HashMap(11);\r
+\r
+ public Driver() throws SQLException {\r
+ }\r
+\r
+ public Driver(PoolProperties properties) throws SQLException {\r
+ init(properties);\r
+ } //Driver\r
+\r
+ public void init(PoolProperties properties) throws SQLException {\r
+ if (pooltable.get(properties.getPoolName()) != null)\r
+ throw new SQLException("Pool identified by:" + properties.getPoolName() + " already exists.");\r
+ ConnectionPool pool = new ConnectionPool(properties);\r
+ pooltable.put(properties.getPoolName(), pool);\r
+ }\r
+\r
+ public void closePool(String url, boolean all) throws SQLException {\r
+ ConnectionPool pool = (ConnectionPool) pooltable.get(url);\r
+ if (pool == null) {\r
+ throw new SQLException("No connection pool established for URL:" + url);\r
+ } else {\r
+ pool.close(all);\r
+ }\r
+ pooltable.remove(url);\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ public Connection connect(String url, Properties info) throws SQLException {\r
+ ConnectionPool pool = (ConnectionPool) pooltable.get(url);\r
+ if (pool == null) {\r
+ throw new SQLException("No connection pool established for URL:" + url);\r
+ } else {\r
+ try {\r
+ return pool.getConnection();\r
+ } catch (SQLException forward) {\r
+ throw forward;\r
+ } catch (Exception e) {\r
+ throw new SQLException("Unknow pool exception:" + ConnectionPool.getStackTrace(e));\r
+ } //catch\r
+ } //end if\r
+ } //connect\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ public boolean acceptsURL(String url) throws SQLException {\r
+ /* check if the driver has a connection pool with that name */\r
+ return (pooltable.get(url) != null ? true : false);\r
+ } //acceptsUrl\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws\r
+ SQLException {\r
+ return new DriverPropertyInfo[0];\r
+ } //getPropertyInfo\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ public int getMajorVersion() {\r
+ return 1;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ public int getMinorVersion() {\r
+ return 0;\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ public boolean jdbcCompliant() {\r
+ return true;\r
+ }\r
+\r
+ public ConnectionPool getPool(String url) throws SQLException {\r
+ return (ConnectionPool) pooltable.get(url);\r
+ }\r
+\r
+} //class\r
--- /dev/null
+/*\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.pool;\r
+\r
+import java.lang.reflect.InvocationHandler;\r
+import java.lang.reflect.Method;\r
+\r
+/**\r
+ * @author Filip Hanik\r
+ * @version 1.0\r
+ */\r
+public abstract class JdbcInterceptor implements InvocationHandler {\r
+ public static final String CLOSE_VAL = "close";\r
+\r
+ private JdbcInterceptor next = null;\r
+\r
+ public JdbcInterceptor() {\r
+ }\r
+\r
+ /**\r
+ * {@inheritDoc}\r
+ */\r
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\r
+ if (getNext()!=null) return getNext().invoke(this,method,args);\r
+ else throw new NullPointerException();\r
+ }\r
+\r
+ public JdbcInterceptor getNext() {\r
+ return next;\r
+ }\r
+\r
+ public void setNext(JdbcInterceptor next) {\r
+ this.next = next;\r
+ }\r
+\r
+ public abstract void reset(ConnectionPool parent, PooledConnection con);\r
+}\r
--- /dev/null
+/*\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.pool;\r
+\r
+\r
+import java.lang.reflect.Method;\r
+import java.util.Properties;\r
+/**\r
+ * @author Filip Hanik\r
+ *\r
+ */\r
+public class PoolProperties {\r
+ protected static volatile int poolCounter = 1;\r
+ protected Properties dbProperties = new Properties();\r
+ protected String url = null;\r
+ protected String driverClassName = null;\r
+ protected Boolean defaultAutoCommit = null;\r
+ protected Boolean defaultReadOnly = null;\r
+ protected int defaultTransactionIsolation = DataSourceFactory.UNKNOWN_TRANSACTIONISOLATION;\r
+ protected String defaultCatalog = null;\r
+ protected String connectionProperties;\r
+ protected int initialSize = 10;\r
+ protected int maxActive = 100;\r
+ protected int maxIdle = maxActive;\r
+ protected int minIdle = initialSize;\r
+ protected int maxWait = 30000;\r
+ protected String validationQuery;\r
+ protected boolean testOnBorrow = false;\r
+ protected boolean testOnReturn = false;\r
+ protected boolean testWhileIdle = false;\r
+ protected int timeBetweenEvictionRunsMillis = 5000;\r
+ protected int numTestsPerEvictionRun;\r
+ protected int minEvictableIdleTimeMillis = 60000;\r
+ protected boolean accessToUnderlyingConnectionAllowed;\r
+ protected boolean removeAbandoned = false;\r
+ protected int removeAbandonedTimeout = 60;\r
+ protected boolean logAbandoned = false;\r
+ protected int loginTimeout = 10000;\r
+ protected String name = "Filip Connection Pool["+(poolCounter++)+"]";\r
+ protected String password;\r
+ protected String username;\r
+ protected long validationInterval = 30000;\r
+ protected boolean jmxEnabled = true;\r
+ protected String initSQL;\r
+ protected boolean testOnConnect =false;\r
+ private String jdbcInterceptors=null;\r
+\r
+ public boolean isAccessToUnderlyingConnectionAllowed() {\r
+ return accessToUnderlyingConnectionAllowed;\r
+ }\r
+\r
+ public String getConnectionProperties() {\r
+ return connectionProperties;\r
+ }\r
+\r
+ public Properties getDbProperties() {\r
+ return dbProperties;\r
+ }\r
+\r
+ public boolean isDefaultAutoCommit() {\r
+ return defaultAutoCommit;\r
+ }\r
+\r
+ public String getDefaultCatalog() {\r
+ return defaultCatalog;\r
+ }\r
+\r
+ public boolean isDefaultReadOnly() {\r
+ return defaultReadOnly;\r
+ }\r
+\r
+ public int getDefaultTransactionIsolation() {\r
+ return defaultTransactionIsolation;\r
+ }\r
+\r
+ public String getDriverClassName() {\r
+ return driverClassName;\r
+ }\r
+\r
+ public int getInitialSize() {\r
+ return initialSize;\r
+ }\r
+\r
+ public boolean isLogAbandoned() {\r
+ return logAbandoned;\r
+ }\r
+\r
+ public int getLoginTimeout() {\r
+ return loginTimeout;\r
+ }\r
+\r
+ public int getMaxActive() {\r
+ return maxActive;\r
+ }\r
+\r
+ public int getMaxIdle() {\r
+ return maxIdle;\r
+ }\r
+\r
+ public int getMaxWait() {\r
+ return maxWait;\r
+ }\r
+\r
+ public int getMinEvictableIdleTimeMillis() {\r
+ return minEvictableIdleTimeMillis;\r
+ }\r
+\r
+ public int getMinIdle() {\r
+ return minIdle;\r
+ }\r
+\r
+ public String getName() {\r
+ return name;\r
+ }\r
+\r
+ public int getNumTestsPerEvictionRun() {\r
+ return numTestsPerEvictionRun;\r
+ }\r
+\r
+ public String getPassword() {\r
+ return password;\r
+ }\r
+\r
+ public String getPoolName() {\r
+ return getName();\r
+ }\r
+\r
+ public boolean isRemoveAbandoned() {\r
+ return removeAbandoned;\r
+ }\r
+\r
+ public int getRemoveAbandonedTimeout() {\r
+ return removeAbandonedTimeout;\r
+ }\r
+\r
+ public boolean isTestOnBorrow() {\r
+ return testOnBorrow;\r
+ }\r
+\r
+ public boolean isTestOnReturn() {\r
+ return testOnReturn;\r
+ }\r
+\r
+ public boolean isTestWhileIdle() {\r
+ return testWhileIdle;\r
+ }\r
+\r
+ public int getTimeBetweenEvictionRunsMillis() {\r
+ return timeBetweenEvictionRunsMillis;\r
+ }\r
+\r
+ public String getUrl() {\r
+ return url;\r
+ }\r
+\r
+ public String getUsername() {\r
+ return username;\r
+ }\r
+\r
+ public String getValidationQuery() {\r
+ return validationQuery;\r
+ }\r
+\r
+ public long getValidationInterval() {\r
+ return validationInterval;\r
+ }\r
+\r
+ public String getInitSQL() {\r
+ return initSQL;\r
+ }\r
+\r
+ public boolean isTestOnConnect() {\r
+ return testOnConnect;\r
+ }\r
+\r
+ public String getJdbcInterceptors() {\r
+ return jdbcInterceptors;\r
+ }\r
+\r
+ public String[] getJdbcInterceptorsAsArray() {\r
+ if (jdbcInterceptors==null) return new String[0];\r
+ else {\r
+ return jdbcInterceptors.split(";");\r
+ }\r
+ }\r
+\r
+ public void setAccessToUnderlyingConnectionAllowed(boolean\r
+ accessToUnderlyingConnectionAllowed) {\r
+ this.accessToUnderlyingConnectionAllowed =\r
+ accessToUnderlyingConnectionAllowed;\r
+ }\r
+\r
+ public void setConnectionProperties(String connectionProperties) {\r
+ this.connectionProperties = connectionProperties;\r
+ }\r
+\r
+ public void setDbProperties(Properties dbProperties) {\r
+ this.dbProperties = dbProperties;\r
+ }\r
+\r
+ public void setDefaultAutoCommit(Boolean defaultAutoCommit) {\r
+ this.defaultAutoCommit = defaultAutoCommit;\r
+ }\r
+\r
+ public void setDefaultCatalog(String defaultCatalog) {\r
+ this.defaultCatalog = defaultCatalog;\r
+ }\r
+\r
+ public void setDefaultReadOnly(Boolean defaultReadOnly) {\r
+ this.defaultReadOnly = defaultReadOnly;\r
+ }\r
+\r
+ public void setDefaultTransactionIsolation(int defaultTransactionIsolation) {\r
+ this.defaultTransactionIsolation = defaultTransactionIsolation;\r
+ }\r
+\r
+ public void setDriverClassName(String driverClassName) {\r
+ this.driverClassName = driverClassName;\r
+ }\r
+\r
+ public void setInitialSize(int initialSize) {\r
+ this.initialSize = initialSize;\r
+ }\r
+\r
+ public void setLogAbandoned(boolean logAbandoned) {\r
+ this.logAbandoned = logAbandoned;\r
+ }\r
+\r
+ public void setLoginTimeout(int loginTimeout) {\r
+ this.loginTimeout = loginTimeout;\r
+ }\r
+\r
+ public void setMaxActive(int maxActive) {\r
+ this.maxActive = maxActive;\r
+ }\r
+\r
+ public void setMaxIdle(int maxIdle) {\r
+ this.maxIdle = maxIdle;\r
+ }\r
+\r
+ public void setMaxWait(int maxWait) {\r
+ this.maxWait = maxWait;\r
+ }\r
+\r
+ public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) {\r
+ this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;\r
+ }\r
+\r
+ public void setMinIdle(int minIdle) {\r
+ this.minIdle = minIdle;\r
+ }\r
+\r
+ public void setName(String name) {\r
+ this.name = name;\r
+ }\r
+\r
+ public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {\r
+ this.numTestsPerEvictionRun = numTestsPerEvictionRun;\r
+ }\r
+\r
+ public void setPassword(String password) {\r
+ this.password = password;\r
+ }\r
+\r
+ public void setRemoveAbandoned(boolean removeAbandoned) {\r
+ this.removeAbandoned = removeAbandoned;\r
+ }\r
+\r
+ public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) {\r
+ this.removeAbandonedTimeout = removeAbandonedTimeout;\r
+ }\r
+\r
+ public void setTestOnBorrow(boolean testOnBorrow) {\r
+ this.testOnBorrow = testOnBorrow;\r
+ }\r
+\r
+ public void setTestWhileIdle(boolean testWhileIdle) {\r
+ this.testWhileIdle = testWhileIdle;\r
+ }\r
+\r
+ public void setTestOnReturn(boolean testOnReturn) {\r
+ this.testOnReturn = testOnReturn;\r
+ }\r
+\r
+ public void setTimeBetweenEvictionRunsMillis(int\r
+ timeBetweenEvictionRunsMillis) {\r
+ this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;\r
+ }\r
+\r
+ public void setUrl(String url) {\r
+ this.url = url;\r
+ }\r
+\r
+ public void setUsername(String username) {\r
+ this.username = username;\r
+ }\r
+\r
+ public void setValidationInterval(long validationInterval) {\r
+ this.validationInterval = validationInterval;\r
+ }\r
+\r
+ public void setValidationQuery(String validationQuery) {\r
+ this.validationQuery = validationQuery;\r
+ }\r
+\r
+ public void setInitSQL(String initSQL) {\r
+ this.initSQL = initSQL;\r
+ }\r
+\r
+ public void setTestOnConnect(boolean testOnConnect) {\r
+ this.testOnConnect = testOnConnect;\r
+ }\r
+\r
+ public void setJdbcInterceptors(String jdbcInterceptors) {\r
+ this.jdbcInterceptors = jdbcInterceptors;\r
+ }\r
+\r
+ public String toString() {\r
+ StringBuffer buf = new StringBuffer("ConnectionPool[");\r
+ try {\r
+ String[] fields = DataSourceFactory.ALL_PROPERTIES;\r
+ for (int i=0; i<fields.length; i++) {\r
+ final String[] prefix = new String[] {"get","is"};\r
+ for (int j=0; j<prefix.length; j++) {\r
+\r
+ String name = prefix[j] + fields[i].substring(0, 1).toUpperCase() +\r
+ fields[i].substring(1);\r
+ Method m = null;\r
+ try {\r
+ m = getClass().getMethod(name);\r
+ }catch (NoSuchMethodException nm) {\r
+ continue;\r
+ }\r
+ buf.append(fields[i]);\r
+ buf.append("=");\r
+ buf.append(m.invoke(this, new Object[0]));\r
+ buf.append("; ");\r
+ break;\r
+ }\r
+ }\r
+ }catch (Exception x) {\r
+ //shouldn;t happen\r
+ x.printStackTrace();\r
+ }\r
+ return buf.toString();\r
+ }\r
+\r
+ public static int getPoolCounter() {\r
+ return poolCounter;\r
+ }\r
+\r
+ public boolean isJmxEnabled() {\r
+ return jmxEnabled;\r
+ }\r
+\r
+ public void setJmxEnabled(boolean jmxEnabled) {\r
+ this.jmxEnabled = jmxEnabled;\r
+ }\r
+\r
+ public Boolean getDefaultAutoCommit() {\r
+ return defaultAutoCommit;\r
+ }\r
+\r
+ public Boolean getDefaultReadOnly() {\r
+ return defaultReadOnly;\r
+ }\r
+ \r
+ public boolean isPoolSweeperEnabled() {\r
+ boolean result = getTimeBetweenEvictionRunsMillis()>0;\r
+ result = result && (isRemoveAbandoned() && getRemoveAbandonedTimeout()>0);\r
+ result = result && (isTestWhileIdle() && getValidationQuery()!=null);\r
+ return result;\r
+ }\r
+}\r
--- /dev/null
+/*\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.pool;\r
+\r
+\r
+import java.lang.ref.WeakReference;\r
+import java.sql.SQLException;\r
+import java.sql.Statement;\r
+import java.util.concurrent.locks.ReentrantReadWriteLock;\r
+\r
+import org.apache.juli.logging.Log;\r
+import org.apache.juli.logging.LogFactory;\r
+import java.util.concurrent.atomic.AtomicInteger;\r
+\r
+/**\r
+ * @author Filip Hanik\r
+ * @version 1.0\r
+ */\r
+public class PooledConnection {\r
+\r
+ public static final int VALIDATE_BORROW = 1;\r
+ public static final int VALIDATE_RETURN = 2;\r
+ public static final int VALIDATE_IDLE = 3;\r
+ public static final int VALIDATE_INIT = 4;\r
+\r
+ protected static Log log = LogFactory.getLog(PooledConnection.class);\r
+ protected static volatile int counter = 1;\r
+\r
+ protected PoolProperties poolProperties;\r
+ protected java.sql.Connection connection;\r
+ protected String abandonTrace = null;\r
+ protected long timestamp;\r
+ protected ReentrantReadWriteLock lock = new ReentrantReadWriteLock(false);\r
+ protected boolean discarded = false;\r
+ protected long lastValidated = System.currentTimeMillis();\r
+ protected int instanceCount = 0;\r
+ protected ConnectionPool parent;\r
+\r
+ protected WeakReference<JdbcInterceptor> handler = null;\r
+\r
+ public PooledConnection(PoolProperties prop, ConnectionPool parent) throws SQLException {\r
+ instanceCount = counter++;\r
+ poolProperties = prop;\r
+ this.parent = parent;\r
+ }\r
+\r
+ protected void connect() throws SQLException {\r
+ if (connection != null) {\r
+ try {\r
+ this.disconnect();\r
+ } catch (Exception x) {\r
+ log.error("Unable to disconnect previous connection.", x);\r
+ } //catch\r
+ } //end if\r
+ java.sql.Driver driver = null;\r
+ try {\r
+ driver = (java.sql.Driver) Class.forName(poolProperties.getDriverClassName(),\r
+ true, PooledConnection.class.getClassLoader()).newInstance();\r
+ } catch (java.lang.Exception cn) {\r
+ log.error("Unable to instantiate JDBC driver.", cn);\r
+ throw new SQLException(cn.getMessage());\r
+ }\r
+ String driverURL = poolProperties.getUrl();\r
+ String usr = poolProperties.getUsername();\r
+ String pwd = poolProperties.getPassword();\r
+ poolProperties.getDbProperties().setProperty("user", usr);\r
+ poolProperties.getDbProperties().setProperty("password", pwd);\r
+ connection = driver.connect(driverURL, poolProperties.getDbProperties());\r
+ //set up the default state\r
+ if (poolProperties.getDefaultReadOnly()!=null) connection.setReadOnly(poolProperties.getDefaultReadOnly().booleanValue());\r
+ if (poolProperties.getDefaultAutoCommit()!=null) connection.setAutoCommit(poolProperties.getDefaultAutoCommit().booleanValue());\r
+ if (poolProperties.getDefaultCatalog()!=null) connection.setCatalog(poolProperties.getDefaultCatalog());\r
+ if (poolProperties.getDefaultTransactionIsolation()!=DataSourceFactory.UNKNOWN_TRANSACTIONISOLATION) connection.setTransactionIsolation(poolProperties.getDefaultTransactionIsolation());\r
+ \r
+ this.discarded = false;\r
+ }\r
+\r
+ protected void reconnect() throws SQLException {\r
+ this.disconnect();\r
+ this.connect();\r
+ } //reconnect\r
+\r
+ protected synchronized void disconnect() throws SQLException {\r
+ if (isDiscarded()) {\r
+ return;\r
+ }\r
+ setDiscarded(true);\r
+ if (connection != null) {\r
+ connection.close();\r
+ }\r
+ connection = null;\r
+ parent.finalize(this);\r
+ }\r
+\r
+\r
+//============================================================================\r
+// com.filip.util.IPoolObject methods\r
+//============================================================================\r
+\r
+ public long getAbandonTimeout() {\r
+ if (poolProperties.getRemoveAbandonedTimeout() <= 0) {\r
+ return Long.MAX_VALUE;\r
+ } else {\r
+ return poolProperties.getRemoveAbandonedTimeout()*1000;\r
+ } //end if\r
+ }\r
+\r
+ public boolean abandon() {\r
+ try {\r
+ disconnect();\r
+ } catch (SQLException x) {\r
+ log.error("", x);\r
+ } //catch\r
+ return false;\r
+ }\r
+\r
+ protected boolean doValidate(int action) {\r
+ if (action == PooledConnection.VALIDATE_BORROW &&\r
+ poolProperties.isTestOnBorrow())\r
+ return true;\r
+ else if (action == PooledConnection.VALIDATE_RETURN &&\r
+ poolProperties.isTestOnReturn())\r
+ return true;\r
+ else if (action == PooledConnection.VALIDATE_IDLE &&\r
+ poolProperties.isTestWhileIdle())\r
+ return true;\r
+ else if (action == PooledConnection.VALIDATE_INIT &&\r
+ poolProperties.isTestOnConnect())\r
+ return true;\r
+ else if (action == PooledConnection.VALIDATE_INIT &&\r
+ poolProperties.getInitSQL()!=null)\r
+ return true;\r
+ else\r
+ return false;\r
+ }\r
+\r
+ /**Returns true if the object is still valid. if not\r
+ * the pool will call the getExpiredAction() and follow up with one\r
+ * of the four expired methods\r
+ */\r
+ public boolean validate(int validateAction) {\r
+ return validate(validateAction,null);\r
+ }\r
+\r
+ public boolean validate(int validateAction,String sql) {\r
+ if (!doValidate(validateAction)) {\r
+ //no validation required, no init sql and props not set\r
+ return true;\r
+ }\r
+\r
+ String query = (VALIDATE_INIT==validateAction && (poolProperties.getInitSQL()!=null))?poolProperties.getInitSQL():sql;\r
+\r
+ if (query==null) query = poolProperties.getValidationQuery();\r
+\r
+ if (query == null) {\r
+ //no validation possible\r
+ return true;\r
+ }\r
+ long now = System.currentTimeMillis();\r
+ if (this.poolProperties.getValidationInterval() > 0 &&\r
+ (now - this.lastValidated) <\r
+ this.poolProperties.getValidationInterval()) {\r
+ return true;\r
+ }\r
+ try {\r
+ Statement stmt = connection.createStatement();\r
+ boolean exec = stmt.execute(query);\r
+ stmt.close();\r
+ this.lastValidated = now;\r
+ return true;\r
+ } catch (Exception ignore) {\r
+ if (log.isDebugEnabled())\r
+ log.debug("Unable to validate object:",ignore);\r
+ }\r
+ return false;\r
+ } //validate\r
+\r
+ /**\r
+ * The time limit for how long the object\r
+ * can remain unused before it is released\r
+ */\r
+ public long getReleaseTime() {\r
+ return this.poolProperties.getMinEvictableIdleTimeMillis();\r
+ }\r
+\r
+ /**\r
+ * This method is called if (Now - timeCheckedIn > getReleaseTime())\r
+ */\r
+ public void release() {\r
+ try {\r
+ disconnect();\r
+ } catch (SQLException x) {\r
+ //TODO\r
+ }\r
+\r
+ }\r
+\r
+ /**\r
+ * The pool will set the stack trace when it is check out and\r
+ * checked in\r
+ */\r
+\r
+ public void setStackTrace(String trace) {\r
+ abandonTrace = trace;\r
+ }\r
+\r
+ public String getStackTrace() {\r
+ return abandonTrace;\r
+ }\r
+\r
+ public void setTimestamp(long timestamp) {\r
+ this.timestamp = timestamp;\r
+ }\r
+\r
+ public void setDiscarded(boolean discarded) {\r
+ if (this.discarded && !discarded) throw new IllegalStateException("Unable to change the state once the connection has been discarded");\r
+ this.discarded = discarded;\r
+ }\r
+\r
+ public void setLastValidated(long lastValidated) {\r
+ this.lastValidated = lastValidated;\r
+ }\r
+\r
+ public void setPoolProperties(PoolProperties poolProperties) {\r
+ this.poolProperties = poolProperties;\r
+ }\r
+\r
+ public long getTimestamp() {\r
+ return timestamp;\r
+ }\r
+\r
+ public boolean isDiscarded() {\r
+ return discarded;\r
+ }\r
+\r
+ public long getLastValidated() {\r
+ return lastValidated;\r
+ }\r
+\r
+ public PoolProperties getPoolProperties() {\r
+ return poolProperties;\r
+ }\r
+\r
+ public void lock() {\r
+ if (this.poolProperties.isPoolSweeperEnabled()) {\r
+ //optimized, only use a lock when there is concurrency\r
+ lock.writeLock().lock();\r
+ }\r
+ }\r
+\r
+ public void unlock() {\r
+ if (this.poolProperties.isPoolSweeperEnabled()) {\r
+ //optimized, only use a lock when there is concurrency\r
+ lock.writeLock().unlock();\r
+ }\r
+ }\r
+\r
+ public java.sql.Connection getConnection() {\r
+ return this.connection;\r
+ }\r
+\r
+ public JdbcInterceptor getHandler() {\r
+ return (handler!=null)?handler.get():null;\r
+ }\r
+\r
+ public void setHandler(JdbcInterceptor handler) {\r
+ if (handler==null) {\r
+ if (this.handler!=null) this.handler.clear();\r
+ } else if (this.handler==null) {\r
+ this.handler = new WeakReference<JdbcInterceptor>(handler);\r
+ } else if (this.handler.get()==null) {\r
+ this.handler.clear();\r
+ this.handler = new WeakReference<JdbcInterceptor>(handler);\r
+ } else if (this.handler.get()!=handler) {\r
+ this.handler.clear();\r
+ this.handler = new WeakReference<JdbcInterceptor>(handler);\r
+ }\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\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.pool;\r
+\r
+import java.lang.reflect.Method;\r
+import java.sql.Connection;\r
+import java.sql.SQLException;\r
+/**\r
+ * @author Filip Hanik\r
+ */\r
+public class ProxyConnection extends JdbcInterceptor {\r
+\r
+ protected PooledConnection connection = null;\r
+\r
+ protected ConnectionPool pool = null;\r
+\r
+ public PooledConnection getConnection() {\r
+ return connection;\r
+ }\r
+\r
+ public void setConnection(PooledConnection connection) {\r
+ this.connection = connection;\r
+ }\r
+\r
+ public ConnectionPool getPool() {\r
+ return pool;\r
+ }\r
+\r
+ public void setPool(ConnectionPool pool) {\r
+ this.pool = pool;\r
+ }\r
+\r
+ protected ProxyConnection(ConnectionPool parent, PooledConnection con) throws SQLException {\r
+ pool = parent;\r
+ connection = con;\r
+ }\r
+\r
+ public void reset(ConnectionPool parent, PooledConnection con) {\r
+ this.pool = parent;\r
+ this.connection = con;\r
+ }\r
+\r
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {\r
+ return (iface.isInstance(connection.getConnection()));\r
+ }\r
+\r
+\r
+ public Object unwrap(Class iface) throws SQLException {\r
+ if (isWrapperFor(iface)) {\r
+ return connection.getConnection();\r
+ } else {\r
+ throw new SQLException("Not a wrapper of "+iface.getName());\r
+ }\r
+ }\r
+\r
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\r
+ if (isClosed()) throw new SQLException("Connection has already been closed.");\r
+ if (CLOSE_VAL==method.getName()) {\r
+ PooledConnection poolc = this.connection;\r
+ this.connection = null;\r
+ pool.returnConnection(poolc);\r
+ return null;\r
+ }\r
+ return method.invoke(connection.getConnection(),args);\r
+ }\r
+\r
+ public boolean isClosed() {\r
+ return connection==null || connection.isDiscarded();\r
+ }\r
+\r
+ public PooledConnection getDelegateConnection() {\r
+ return connection;\r
+ }\r
+\r
+ public ConnectionPool getParentPool() {\r
+ return pool;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\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.pool.interceptor;\r
+\r
+import java.lang.reflect.Method;\r
+\r
+import org.apache.tomcat.jdbc.pool.ConnectionPool;\r
+import org.apache.tomcat.jdbc.pool.DataSourceFactory;\r
+import org.apache.tomcat.jdbc.pool.JdbcInterceptor;\r
+import org.apache.tomcat.jdbc.pool.PooledConnection;\r
+\r
+/**\r
+ * Interceptor that keep track of connection state to avoid roundtrips to the database\r
+ * @author fhanik\r
+ *\r
+ */\r
+\r
+public class ConnectionState extends JdbcInterceptor {\r
+\r
+ protected final String[] readState = {"getAutoCommit","getTransactionIsolation","isReadOnly"};\r
+ protected final String[] writeState = {"setAutoCommit","setTransactionIsolation","setReadOnly"};\r
+\r
+ protected Boolean autoCommit = null;\r
+ protected Integer transactionIsolation = null;\r
+ protected Boolean readOnly = null;\r
+\r
+ public void reset(ConnectionPool parent, PooledConnection con) {\r
+ autoCommit = null;\r
+ transactionIsolation = null;\r
+ readOnly = null;\r
+ }\r
+\r
+ @Override\r
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\r
+ String name = method.getName();\r
+ boolean read = false;\r
+ int index = -1;\r
+ for (int i=0; (!read) && i<readState.length; i++) {\r
+ read = name==readState[i];\r
+ if (read) index = i;\r
+ }\r
+ boolean write = false;\r
+ for (int i=0; (!write) && (!read) && i<writeState.length; i++) {\r
+ write = name==writeState[i];\r
+ if (write) index = i;\r
+ }\r
+ Object result = null;\r
+ if (read) {\r
+ switch (index) {\r
+ case 0:{result = autoCommit; break;}\r
+ case 1:{result = transactionIsolation; break;}\r
+ case 2:{result = readOnly; break;}\r
+ default: result = null;\r
+ }\r
+ //return cached result, if we have it\r
+ if (result!=null) return result;\r
+ }\r
+\r
+ result = super.invoke(proxy, method, args);\r
+ if (read || write) {\r
+ switch (index) {\r
+ case 0:{autoCommit = (Boolean) (read?result:args[0]); break;}\r
+ case 1:{transactionIsolation = (Integer)(read?result:args[0]); break;}\r
+ case 2:{readOnly = (Boolean)(read?result:args[0]); break;}\r
+ }\r
+ }\r
+ return result;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\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.pool.interceptor;\r
+\r
+import java.lang.reflect.InvocationHandler;\r
+import java.lang.reflect.Method;\r
+import java.lang.reflect.Proxy;\r
+import java.sql.CallableStatement;\r
+import java.sql.SQLException;\r
+\r
+import org.apache.tomcat.jdbc.pool.ConnectionPool;\r
+import org.apache.tomcat.jdbc.pool.JdbcInterceptor;\r
+import org.apache.tomcat.jdbc.pool.PooledConnection;\r
+\r
+/**\r
+ * @author Filip Hanik\r
+ * @version 1.0\r
+ */\r
+public class SlowQueryReport extends JdbcInterceptor {\r
+ protected final String[] statements = {"createStatement","prepareStatement","prepareCall"};\r
+ protected final String[] executes = {"execute","executeQuery","executeUpdate","executeBatch"};\r
+\r
+ public SlowQueryReport() {\r
+ super();\r
+ }\r
+\r
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\r
+ boolean process = false;\r
+ process = process(statements, method, process);\r
+ if (process) {\r
+ Object statement = super.invoke(proxy,method,args);\r
+ CallableStatement measuredStatement =\r
+ (CallableStatement)Proxy.newProxyInstance(SlowQueryReport.class.getClassLoader(),\r
+ new Class[] {java.sql.CallableStatement.class,\r
+ java.sql.PreparedStatement.class,\r
+ java.sql.Statement.class},\r
+ new StatementProxy(statement, args));\r
+\r
+ return measuredStatement;\r
+ } else {\r
+ return super.invoke(proxy,method,args);\r
+ }\r
+ }\r
+\r
+ protected boolean process(String[] names, Method method, boolean process) {\r
+ for (int i=0; (!process) && i<names.length; i++) {\r
+ process = (method.getName()==names[i]);\r
+ }\r
+ return process;\r
+ }\r
+\r
+ protected class StatementProxy implements InvocationHandler {\r
+ protected Object parent;\r
+ protected Object[] args;\r
+ public StatementProxy(Object parent, Object[] args) {\r
+ this.parent = parent;\r
+ this.args = args;\r
+ }\r
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {\r
+ if (this.parent == null ) throw new SQLException("Statement has been closed.");\r
+ boolean process = false;\r
+ process = process(executes, method, process);\r
+ long start = (process)?System.currentTimeMillis():0;\r
+ //execute the query\r
+ Object result = method.invoke(parent,args);\r
+ long delta = (process)?(System.currentTimeMillis()-start):0;\r
+ if (delta>10) {\r
+ StringBuffer out = new StringBuffer("\n\tType:");\r
+ out.append(parent.getClass().getName());\r
+ out.append("\n\tCreate/Prepare args:");\r
+ for (int i=0; this.args!=null && i<this.args.length;i++) {\r
+ out.append(this.args[i]!=null?this.args[i]:"null");\r
+ out.append("; ");\r
+ }\r
+ out.append("\n\tExecute args:");\r
+ for (int i=0; args!=null && i<args.length;i++) {\r
+ out.append(args[i]!=null?args[i]:"null");\r
+ out.append("; ");\r
+ }\r
+ System.out.println("Slow query:"+out+"\nTime to execute:"+(delta)+" ms.");\r
+ }\r
+ if (JdbcInterceptor.CLOSE_VAL==method.getName()) {\r
+ this.parent = null;\r
+ this.args = null;\r
+ }\r
+ return result;\r
+ }\r
+ }\r
+\r
+ public void reset(ConnectionPool parent, PooledConnection con) {\r
+\r
+ }\r
+}\r
--- /dev/null
+/* 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.pool.jmx;\r
+/**\r
+ * @author Filip Hanik\r
+ */\r
+import java.util.Properties;\r
+\r
+import javax.management.DynamicMBean;\r
+\r
+import org.apache.tomcat.jdbc.pool.JdbcInterceptor;\r
+\r
+public class ConnectionPool implements ConnectionPoolMBean {\r
+ protected org.apache.tomcat.jdbc.pool.ConnectionPool pool = null;\r
+\r
+ public ConnectionPool(org.apache.tomcat.jdbc.pool.ConnectionPool pool) {\r
+ this.pool = pool;\r
+ }\r
+\r
+ public org.apache.tomcat.jdbc.pool.ConnectionPool getPool() {\r
+ return pool;\r
+ }\r
+\r
+ //=================================================================\r
+ // POOL STATS\r
+ //=================================================================\r
+\r
+ public int getSize() {\r
+ return pool.getSize();\r
+ }\r
+\r
+ public int getIdle() {\r
+ return pool.getIdle();\r
+ }\r
+\r
+ public int getActive() {\r
+ return pool.getActive();\r
+ }\r
+ \r
+ public boolean isPoolSweeperEnabled() {\r
+ return pool.getPoolProperties().isPoolSweeperEnabled();\r
+ }\r
+\r
+ //=================================================================\r
+ // POOL OPERATIONS\r
+ //=================================================================\r
+ public void checkIdle() {\r
+ pool.checkIdle();\r
+ }\r
+\r
+ public void checkAbandoned() {\r
+ pool.checkAbandoned();\r
+ }\r
+\r
+ public void testIdle() {\r
+ pool.testAllIdle();\r
+ }\r
+ //=================================================================\r
+ // POOL PROPERTIES\r
+ //=================================================================\r
+ public Properties getDbProperties() {\r
+ return pool.getPoolProperties().getDbProperties();\r
+ }\r
+ public String getUrl() {\r
+ return pool.getPoolProperties().getUrl();\r
+ }\r
+ public String getDriverClassName() {\r
+ return pool.getPoolProperties().getDriverClassName();\r
+ }\r
+ public boolean isDefaultAutoCommit() {\r
+ return pool.getPoolProperties().isDefaultAutoCommit();\r
+ }\r
+ public boolean isDefaultReadOnly() {\r
+ return pool.getPoolProperties().isDefaultReadOnly();\r
+ }\r
+ public int getDefaultTransactionIsolation() {\r
+ return pool.getPoolProperties().getDefaultTransactionIsolation();\r
+ }\r
+ public String getConnectionProperties() {\r
+ return pool.getPoolProperties().getConnectionProperties();\r
+ }\r
+ public String getDefaultCatalog() {\r
+ return pool.getPoolProperties().getDefaultCatalog();\r
+ }\r
+ public int getInitialSize() {\r
+ return pool.getPoolProperties().getInitialSize();\r
+ }\r
+ public int getMaxActive() {\r
+ return pool.getPoolProperties().getMaxActive();\r
+ }\r
+ public int getMaxIdle() {\r
+ return pool.getPoolProperties().getMaxIdle();\r
+ }\r
+ public int getMinIdle() {\r
+ return pool.getPoolProperties().getMinIdle();\r
+ }\r
+ public int getMaxWait() {\r
+ return pool.getPoolProperties().getMaxWait();\r
+ }\r
+ public String getValidationQuery() {\r
+ return pool.getPoolProperties().getValidationQuery();\r
+ }\r
+ public boolean isTestOnBorrow() {\r
+ return pool.getPoolProperties().isTestOnBorrow();\r
+ }\r
+ public boolean isTestOnReturn() {\r
+ return pool.getPoolProperties().isTestOnReturn();\r
+ }\r
+ public boolean isTestWhileIdle() {\r
+ return pool.getPoolProperties().isTestWhileIdle();\r
+ }\r
+ public int getTimeBetweenEvictionRunsMillis() {\r
+ return pool.getPoolProperties().getTimeBetweenEvictionRunsMillis();\r
+ }\r
+ public int getNumTestsPerEvictionRun() {\r
+ return pool.getPoolProperties().getNumTestsPerEvictionRun();\r
+ }\r
+ public int getMinEvictableIdleTimeMillis() {\r
+ return pool.getPoolProperties().getMinEvictableIdleTimeMillis();\r
+ }\r
+ public boolean isAccessToUnderlyingConnectionAllowed() {\r
+ return pool.getPoolProperties().isAccessToUnderlyingConnectionAllowed();\r
+ }\r
+ public boolean isRemoveAbandoned() {\r
+ return pool.getPoolProperties().isRemoveAbandoned();\r
+ }\r
+ public int getRemoveAbandonedTimeout() {\r
+ return pool.getPoolProperties().getRemoveAbandonedTimeout();\r
+ }\r
+ public boolean isLogAbandoned() {\r
+ return pool.getPoolProperties().isLogAbandoned();\r
+ }\r
+ public int getLoginTimeout() {\r
+ return pool.getPoolProperties().getLoginTimeout();\r
+ }\r
+ public String getName() {\r
+ return pool.getPoolProperties().getName();\r
+ }\r
+ public String getPassword() {\r
+ return pool.getPoolProperties().getPassword();\r
+ }\r
+ public String getUsername() {\r
+ return pool.getPoolProperties().getUsername();\r
+ }\r
+ public long getValidationInterval() {\r
+ return pool.getPoolProperties().getValidationInterval();\r
+ }\r
+ public String getInitSQL() {\r
+ return pool.getPoolProperties().getInitSQL();\r
+ }\r
+ public boolean isTestOnConnect() {\r
+ return pool.getPoolProperties().isTestOnConnect();\r
+ }\r
+ public String getJdbcInterceptors() {\r
+ return pool.getPoolProperties().getJdbcInterceptors();\r
+ }\r
+\r
+}\r
--- /dev/null
+/* 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.pool.jmx;\r
+\r
+import java.util.Properties;\r
+\r
+import javax.management.DynamicMBean;\r
+\r
+import org.apache.tomcat.jdbc.pool.ConnectionPool;\r
+import org.apache.tomcat.jdbc.pool.JdbcInterceptor;\r
+\r
+public interface ConnectionPoolMBean {\r
+\r
+ //=================================================================\r
+ // POOL STATS\r
+ //=================================================================\r
+\r
+ public int getSize();\r
+\r
+ public int getIdle();\r
+\r
+ public int getActive();\r
+ \r
+ public boolean isPoolSweeperEnabled();\r
+\r
+ //=================================================================\r
+ // POOL OPERATIONS\r
+ //=================================================================\r
+ public void checkIdle();\r
+\r
+ public void checkAbandoned();\r
+\r
+ public void testIdle();\r
+\r
+ //=================================================================\r
+ // POOL PROPERTIES\r
+ //=================================================================\r
+ public Properties getDbProperties();\r
+\r
+ public String getUrl();\r
+\r
+ public String getDriverClassName();\r
+\r
+ public boolean isDefaultAutoCommit();\r
+\r
+ public boolean isDefaultReadOnly();\r
+\r
+ public int getDefaultTransactionIsolation();\r
+\r
+ public String getConnectionProperties();\r
+\r
+ public String getDefaultCatalog();\r
+\r
+ public int getInitialSize();\r
+\r
+ public int getMaxActive();\r
+\r
+ public int getMaxIdle();\r
+\r
+ public int getMinIdle();\r
+\r
+ public int getMaxWait();\r
+\r
+ public String getValidationQuery();\r
+\r
+ public boolean isTestOnBorrow();\r
+\r
+ public boolean isTestOnReturn();\r
+\r
+ public boolean isTestWhileIdle();\r
+\r
+ public int getTimeBetweenEvictionRunsMillis();\r
+\r
+ public int getNumTestsPerEvictionRun();\r
+\r
+ public int getMinEvictableIdleTimeMillis();\r
+\r
+ public boolean isAccessToUnderlyingConnectionAllowed();\r
+\r
+ public boolean isRemoveAbandoned();\r
+\r
+ public int getRemoveAbandonedTimeout();\r
+\r
+ public boolean isLogAbandoned();\r
+\r
+ public int getLoginTimeout();\r
+\r
+ public String getName();\r
+\r
+ public String getPassword();\r
+\r
+ public String getUsername();\r
+\r
+ public long getValidationInterval();\r
+\r
+ public String getInitSQL();\r
+\r
+ public boolean isTestOnConnect();\r
+\r
+ public String getJdbcInterceptors();\r
+\r
+}\r
--- /dev/null
+/*\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 java.util.concurrent.CountDownLatch;\r
+import java.util.concurrent.atomic.AtomicInteger;\r
+import java.sql.Connection;\r
+import java.sql.Statement;\r
+import java.sql.ResultSet;\r
+\r
+import javax.sql.DataSource;\r
+\r
+import org.apache.tomcat.jdbc.pool.DataSourceFactory;\r
+\r
+/**\r
+ * @author Filip Hanik\r
+ * @version 1.0\r
+ */\r
+public class CheckOutThreadTest extends DefaultTestCase {\r
+ public CheckOutThreadTest(String name) {\r
+ super(name);\r
+ }\r
+\r
+ CountDownLatch latch = null;\r
+\r
+ public void testDBCPThreads10Connections10() throws Exception {\r
+ init();\r
+ this.datasource.getPoolProperties().setMaxActive(10);\r
+ this.threadcount = 10;\r
+ this.transferProperties();\r
+ this.tDatasource.getConnection().close();\r
+ latch = new CountDownLatch(threadcount);\r
+ long start = System.currentTimeMillis();\r
+ for (int i=0; i<threadcount; i++) {\r
+ TestThread t = new TestThread();\r
+ t.setName("tomcat-dbcp-"+i);\r
+ t.d = this.tDatasource;\r
+ t.start();\r
+ }\r
+ latch.await();\r
+ long delta = System.currentTimeMillis() - start;\r
+ System.out.println("[testDBCPThreads10Connections10]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));\r
+ tearDown();\r
+ }\r
+\r
+ public void testPoolThreads10Connections10() throws Exception {\r
+ init();\r
+ this.datasource.getPoolProperties().setMaxActive(10);\r
+ this.threadcount = 10;\r
+ this.transferProperties();\r
+ this.datasource.getConnection().close();\r
+ latch = new CountDownLatch(threadcount);\r
+ long start = System.currentTimeMillis();\r
+ for (int i=0; i<threadcount; i++) {\r
+ TestThread t = new TestThread();\r
+ t.setName("tomcat-pool-"+i);\r
+ t.d = DataSourceFactory.getDataSource(this.datasource);\r
+ t.start();\r
+ }\r
+ latch.await();\r
+ long delta = System.currentTimeMillis() - start;\r
+ System.out.println("[testPoolThreads10Connections10]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));\r
+ tearDown();\r
+ }\r
+\r
+ public void testDBCPThreads20Connections10() throws Exception {\r
+ init();\r
+ this.datasource.getPoolProperties().setMaxActive(10);\r
+ this.threadcount = 20;\r
+ this.transferProperties();\r
+ this.tDatasource.getConnection().close();\r
+ latch = new CountDownLatch(threadcount);\r
+ long start = System.currentTimeMillis();\r
+ for (int i=0; i<threadcount; i++) {\r
+ TestThread t = new TestThread();\r
+ t.setName("tomcat-dbcp-"+i);\r
+ t.d = this.tDatasource;\r
+ t.start();\r
+ }\r
+ latch.await();\r
+ long delta = System.currentTimeMillis() - start;\r
+ System.out.println("[testDBCPThreads20Connections10]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));\r
+ tearDown();\r
+ }\r
+\r
+ public void testPoolThreads20Connections10() throws Exception {\r
+ init();\r
+ this.datasource.getPoolProperties().setMaxActive(10);\r
+ this.threadcount = 20;\r
+ this.transferProperties();\r
+ this.datasource.getConnection().close();\r
+ latch = new CountDownLatch(threadcount);\r
+ long start = System.currentTimeMillis();\r
+ for (int i=0; i<threadcount; i++) {\r
+ TestThread t = new TestThread();\r
+ t.setName("tomcat-pool-"+i);\r
+ t.d = DataSourceFactory.getDataSource(this.datasource);\r
+ t.start();\r
+ }\r
+ latch.await();\r
+ long delta = System.currentTimeMillis() - start;\r
+ System.out.println("[testPoolThreads20Connections10]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));\r
+ tearDown();\r
+ }\r
+\r
+\r
+ \r
+ public void testDBCPThreads10Connections10Validate() throws Exception {\r
+ init();\r
+ this.datasource.getPoolProperties().setMaxActive(10);\r
+ this.datasource.getPoolProperties().setValidationQuery("SELECT 1");\r
+ this.datasource.getPoolProperties().setTestOnBorrow(true);\r
+ this.threadcount = 10;\r
+ this.transferProperties();\r
+ this.tDatasource.getConnection().close();\r
+ latch = new CountDownLatch(threadcount);\r
+ long start = System.currentTimeMillis();\r
+ for (int i=0; i<threadcount; i++) {\r
+ TestThread t = new TestThread();\r
+ t.setName("tomcat-dbcp-validate-"+i);\r
+ t.d = this.tDatasource;\r
+ t.start();\r
+ }\r
+ latch.await();\r
+ long delta = System.currentTimeMillis() - start;\r
+ System.out.println("[testDBCPThreads10Connections10Validate]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));\r
+ tearDown();\r
+ }\r
+\r
+ public void testPoolThreads10Connections10Validate() throws Exception {\r
+ init();\r
+ this.datasource.getPoolProperties().setMaxActive(10);\r
+ this.datasource.getPoolProperties().setValidationQuery("SELECT 1");\r
+ this.datasource.getPoolProperties().setTestOnBorrow(true);\r
+ this.threadcount = 10;\r
+ this.transferProperties();\r
+ this.datasource.getConnection().close();\r
+ latch = new CountDownLatch(threadcount);\r
+ long start = System.currentTimeMillis();\r
+ for (int i=0; i<threadcount; i++) {\r
+ TestThread t = new TestThread();\r
+ t.setName("tomcat-pool-validate-"+i);\r
+ t.d = DataSourceFactory.getDataSource(this.datasource);\r
+ t.start();\r
+ }\r
+ latch.await();\r
+ long delta = System.currentTimeMillis() - start;\r
+ System.out.println("[testPoolThreads10Connections10Validate]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));\r
+ tearDown();\r
+ }\r
+\r
+ public void testDBCPThreads20Connections10Validate() throws Exception {\r
+ init();\r
+ this.datasource.getPoolProperties().setMaxActive(10);\r
+ this.datasource.getPoolProperties().setValidationQuery("SELECT 1");\r
+ this.datasource.getPoolProperties().setTestOnBorrow(true);\r
+ this.threadcount = 20;\r
+ this.transferProperties();\r
+ this.tDatasource.getConnection().close();\r
+ latch = new CountDownLatch(threadcount);\r
+ long start = System.currentTimeMillis();\r
+ for (int i=0; i<threadcount; i++) {\r
+ TestThread t = new TestThread();\r
+ t.setName("tomcat-dbcp-validate-"+i);\r
+ t.d = this.tDatasource;\r
+ t.start();\r
+ }\r
+ latch.await();\r
+ long delta = System.currentTimeMillis() - start;\r
+ System.out.println("[testDBCPThreads20Connections10Validate]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));\r
+ tearDown();\r
+ }\r
+\r
+ public void testPoolThreads10Connections20Validate() throws Exception {\r
+ init();\r
+ this.datasource.getPoolProperties().setMaxActive(10);\r
+ this.datasource.getPoolProperties().setValidationQuery("SELECT 1");\r
+ this.datasource.getPoolProperties().setTestOnBorrow(true);\r
+ this.threadcount = 20;\r
+ this.transferProperties();\r
+ this.datasource.getConnection().close();\r
+ latch = new CountDownLatch(threadcount);\r
+ long start = System.currentTimeMillis();\r
+ for (int i=0; i<threadcount; i++) {\r
+ TestThread t = new TestThread();\r
+ t.setName("tomcat-pool-validate-"+i);\r
+ t.d = DataSourceFactory.getDataSource(this.datasource);\r
+ t.start();\r
+ }\r
+ latch.await();\r
+ long delta = System.currentTimeMillis() - start;\r
+ System.out.println("[testPoolThreads20Connections10Validate]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));\r
+ tearDown();\r
+ }\r
+\r
+ \r
+ public class TestThread extends Thread {\r
+ protected DataSource d;\r
+ \r
+ public void run() {\r
+ long max = -1, totalmax=0, totalcmax=0, cmax = -1, nroffetch = 0, totalruntime = 0;\r
+ try {\r
+ for (int i = 0; i < CheckOutThreadTest.this.iterations; i++) {\r
+ long start = System.nanoTime();\r
+ Connection con = null;\r
+ try {\r
+ con = d.getConnection();\r
+ long delta = System.nanoTime() - start;\r
+ totalmax += delta;\r
+ max = Math.max(delta, max);\r
+ nroffetch++;\r
+ } finally {\r
+ long cstart = System.nanoTime();\r
+ if (con!=null) try {con.close();}catch(Exception x) {x.printStackTrace();}\r
+ long cdelta = System.nanoTime() - cstart;\r
+ totalcmax += cdelta;\r
+ cmax = Math.max(cdelta, cmax);\r
+ }\r
+ totalruntime+=(System.nanoTime()-start);\r
+ }\r
+\r
+ } catch (Exception x) {\r
+ x.printStackTrace();\r
+ } finally {\r
+ CheckOutThreadTest.this.latch.countDown();\r
+ }\r
+ if (System.getProperty("print-thread-stats")!=null) {\r
+ System.out.println("["+getName()+"] "+\r
+ "\n\tMax time to retrieve connection:"+(((float)max)/1000f/1000f)+" ms."+\r
+ "\n\tTotal time to retrieve connection:"+(((float)totalmax)/1000f/1000f)+" ms."+\r
+ "\n\tAverage time to retrieve connection:"+(((float)totalmax)/1000f/1000f)/(float)nroffetch+" ms."+\r
+ "\n\tMax time to close connection:"+(((float)cmax)/1000f/1000f)+" ms."+\r
+ "\n\tTotal time to close connection:"+(((float)totalcmax)/1000f/1000f)+" ms."+\r
+ "\n\tAverage time to close connection:"+(((float)totalcmax)/1000f/1000f)/(float)nroffetch+" ms."+\r
+ "\n\tRun time:"+(((float)totalruntime)/1000f/1000f)+" ms."+\r
+ "\n\tNr of fetch:"+nroffetch);\r
+ }\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/*\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 java.util.Properties;\r
+\r
+import org.apache.tomcat.jdbc.pool.DataSourceFactory;\r
+import org.apache.tomcat.jdbc.pool.PoolProperties;\r
+\r
+/**\r
+ * @author Filip Hanik\r
+ * @version 1.0\r
+ */\r
+public class DefaultProperties extends PoolProperties {\r
+ public DefaultProperties() {\r
+ dbProperties = new Properties();\r
+ url = "jdbc:mysql://localhost:3306/mysql?autoReconnect=true";\r
+ driverClassName = "com.mysql.jdbc.Driver";\r
+ password = "password";\r
+ username = "root";\r
+ defaultAutoCommit = true;\r
+ defaultReadOnly = false;\r
+ defaultTransactionIsolation = DataSourceFactory.UNKNOWN_TRANSACTIONISOLATION;\r
+ connectionProperties = null;\r
+ defaultCatalog = null;\r
+ initialSize = 10;\r
+ maxActive = 100;\r
+ maxIdle = initialSize;\r
+ minIdle = initialSize;\r
+ maxWait = 10000;\r
+ validationQuery = "SELECT 1";\r
+ testOnBorrow = true;\r
+ testOnReturn = false;\r
+ testWhileIdle = true;\r
+ timeBetweenEvictionRunsMillis = 5000;\r
+ numTestsPerEvictionRun = 0;\r
+ minEvictableIdleTimeMillis = 1000;\r
+ accessToUnderlyingConnectionAllowed = false;\r
+ removeAbandoned = true;\r
+ removeAbandonedTimeout = 5000;\r
+ logAbandoned = true;\r
+ loginTimeout = 0;\r
+ validationInterval = 0; //always validate\r
+ initSQL = null;\r
+ testOnConnect = false;;\r
+ dbProperties.setProperty("user",username);\r
+ dbProperties.setProperty("password",password);\r
+ }\r
+}\r
--- /dev/null
+/*\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 java.lang.reflect.Method;\r
+import java.util.Properties;\r
+\r
+import org.apache.tomcat.dbcp.dbcp.BasicDataSource;\r
+import org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory;\r
+\r
+import junit.framework.TestCase;\r
+import org.apache.tomcat.jdbc.pool.PoolProperties;\r
+import org.apache.tomcat.jdbc.pool.DataSourceProxy;\r
+\r
+/**\r
+ * @author Filip Hanik\r
+ * @version 1.0\r
+ */\r
+public class DefaultTestCase extends TestCase {\r
+ protected DataSourceProxy datasource;\r
+ protected BasicDataSource tDatasource;\r
+ protected int threadcount = 10;\r
+ protected int iterations = 100000;\r
+ public DefaultTestCase(String name) {\r
+ super(name);\r
+ }\r
+\r
+ protected void init() throws Exception {\r
+ PoolProperties p = new DefaultProperties();\r
+ p.setJmxEnabled(false);\r
+ p.setTestWhileIdle(false);\r
+ p.setTestOnBorrow(false);\r
+ p.setTestOnReturn(false);\r
+ p.setValidationInterval(30000);\r
+ p.setTimeBetweenEvictionRunsMillis(30000);\r
+ p.setMaxActive(threadcount);\r
+ p.setInitialSize(threadcount);\r
+ p.setMaxWait(10000);\r
+ p.setRemoveAbandonedTimeout(10000);\r
+ p.setMinEvictableIdleTimeMillis(10000);\r
+ p.setMinIdle(threadcount);\r
+ p.setLogAbandoned(false);\r
+ p.setRemoveAbandoned(false);\r
+ datasource = new org.apache.tomcat.jdbc.pool.DataSourceProxy();\r
+ datasource.setPoolProperties(p);\r
+ }\r
+\r
+ protected void transferProperties() {\r
+ try {\r
+ BasicDataSourceFactory factory = new BasicDataSourceFactory();\r
+ Properties p = new Properties();\r
+\r
+ for (int i=0; i<this.ALL_PROPERTIES.length; i++) {\r
+ String name = "get" + Character.toUpperCase(ALL_PROPERTIES[i].charAt(0)) + ALL_PROPERTIES[i].substring(1);\r
+ String bname = "is" + name.substring(3);\r
+ Method get = null;\r
+ try {\r
+ get = PoolProperties.class.getMethod(name, new Class[0]);\r
+ }catch (NoSuchMethodException x) {\r
+ try {\r
+ get = PoolProperties.class.getMethod(bname, new Class[0]);\r
+ }catch (NoSuchMethodException x2) {\r
+ System.err.println(x2.getMessage());\r
+ }\r
+ }\r
+ if (get!=null) {\r
+ Object value = get.invoke(datasource.getPoolProperties(), new Object[0]);\r
+ if (value!=null) {\r
+ p.setProperty(ALL_PROPERTIES[i], value.toString());\r
+ }\r
+ }\r
+ }\r
+ tDatasource = (BasicDataSource)factory.createDataSource(p);\r
+ }catch (Exception x) {\r
+ x.printStackTrace();\r
+ }\r
+ }\r
+\r
+\r
+ protected void tearDown() throws Exception {\r
+ datasource = null;\r
+ tDatasource = null;\r
+ System.gc();\r
+ }\r
+\r
+ private final static String PROP_DEFAULTAUTOCOMMIT = "defaultAutoCommit";\r
+ private final static String PROP_DEFAULTREADONLY = "defaultReadOnly";\r
+ private final static String PROP_DEFAULTTRANSACTIONISOLATION = "defaultTransactionIsolation";\r
+ private final static String PROP_DEFAULTCATALOG = "defaultCatalog";\r
+ private final static String PROP_DRIVERCLASSNAME = "driverClassName";\r
+ private final static String PROP_MAXACTIVE = "maxActive";\r
+ private final static String PROP_MAXIDLE = "maxIdle";\r
+ private final static String PROP_MINIDLE = "minIdle";\r
+ private final static String PROP_INITIALSIZE = "initialSize";\r
+ private final static String PROP_MAXWAIT = "maxWait";\r
+ private final static String PROP_TESTONBORROW = "testOnBorrow";\r
+ private final static String PROP_TESTONRETURN = "testOnReturn";\r
+ private final static String PROP_TIMEBETWEENEVICTIONRUNSMILLIS = "timeBetweenEvictionRunsMillis";\r
+ private final static String PROP_NUMTESTSPEREVICTIONRUN = "numTestsPerEvictionRun";\r
+ private final static String PROP_MINEVICTABLEIDLETIMEMILLIS = "minEvictableIdleTimeMillis";\r
+ private final static String PROP_TESTWHILEIDLE = "testWhileIdle";\r
+ private final static String PROP_PASSWORD = "password";\r
+ private final static String PROP_URL = "url";\r
+ private final static String PROP_USERNAME = "username";\r
+ private final static String PROP_VALIDATIONQUERY = "validationQuery";\r
+ private final static String PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED = "accessToUnderlyingConnectionAllowed";\r
+ private final static String PROP_REMOVEABANDONED = "removeAbandoned";\r
+ private final static String PROP_REMOVEABANDONEDTIMEOUT = "removeAbandonedTimeout";\r
+ private final static String PROP_LOGABANDONED = "logAbandoned";\r
+ private final static String PROP_POOLPREPAREDSTATEMENTS = "poolPreparedStatements";\r
+ private final static String PROP_MAXOPENPREPAREDSTATEMENTS = "maxOpenPreparedStatements";\r
+ private final static String PROP_CONNECTIONPROPERTIES = "connectionProperties";\r
+\r
+ private final static String[] ALL_PROPERTIES = {\r
+ PROP_DEFAULTAUTOCOMMIT,\r
+ PROP_DEFAULTREADONLY,\r
+ PROP_DEFAULTTRANSACTIONISOLATION,\r
+ PROP_DEFAULTCATALOG,\r
+ PROP_DRIVERCLASSNAME,\r
+ PROP_MAXACTIVE,\r
+ PROP_MAXIDLE,\r
+ PROP_MINIDLE,\r
+ PROP_INITIALSIZE,\r
+ PROP_MAXWAIT,\r
+ PROP_TESTONBORROW,\r
+ PROP_TESTONRETURN,\r
+ PROP_TIMEBETWEENEVICTIONRUNSMILLIS,\r
+ PROP_NUMTESTSPEREVICTIONRUN,\r
+ PROP_MINEVICTABLEIDLETIMEMILLIS,\r
+ PROP_TESTWHILEIDLE,\r
+ PROP_PASSWORD,\r
+ PROP_URL,\r
+ PROP_USERNAME,\r
+ PROP_VALIDATIONQUERY,\r
+ PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED,\r
+ PROP_REMOVEABANDONED,\r
+ PROP_REMOVEABANDONEDTIMEOUT,\r
+ PROP_LOGABANDONED,\r
+ PROP_CONNECTIONPROPERTIES\r
+ };\r
+\r
+\r
+\r
+}\r
--- /dev/null
+/*\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
+/**\r
+ * @author Filip Hanik\r
+ * @version 1.0\r
+ */\r
+public class TestGCClose extends DefaultTestCase {\r
+ public TestGCClose(String name) {\r
+ super(name);\r
+ }\r
+ \r
+ public void testGCStop() throws Exception {\r
+ init();\r
+ datasource.getConnection();\r
+ System.out.println("Got a connection, but didn't return it");\r
+ tearDown();\r
+ Thread.sleep(10000);\r
+ }\r
+}\r
--- /dev/null
+/*\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 java.util.concurrent.atomic.AtomicInteger;\r
+\r
+/**\r
+ * @author Filip Hanik\r
+ * @version 1.0\r
+ */\r
+public class TestTimeout extends DefaultTestCase {\r
+ public TestTimeout(String name) {\r
+ super(name);\r
+ }\r
+\r
+ AtomicInteger counter = new AtomicInteger(0);\r
+\r
+ public void testCheckoutTimeout() throws Exception {\r
+ try {\r
+ init();\r
+ this.datasource.getPoolProperties().setTestWhileIdle(true);\r
+ this.datasource.getPoolProperties().setTestOnBorrow(false);\r
+ this.datasource.getPoolProperties().setTestOnReturn(false);\r
+ this.datasource.getPoolProperties().setValidationInterval(30000);\r
+ this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(1000);\r
+ this.datasource.getPoolProperties().setMaxActive(20);\r
+ this.datasource.getPoolProperties().setMaxWait(3000);\r
+ this.datasource.getPoolProperties().setRemoveAbandonedTimeout(5000);\r
+ this.datasource.getPoolProperties().setMinEvictableIdleTimeMillis(5000);\r
+ this.datasource.getPoolProperties().setMinIdle(5);\r
+ this.datasource.getPoolProperties().setLogAbandoned(true);\r
+ System.out.println("About to test connection pool:"+datasource);\r
+ for (int i = 0; i < 21; i++) {\r
+ long now = System.currentTimeMillis();\r
+ this.datasource.getConnection();\r
+ long delta = System.currentTimeMillis()-now;\r
+ System.out.println("Got connection #"+i+" in "+delta+" ms.");\r
+ }\r
+ } catch ( Exception x ) {\r
+ x.printStackTrace();\r
+ }finally {\r
+ Thread.sleep(20000);\r
+ tearDown();\r
+ }\r
+ }\r
+\r
+ public void testRemoveAbandoned() throws Exception {\r
+ try {\r
+ init();\r
+ this.datasource.getPoolProperties().setTestWhileIdle(true);\r
+ this.datasource.getPoolProperties().setTestOnBorrow(false);\r
+ this.datasource.getPoolProperties().setTestOnReturn(false);\r
+ this.datasource.getPoolProperties().setValidationInterval(30000);\r
+ this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(1000);\r
+ this.datasource.getPoolProperties().setMaxActive(20);\r
+ this.datasource.getPoolProperties().setMaxWait(3000);\r
+ this.datasource.getPoolProperties().setRemoveAbandonedTimeout(5000);\r
+ this.datasource.getPoolProperties().setMinEvictableIdleTimeMillis(5000);\r
+ this.datasource.getPoolProperties().setMinIdle(5);\r
+ this.datasource.getPoolProperties().setRemoveAbandoned(true);\r
+ this.datasource.getPoolProperties().setLogAbandoned(true);\r
+ System.out.println("About to test connection pool:"+datasource);\r
+ for (int i = 0; i < threadcount; i++) {\r
+ long now = System.currentTimeMillis();\r
+ this.datasource.getConnection();\r
+ long delta = System.currentTimeMillis()-now;\r
+ System.out.println("Got connection #"+i+" in "+delta+" ms.");\r
+ }\r
+ } catch ( Exception x ) {\r
+ x.printStackTrace();\r
+ }finally {\r
+ Thread.sleep(20000);\r
+ tearDown();\r
+ }\r
+ }\r
+\r
+\r
+}\r
+++ /dev/null
-/*\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 java.util.concurrent.CountDownLatch;\r
-import java.util.concurrent.atomic.AtomicInteger;\r
-import java.sql.Connection;\r
-import java.sql.Statement;\r
-import java.sql.ResultSet;\r
-\r
-import javax.sql.DataSource;\r
-\r
-import org.apache.tomcat.jdbc.pool.DataSourceFactory;\r
-\r
-/**\r
- * @author Filip Hanik\r
- * @version 1.0\r
- */\r
-public class CheckOutThreadTest extends DefaultTestCase {\r
- public CheckOutThreadTest(String name) {\r
- super(name);\r
- }\r
-\r
- CountDownLatch latch = null;\r
-\r
- public void testDBCPThreads10Connections10() throws Exception {\r
- init();\r
- this.datasource.getPoolProperties().setMaxActive(10);\r
- this.threadcount = 10;\r
- this.transferProperties();\r
- this.tDatasource.getConnection().close();\r
- latch = new CountDownLatch(threadcount);\r
- long start = System.currentTimeMillis();\r
- for (int i=0; i<threadcount; i++) {\r
- TestThread t = new TestThread();\r
- t.setName("tomcat-dbcp-"+i);\r
- t.d = this.tDatasource;\r
- t.start();\r
- }\r
- latch.await();\r
- long delta = System.currentTimeMillis() - start;\r
- System.out.println("[testDBCPThreads10Connections10]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));\r
- tearDown();\r
- }\r
-\r
- public void testPoolThreads10Connections10() throws Exception {\r
- init();\r
- this.datasource.getPoolProperties().setMaxActive(10);\r
- this.threadcount = 10;\r
- this.transferProperties();\r
- this.datasource.getConnection().close();\r
- latch = new CountDownLatch(threadcount);\r
- long start = System.currentTimeMillis();\r
- for (int i=0; i<threadcount; i++) {\r
- TestThread t = new TestThread();\r
- t.setName("tomcat-pool-"+i);\r
- t.d = DataSourceFactory.getDataSource(this.datasource);\r
- t.start();\r
- }\r
- latch.await();\r
- long delta = System.currentTimeMillis() - start;\r
- System.out.println("[testPoolThreads10Connections10]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));\r
- tearDown();\r
- }\r
-\r
- public void testDBCPThreads20Connections10() throws Exception {\r
- init();\r
- this.datasource.getPoolProperties().setMaxActive(10);\r
- this.threadcount = 20;\r
- this.transferProperties();\r
- this.tDatasource.getConnection().close();\r
- latch = new CountDownLatch(threadcount);\r
- long start = System.currentTimeMillis();\r
- for (int i=0; i<threadcount; i++) {\r
- TestThread t = new TestThread();\r
- t.setName("tomcat-dbcp-"+i);\r
- t.d = this.tDatasource;\r
- t.start();\r
- }\r
- latch.await();\r
- long delta = System.currentTimeMillis() - start;\r
- System.out.println("[testDBCPThreads20Connections10]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));\r
- tearDown();\r
- }\r
-\r
- public void testPoolThreads20Connections10() throws Exception {\r
- init();\r
- this.datasource.getPoolProperties().setMaxActive(10);\r
- this.threadcount = 20;\r
- this.transferProperties();\r
- this.datasource.getConnection().close();\r
- latch = new CountDownLatch(threadcount);\r
- long start = System.currentTimeMillis();\r
- for (int i=0; i<threadcount; i++) {\r
- TestThread t = new TestThread();\r
- t.setName("tomcat-pool-"+i);\r
- t.d = DataSourceFactory.getDataSource(this.datasource);\r
- t.start();\r
- }\r
- latch.await();\r
- long delta = System.currentTimeMillis() - start;\r
- System.out.println("[testPoolThreads20Connections10]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));\r
- tearDown();\r
- }\r
-\r
-\r
- \r
- public void testDBCPThreads10Connections10Validate() throws Exception {\r
- init();\r
- this.datasource.getPoolProperties().setMaxActive(10);\r
- this.datasource.getPoolProperties().setValidationQuery("SELECT 1");\r
- this.datasource.getPoolProperties().setTestOnBorrow(true);\r
- this.threadcount = 10;\r
- this.transferProperties();\r
- this.tDatasource.getConnection().close();\r
- latch = new CountDownLatch(threadcount);\r
- long start = System.currentTimeMillis();\r
- for (int i=0; i<threadcount; i++) {\r
- TestThread t = new TestThread();\r
- t.setName("tomcat-dbcp-validate-"+i);\r
- t.d = this.tDatasource;\r
- t.start();\r
- }\r
- latch.await();\r
- long delta = System.currentTimeMillis() - start;\r
- System.out.println("[testDBCPThreads10Connections10Validate]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));\r
- tearDown();\r
- }\r
-\r
- public void testPoolThreads10Connections10Validate() throws Exception {\r
- init();\r
- this.datasource.getPoolProperties().setMaxActive(10);\r
- this.datasource.getPoolProperties().setValidationQuery("SELECT 1");\r
- this.datasource.getPoolProperties().setTestOnBorrow(true);\r
- this.threadcount = 10;\r
- this.transferProperties();\r
- this.datasource.getConnection().close();\r
- latch = new CountDownLatch(threadcount);\r
- long start = System.currentTimeMillis();\r
- for (int i=0; i<threadcount; i++) {\r
- TestThread t = new TestThread();\r
- t.setName("tomcat-pool-validate-"+i);\r
- t.d = DataSourceFactory.getDataSource(this.datasource);\r
- t.start();\r
- }\r
- latch.await();\r
- long delta = System.currentTimeMillis() - start;\r
- System.out.println("[testPoolThreads10Connections10Validate]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));\r
- tearDown();\r
- }\r
-\r
- public void testDBCPThreads20Connections10Validate() throws Exception {\r
- init();\r
- this.datasource.getPoolProperties().setMaxActive(10);\r
- this.datasource.getPoolProperties().setValidationQuery("SELECT 1");\r
- this.datasource.getPoolProperties().setTestOnBorrow(true);\r
- this.threadcount = 20;\r
- this.transferProperties();\r
- this.tDatasource.getConnection().close();\r
- latch = new CountDownLatch(threadcount);\r
- long start = System.currentTimeMillis();\r
- for (int i=0; i<threadcount; i++) {\r
- TestThread t = new TestThread();\r
- t.setName("tomcat-dbcp-validate-"+i);\r
- t.d = this.tDatasource;\r
- t.start();\r
- }\r
- latch.await();\r
- long delta = System.currentTimeMillis() - start;\r
- System.out.println("[testDBCPThreads20Connections10Validate]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));\r
- tearDown();\r
- }\r
-\r
- public void testPoolThreads10Connections20Validate() throws Exception {\r
- init();\r
- this.datasource.getPoolProperties().setMaxActive(10);\r
- this.datasource.getPoolProperties().setValidationQuery("SELECT 1");\r
- this.datasource.getPoolProperties().setTestOnBorrow(true);\r
- this.threadcount = 20;\r
- this.transferProperties();\r
- this.datasource.getConnection().close();\r
- latch = new CountDownLatch(threadcount);\r
- long start = System.currentTimeMillis();\r
- for (int i=0; i<threadcount; i++) {\r
- TestThread t = new TestThread();\r
- t.setName("tomcat-pool-validate-"+i);\r
- t.d = DataSourceFactory.getDataSource(this.datasource);\r
- t.start();\r
- }\r
- latch.await();\r
- long delta = System.currentTimeMillis() - start;\r
- System.out.println("[testPoolThreads20Connections10Validate]Test complete:"+delta+" ms. Iterations:"+(threadcount*this.iterations));\r
- tearDown();\r
- }\r
-\r
- \r
- public class TestThread extends Thread {\r
- protected DataSource d;\r
- \r
- public void run() {\r
- long max = -1, totalmax=0, totalcmax=0, cmax = -1, nroffetch = 0, totalruntime = 0;\r
- try {\r
- for (int i = 0; i < CheckOutThreadTest.this.iterations; i++) {\r
- long start = System.nanoTime();\r
- Connection con = null;\r
- try {\r
- con = d.getConnection();\r
- long delta = System.nanoTime() - start;\r
- totalmax += delta;\r
- max = Math.max(delta, max);\r
- nroffetch++;\r
- } finally {\r
- long cstart = System.nanoTime();\r
- if (con!=null) try {con.close();}catch(Exception x) {x.printStackTrace();}\r
- long cdelta = System.nanoTime() - cstart;\r
- totalcmax += cdelta;\r
- cmax = Math.max(cdelta, cmax);\r
- }\r
- totalruntime+=(System.nanoTime()-start);\r
- }\r
-\r
- } catch (Exception x) {\r
- x.printStackTrace();\r
- } finally {\r
- CheckOutThreadTest.this.latch.countDown();\r
- }\r
- if (System.getProperty("print-thread-stats")!=null) {\r
- System.out.println("["+getName()+"] "+\r
- "\n\tMax time to retrieve connection:"+(((float)max)/1000f/1000f)+" ms."+\r
- "\n\tTotal time to retrieve connection:"+(((float)totalmax)/1000f/1000f)+" ms."+\r
- "\n\tAverage time to retrieve connection:"+(((float)totalmax)/1000f/1000f)/(float)nroffetch+" ms."+\r
- "\n\tMax time to close connection:"+(((float)cmax)/1000f/1000f)+" ms."+\r
- "\n\tTotal time to close connection:"+(((float)totalcmax)/1000f/1000f)+" ms."+\r
- "\n\tAverage time to close connection:"+(((float)totalcmax)/1000f/1000f)/(float)nroffetch+" ms."+\r
- "\n\tRun time:"+(((float)totalruntime)/1000f/1000f)+" ms."+\r
- "\n\tNr of fetch:"+nroffetch);\r
- }\r
- }\r
- }\r
-}\r
+++ /dev/null
-/*\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 java.util.Properties;\r
-\r
-import org.apache.tomcat.jdbc.pool.DataSourceFactory;\r
-import org.apache.tomcat.jdbc.pool.PoolProperties;\r
-\r
-/**\r
- * @author Filip Hanik\r
- * @version 1.0\r
- */\r
-public class DefaultProperties extends PoolProperties {\r
- public DefaultProperties() {\r
- dbProperties = new Properties();\r
- url = "jdbc:mysql://localhost:3306/mysql?autoReconnect=true";\r
- driverClassName = "com.mysql.jdbc.Driver";\r
- password = "password";\r
- username = "root";\r
- defaultAutoCommit = true;\r
- defaultReadOnly = false;\r
- defaultTransactionIsolation = DataSourceFactory.UNKNOWN_TRANSACTIONISOLATION;\r
- connectionProperties = null;\r
- defaultCatalog = null;\r
- initialSize = 10;\r
- maxActive = 100;\r
- maxIdle = initialSize;\r
- minIdle = initialSize;\r
- maxWait = 10000;\r
- validationQuery = "SELECT 1";\r
- testOnBorrow = true;\r
- testOnReturn = false;\r
- testWhileIdle = true;\r
- timeBetweenEvictionRunsMillis = 5000;\r
- numTestsPerEvictionRun = 0;\r
- minEvictableIdleTimeMillis = 1000;\r
- accessToUnderlyingConnectionAllowed = false;\r
- removeAbandoned = true;\r
- removeAbandonedTimeout = 5000;\r
- logAbandoned = true;\r
- loginTimeout = 0;\r
- validationInterval = 0; //always validate\r
- initSQL = null;\r
- testOnConnect = false;;\r
- dbProperties.setProperty("user",username);\r
- dbProperties.setProperty("password",password);\r
- }\r
-}\r
+++ /dev/null
-/*\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 java.lang.reflect.Method;\r
-import java.util.Properties;\r
-\r
-import org.apache.tomcat.dbcp.dbcp.BasicDataSource;\r
-import org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory;\r
-\r
-import junit.framework.TestCase;\r
-import org.apache.tomcat.jdbc.pool.PoolProperties;\r
-import org.apache.tomcat.jdbc.pool.DataSourceProxy;\r
-\r
-/**\r
- * @author Filip Hanik\r
- * @version 1.0\r
- */\r
-public class DefaultTestCase extends TestCase {\r
- protected DataSourceProxy datasource;\r
- protected BasicDataSource tDatasource;\r
- protected int threadcount = 10;\r
- protected int iterations = 100000;\r
- public DefaultTestCase(String name) {\r
- super(name);\r
- }\r
-\r
- protected void init() throws Exception {\r
- PoolProperties p = new DefaultProperties();\r
- p.setJmxEnabled(false);\r
- p.setTestWhileIdle(false);\r
- p.setTestOnBorrow(false);\r
- p.setTestOnReturn(false);\r
- p.setValidationInterval(30000);\r
- p.setTimeBetweenEvictionRunsMillis(30000);\r
- p.setMaxActive(threadcount);\r
- p.setInitialSize(threadcount);\r
- p.setMaxWait(10000);\r
- p.setRemoveAbandonedTimeout(10000);\r
- p.setMinEvictableIdleTimeMillis(10000);\r
- p.setMinIdle(threadcount);\r
- p.setLogAbandoned(false);\r
- p.setRemoveAbandoned(false);\r
- datasource = new org.apache.tomcat.jdbc.pool.DataSourceProxy();\r
- datasource.setPoolProperties(p);\r
- }\r
-\r
- protected void transferProperties() {\r
- try {\r
- BasicDataSourceFactory factory = new BasicDataSourceFactory();\r
- Properties p = new Properties();\r
-\r
- for (int i=0; i<this.ALL_PROPERTIES.length; i++) {\r
- String name = "get" + Character.toUpperCase(ALL_PROPERTIES[i].charAt(0)) + ALL_PROPERTIES[i].substring(1);\r
- String bname = "is" + name.substring(3);\r
- Method get = null;\r
- try {\r
- get = PoolProperties.class.getMethod(name, new Class[0]);\r
- }catch (NoSuchMethodException x) {\r
- try {\r
- get = PoolProperties.class.getMethod(bname, new Class[0]);\r
- }catch (NoSuchMethodException x2) {\r
- System.err.println(x2.getMessage());\r
- }\r
- }\r
- if (get!=null) {\r
- Object value = get.invoke(datasource.getPoolProperties(), new Object[0]);\r
- if (value!=null) {\r
- p.setProperty(ALL_PROPERTIES[i], value.toString());\r
- }\r
- }\r
- }\r
- tDatasource = (BasicDataSource)factory.createDataSource(p);\r
- }catch (Exception x) {\r
- x.printStackTrace();\r
- }\r
- }\r
-\r
-\r
- protected void tearDown() throws Exception {\r
- datasource = null;\r
- tDatasource = null;\r
- System.gc();\r
- }\r
-\r
- private final static String PROP_DEFAULTAUTOCOMMIT = "defaultAutoCommit";\r
- private final static String PROP_DEFAULTREADONLY = "defaultReadOnly";\r
- private final static String PROP_DEFAULTTRANSACTIONISOLATION = "defaultTransactionIsolation";\r
- private final static String PROP_DEFAULTCATALOG = "defaultCatalog";\r
- private final static String PROP_DRIVERCLASSNAME = "driverClassName";\r
- private final static String PROP_MAXACTIVE = "maxActive";\r
- private final static String PROP_MAXIDLE = "maxIdle";\r
- private final static String PROP_MINIDLE = "minIdle";\r
- private final static String PROP_INITIALSIZE = "initialSize";\r
- private final static String PROP_MAXWAIT = "maxWait";\r
- private final static String PROP_TESTONBORROW = "testOnBorrow";\r
- private final static String PROP_TESTONRETURN = "testOnReturn";\r
- private final static String PROP_TIMEBETWEENEVICTIONRUNSMILLIS = "timeBetweenEvictionRunsMillis";\r
- private final static String PROP_NUMTESTSPEREVICTIONRUN = "numTestsPerEvictionRun";\r
- private final static String PROP_MINEVICTABLEIDLETIMEMILLIS = "minEvictableIdleTimeMillis";\r
- private final static String PROP_TESTWHILEIDLE = "testWhileIdle";\r
- private final static String PROP_PASSWORD = "password";\r
- private final static String PROP_URL = "url";\r
- private final static String PROP_USERNAME = "username";\r
- private final static String PROP_VALIDATIONQUERY = "validationQuery";\r
- private final static String PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED = "accessToUnderlyingConnectionAllowed";\r
- private final static String PROP_REMOVEABANDONED = "removeAbandoned";\r
- private final static String PROP_REMOVEABANDONEDTIMEOUT = "removeAbandonedTimeout";\r
- private final static String PROP_LOGABANDONED = "logAbandoned";\r
- private final static String PROP_POOLPREPAREDSTATEMENTS = "poolPreparedStatements";\r
- private final static String PROP_MAXOPENPREPAREDSTATEMENTS = "maxOpenPreparedStatements";\r
- private final static String PROP_CONNECTIONPROPERTIES = "connectionProperties";\r
-\r
- private final static String[] ALL_PROPERTIES = {\r
- PROP_DEFAULTAUTOCOMMIT,\r
- PROP_DEFAULTREADONLY,\r
- PROP_DEFAULTTRANSACTIONISOLATION,\r
- PROP_DEFAULTCATALOG,\r
- PROP_DRIVERCLASSNAME,\r
- PROP_MAXACTIVE,\r
- PROP_MAXIDLE,\r
- PROP_MINIDLE,\r
- PROP_INITIALSIZE,\r
- PROP_MAXWAIT,\r
- PROP_TESTONBORROW,\r
- PROP_TESTONRETURN,\r
- PROP_TIMEBETWEENEVICTIONRUNSMILLIS,\r
- PROP_NUMTESTSPEREVICTIONRUN,\r
- PROP_MINEVICTABLEIDLETIMEMILLIS,\r
- PROP_TESTWHILEIDLE,\r
- PROP_PASSWORD,\r
- PROP_URL,\r
- PROP_USERNAME,\r
- PROP_VALIDATIONQUERY,\r
- PROP_ACCESSTOUNDERLYINGCONNECTIONALLOWED,\r
- PROP_REMOVEABANDONED,\r
- PROP_REMOVEABANDONEDTIMEOUT,\r
- PROP_LOGABANDONED,\r
- PROP_CONNECTIONPROPERTIES\r
- };\r
-\r
-\r
-\r
-}\r
+++ /dev/null
-/*\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
-/**\r
- * @author Filip Hanik\r
- * @version 1.0\r
- */\r
-public class TestGCClose extends DefaultTestCase {\r
- public TestGCClose(String name) {\r
- super(name);\r
- }\r
- \r
- public void testGCStop() throws Exception {\r
- init();\r
- datasource.getConnection();\r
- System.out.println("Got a connection, but didn't return it");\r
- tearDown();\r
- Thread.sleep(10000);\r
- }\r
-}\r
+++ /dev/null
-/*\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 java.util.concurrent.atomic.AtomicInteger;\r
-\r
-/**\r
- * @author Filip Hanik\r
- * @version 1.0\r
- */\r
-public class TestTimeout extends DefaultTestCase {\r
- public TestTimeout(String name) {\r
- super(name);\r
- }\r
-\r
- AtomicInteger counter = new AtomicInteger(0);\r
-\r
- public void testCheckoutTimeout() throws Exception {\r
- try {\r
- init();\r
- this.datasource.getPoolProperties().setTestWhileIdle(true);\r
- this.datasource.getPoolProperties().setTestOnBorrow(false);\r
- this.datasource.getPoolProperties().setTestOnReturn(false);\r
- this.datasource.getPoolProperties().setValidationInterval(30000);\r
- this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(1000);\r
- this.datasource.getPoolProperties().setMaxActive(20);\r
- this.datasource.getPoolProperties().setMaxWait(3000);\r
- this.datasource.getPoolProperties().setRemoveAbandonedTimeout(5000);\r
- this.datasource.getPoolProperties().setMinEvictableIdleTimeMillis(5000);\r
- this.datasource.getPoolProperties().setMinIdle(5);\r
- this.datasource.getPoolProperties().setLogAbandoned(true);\r
- System.out.println("About to test connection pool:"+datasource);\r
- for (int i = 0; i < 21; i++) {\r
- long now = System.currentTimeMillis();\r
- this.datasource.getConnection();\r
- long delta = System.currentTimeMillis()-now;\r
- System.out.println("Got connection #"+i+" in "+delta+" ms.");\r
- }\r
- } catch ( Exception x ) {\r
- x.printStackTrace();\r
- }finally {\r
- Thread.sleep(20000);\r
- tearDown();\r
- }\r
- }\r
-\r
- public void testRemoveAbandoned() throws Exception {\r
- try {\r
- init();\r
- this.datasource.getPoolProperties().setTestWhileIdle(true);\r
- this.datasource.getPoolProperties().setTestOnBorrow(false);\r
- this.datasource.getPoolProperties().setTestOnReturn(false);\r
- this.datasource.getPoolProperties().setValidationInterval(30000);\r
- this.datasource.getPoolProperties().setTimeBetweenEvictionRunsMillis(1000);\r
- this.datasource.getPoolProperties().setMaxActive(20);\r
- this.datasource.getPoolProperties().setMaxWait(3000);\r
- this.datasource.getPoolProperties().setRemoveAbandonedTimeout(5000);\r
- this.datasource.getPoolProperties().setMinEvictableIdleTimeMillis(5000);\r
- this.datasource.getPoolProperties().setMinIdle(5);\r
- this.datasource.getPoolProperties().setRemoveAbandoned(true);\r
- this.datasource.getPoolProperties().setLogAbandoned(true);\r
- System.out.println("About to test connection pool:"+datasource);\r
- for (int i = 0; i < threadcount; i++) {\r
- long now = System.currentTimeMillis();\r
- this.datasource.getConnection();\r
- long delta = System.currentTimeMillis()-now;\r
- System.out.println("Got connection #"+i+" in "+delta+" ms.");\r
- }\r
- } catch ( Exception x ) {\r
- x.printStackTrace();\r
- }finally {\r
- Thread.sleep(20000);\r
- tearDown();\r
- }\r
- }\r
-\r
-\r
-}\r