11package javaxt .sql ;
22
33import java .io .PrintWriter ;
4- import java .sql .Connection ;
4+ // import java.sql.Connection;
55import java .sql .SQLException ;
66import java .util .concurrent .Semaphore ;
77import java .util .concurrent .TimeUnit ;
1616//** ConnectionPool
1717//******************************************************************************
1818/**
19- * A simple standalone JDBC connection pool manager.
20- * <p>
21- * The public methods of this class are thread-safe.
22- * <p>
23- * Home page: <a href="http://www.source-code.biz">www.source-code.biz</a><br>
24- * Author: Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland<br>
25- * Multi-licensed: EPL/LGPL/MPL.
26- * <p>
27- * 2007-06-21: Constructor with a timeout parameter added.<br>
28- * 2008-05-03: Additional licenses added (EPL/MPL).<br>
29- * 2009-06-26: Variable recycledConnections changed from Stack to Queue, so that
30- * the unused connections are reused in a circular manner.
31- * Thanks to Daniel Jurado for the tip.<br>
32- * 2009-08-21: ArrayDeque (which was introduced with change 2009-06-26) replaced
33- * by LinkedList, because ArrayDeque is only available since Java 1.6 and we want
34- * to keep MiniConnectionPoolManager compatible with Java 1.5.<br>
19+ * A lightweight standalone JDBC connection pool manager written by
20+ * Christian d'Heureuse, Inventec Informatik AG, Zurich, Switzerland. Added
21+ * 2 new constructors to instantiate this class using a javaxt.sql.Database.
22+ *
3523 ******************************************************************************/
3624
3725public class ConnectionPool {
@@ -48,95 +36,143 @@ public class ConnectionPool {
4836//
4937// Please contact the author if you need another license.
5038// This module is provided "as is", without warranties of any kind.
51-
52-
53-
54-
55- private ConnectionPoolDataSource dataSource ;
56- private int maxConnections ;
57- private int timeout ;
58- private PrintWriter logWriter ;
59- private Semaphore semaphore ;
60- private Queue <PooledConnection > recycledConnections ;
61- private int activeConnections ;
62- private PoolConnectionEventListener poolConnectionEventListener ;
63- private boolean isDisposed ;
64-
65-
66- /**
67- * Thrown in {@link #getConnection()} when no free connection becomes available within <code>timeout</code> seconds.
68- */
69- public static class TimeoutException extends RuntimeException {
70- private static final long serialVersionUID = 1 ;
71- public TimeoutException () {
72- super ("Timeout while waiting for a free database connection." ); }}
73-
74- /**
75- * Constructs a MiniConnectionPoolManager object with a timeout of 60 seconds.
76- * @param dataSource the data source for the connections.
77- * @param maxConnections the maximum number of connections.
78- */
79- public ConnectionPool (ConnectionPoolDataSource dataSource , int maxConnections ) {
80- this (dataSource , maxConnections , 60 ); }
81-
82- /**
83- * Constructs a MiniConnectionPoolManager object.
84- * @param dataSource the data source for the connections.
85- * @param maxConnections the maximum number of connections.
86- * @param timeout the maximum time in seconds to wait for a free connection.
87- */
88- public ConnectionPool (ConnectionPoolDataSource dataSource , int maxConnections , int timeout ) {
89- this .dataSource = dataSource ;
90- this .maxConnections = maxConnections ;
91- this .timeout = timeout ;
92- try {
93- logWriter = dataSource .getLogWriter (); }
94- catch (SQLException e ) {}
95- if (maxConnections < 1 ) throw new IllegalArgumentException ("Invalid maxConnections value." );
96- semaphore = new Semaphore (maxConnections ,true );
97- recycledConnections = new LinkedList <PooledConnection >();
98- poolConnectionEventListener = new PoolConnectionEventListener (); }
99-
100- /**
101- * Closes all unused pooled connections.
102- */
103- public synchronized void dispose () throws SQLException {
104- if (isDisposed ) return ;
105- isDisposed = true ;
106- SQLException e = null ;
107- while (!recycledConnections .isEmpty ()) {
108- PooledConnection pconn = recycledConnections .remove ();
109- try {
110- pconn .close (); }
111- catch (SQLException e2 ) {
112- if (e == null ) e = e2 ; }}
113- if (e != null ) throw e ; }
114-
115- /**
116- * Retrieves a connection from the connection pool.
117- * If <code>maxConnections</code> connections are already in use, the method
118- * waits until a connection becomes available or <code>timeout</code> seconds elapsed.
119- * When the application is finished using the connection, it must close it
120- * in order to return it to the pool.
121- * @return a new Connection object.
122- * @throws TimeoutException when no connection becomes available within <code>timeout</code> seconds.
123- */
124- public Connection getConnection () throws SQLException {
125- // This routine is unsynchronized, because semaphore.tryAcquire() may block.
126- synchronized (this ) {
127- if (isDisposed ) throw new IllegalStateException ("Connection pool has been disposed." ); }
128- try {
129- if (!semaphore .tryAcquire (timeout ,TimeUnit .SECONDS ))
130- throw new TimeoutException (); }
131- catch (InterruptedException e ) {
132- throw new RuntimeException ("Interrupted while waiting for a database connection." ,e ); }
133- boolean ok = false ;
134- try {
135- Connection conn = getConnection2 ();
136- ok = true ;
137- return conn ; }
138- finally {
139- if (!ok ) semaphore .release (); }}
39+ //
40+ // Revision History:
41+ // 2007-06-21: Constructor with a timeout parameter added.
42+ // 2008-05-03: Additional licenses added (EPL/MPL).
43+ // 2009-06-26: Variable recycledConnections changed from Stack to Queue, so that
44+ // the unused connections are reused in a circular manner.
45+ // Thanks to Daniel Jurado for the tip.
46+ // 2009-08-21: ArrayDeque (which was introduced with change 2009-06-26) replaced
47+ // by LinkedList, because ArrayDeque is only available since Java 1.6 and we want
48+ // to keep MiniConnectionPoolManager compatible with Java 1.5.
49+ // 2011-12-02: Added 2 new constructors to take a Database object and renamed the
50+ // dispose() method to close().
51+
52+
53+ private ConnectionPoolDataSource dataSource ;
54+ private int maxConnections ;
55+ private int timeout ;
56+ private PrintWriter logWriter ;
57+ private Semaphore semaphore ;
58+ private Queue <PooledConnection > recycledConnections ;
59+ private int activeConnections ;
60+ private PoolConnectionEventListener poolConnectionEventListener ;
61+ private boolean isDisposed ;
62+
63+
64+ /**
65+ * Thrown in {@link #getConnection()} when no free connection becomes available within <code>timeout</code> seconds.
66+ */
67+ public static class TimeoutException extends RuntimeException {
68+ private static final long serialVersionUID = 1 ;
69+ public TimeoutException () {
70+ super ("Timeout while waiting for a free database connection." ); }
71+ }
72+
73+
74+ //**************************************************************************
75+ //** Constructor
76+ //**************************************************************************
77+ /** Constructs a ConnectionPool with a timeout of 60 seconds.
78+ */
79+ public ConnectionPool (Database database , int maxConnections ) throws SQLException {
80+ this (database .getConnectionPoolDataSource (), maxConnections , 60 );
81+ }
82+
83+
84+ //**************************************************************************
85+ //** Constructor
86+ //**************************************************************************
87+ /** Constructs a ConnectionPool.
88+ */
89+ public ConnectionPool (Database database , int maxConnections , int timeout ) throws SQLException {
90+ this (database .getConnectionPoolDataSource (), maxConnections , timeout );
91+ }
92+
93+
94+ //**************************************************************************
95+ //** Constructor
96+ //**************************************************************************
97+ /** Constructs a ConnectionPool with a timeout of 60 seconds.
98+ * @param dataSource the data source for the connections.
99+ * @param maxConnections the maximum number of connections.
100+ */
101+ public ConnectionPool (ConnectionPoolDataSource dataSource , int maxConnections ) {
102+ this (dataSource , maxConnections , 60 );
103+ }
104+
105+
106+ //**************************************************************************
107+ //** Constructor
108+ //**************************************************************************
109+ /** Constructs a ConnectionPool.
110+ * @param dataSource the data source for the connections.
111+ * @param maxConnections the maximum number of connections.
112+ * @param timeout the maximum time in seconds to wait for a free connection.
113+ */
114+ public ConnectionPool (ConnectionPoolDataSource dataSource , int maxConnections , int timeout ) {
115+ this .dataSource = dataSource ;
116+ this .maxConnections = maxConnections ;
117+ this .timeout = timeout ;
118+ try {
119+ logWriter = dataSource .getLogWriter (); }
120+ catch (SQLException e ) {}
121+ if (maxConnections < 1 ) throw new IllegalArgumentException ("Invalid maxConnections value." );
122+ semaphore = new Semaphore (maxConnections ,true );
123+ recycledConnections = new LinkedList <PooledConnection >();
124+ poolConnectionEventListener = new PoolConnectionEventListener ();
125+ }
126+
127+
128+ //**************************************************************************
129+ //** close
130+ //**************************************************************************
131+ /** Closes all unused pooled connections. */
132+
133+ public synchronized void close () throws SQLException {
134+ if (isDisposed ) return ;
135+ isDisposed = true ;
136+ SQLException e = null ;
137+ while (!recycledConnections .isEmpty ()) {
138+ PooledConnection pconn = recycledConnections .remove ();
139+ try {
140+ pconn .close (); }
141+ catch (SQLException e2 ) {
142+ if (e == null ) e = e2 ; }}
143+ if (e != null ) throw e ;
144+ }
145+
146+
147+ //**************************************************************************
148+ //** getConnection
149+ //**************************************************************************
150+ /** Retrieves a connection from the connection pool.
151+ * If <code>maxConnections</code> connections are already in use, the method
152+ * waits until a connection becomes available or <code>timeout</code> seconds elapsed.
153+ * When the application is finished using the connection, it must close it
154+ * in order to return it to the pool.
155+ * @return a new Connection object.
156+ * @throws TimeoutException when no connection becomes available within <code>timeout</code> seconds.
157+ */
158+ public Connection getConnection () throws SQLException {
159+ // This routine is unsynchronized, because semaphore.tryAcquire() may block.
160+ synchronized (this ) {
161+ if (isDisposed ) throw new IllegalStateException ("Connection pool has been disposed." ); }
162+ try {
163+ if (!semaphore .tryAcquire (timeout ,TimeUnit .SECONDS ))
164+ throw new TimeoutException (); }
165+ catch (InterruptedException e ) {
166+ throw new RuntimeException ("Interrupted while waiting for a database connection." ,e ); }
167+ boolean ok = false ;
168+ try {
169+ Connection conn = getConnection2 ();
170+ ok = true ;
171+ return conn ; }
172+ finally {
173+ if (!ok ) semaphore .release ();
174+ }
175+ }
140176
141177private synchronized Connection getConnection2 () throws SQLException {
142178 if (isDisposed ) throw new IllegalStateException ("Connection pool has been disposed." ); // test again with lock
@@ -145,7 +181,7 @@ private synchronized Connection getConnection2() throws SQLException {
145181 pconn = recycledConnections .remove (); }
146182 else {
147183 pconn = dataSource .getPooledConnection (); }
148- Connection conn = pconn .getConnection ();
184+ Connection conn = new Connection ( pconn .getConnection () );
149185 activeConnections ++;
150186 pconn .addConnectionEventListener (poolConnectionEventListener );
151187 assertInnerState ();
0 commit comments