DBPool.java
00001 package edu.virtualschool.jwaa.dbms;
00002
00003 import java.io.File;
00004 import java.sql.Connection;
00005 import java.sql.Driver;
00006 import java.sql.DriverManager;
00007 import java.sql.SQLException;
00008 import java.util.Enumeration;
00009 import java.util.Vector;
00010
00011 import edu.virtualschool.jwaa.Config;
00012
00024 public class DBPool
00025 {
00026 boolean isInitialized = false;
00027 final String url;
00028 final String password;
00029 final String user;
00030 final int maxConnections;
00031 final String[] driverList;
00032 final Vector pooledConnections = new Vector();
00033 public int numberBusyConnections;
00034
00041 public DBPool(String path) throws Config.Fault, Fault
00042 {
00043 this(Config.loadFile(path));
00044 }
00045 public DBPool(File path) throws Config.Fault, Fault
00046 {
00047 this(Config.loadFile(path));
00048 }
00049 public DBPool(Config config) throws Config.Fault, Fault
00050 {
00051 this(
00052 config.get("url"),
00053 config.get("user"),
00054 config.get("pass"),
00055 config.get("connections"),
00056 new String[] { config.get("driver") }
00057 );
00058 }
00073 public DBPool(
00074 String url,
00075 String user,
00076 String password,
00077 String maxConnections,
00078 String[] driverList
00079 ) throws Fault
00080 {
00081 this.driverList = driverList;
00082 if (driverList == null)
00083 throw new Fault("driverList may not be null");
00084 if (driverList.length <= 0)
00085 throw new Fault("driverList length may not be zero");
00086
00087 this.url = url;
00088 if ( url == null)
00089 throw new Fault("url may not be null");
00090
00091 this.user = user;
00092 if (user == null)
00093 throw new Fault("user may not be null");
00094
00095 this.password = password;
00096 if (password == null)
00097 throw new Fault("password may not be null");
00098
00099 this.numberBusyConnections = 0;
00100 this.isInitialized = false;
00101
00102 if (maxConnections == null)
00103 throw new Fault("maxConnections may not be null");
00104 try
00105 {
00106 this.maxConnections = Integer.parseInt(maxConnections);
00107 }
00108 catch (NumberFormatException e1)
00109 {
00110 throw new Fault(maxConnections+" is not an integer");
00111 }
00112 }
00117 public Connection checkout() throws Fault { return checkout(10*1000); }
00131 public synchronized Connection checkout(long timeout) throws Fault
00132 {
00133 long startTime = System.currentTimeMillis();
00134 Connection connection = null;
00135 while((connection = getConnection()) == null)
00136 {
00137 try
00138 {
00139 super.wait(timeout);
00140 }
00141 catch (InterruptedException e)
00142 {
00143 e.printStackTrace();
00144 }
00145 if ((System.currentTimeMillis() - startTime) >= timeout)
00146 throw new Fault("Connection pool timeout: " + timeout, null);
00147 }
00148 numberBusyConnections++;
00149 try
00150 {
00151 connection.setAutoCommit(false);
00152 connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
00153 }
00154 catch (SQLException e)
00155 {
00156 throw new DBPool.Fault
00157 ("Fault setting up connection #"+numberBusyConnections, e);
00158 }
00159 return connection;
00160 }
00166 public synchronized void checkin(Connection connection)
00167 {
00168 if (connection != null)
00169 {
00170 pooledConnections.add(connection);
00171 numberBusyConnections--;
00172 super.notifyAll();
00173 }
00174 }
00175 public final String toString() { return url; }
00180 public final int getMaxConnections() { return maxConnections; }
00186 public final int getNumberBusyConnections() { return numberBusyConnections; }
00192 public final int getNumberPooledConnections() { return pooledConnections.size(); }
00193
00204 private Connection getConnection() throws Fault
00205 {
00206 Connection connection = null;
00207 while (pooledConnections.size() > 0 && connection == null)
00208 {
00209 connection = (Connection) pooledConnections.firstElement();
00210 pooledConnections.removeElementAt(0);
00211 try
00212 {
00213 if (connection.isClosed())
00214 connection = null;
00215 }
00216 catch (SQLException e)
00217 {
00218 throw new Fault(e, e);
00219 }
00220 }
00221 if (connection == null)
00222 {
00223 if (maxConnections == 0 || numberBusyConnections < maxConnections)
00224 connection = addConnection();
00225 }
00226 return connection;
00227 }
00234 private Connection addConnection() throws Fault
00235 {
00236 if (!isInitialized)
00237 initialize();
00238 Connection connection = null;
00239 try
00240 {
00241 if (user == null || password == null)
00242 connection =DriverManager.getConnection(url);
00243 else
00244 connection = DriverManager.getConnection(url, user, password);
00245
00246 if (connection == null)
00247 throw new Fault("DriverManager.getConnection("+url+") fault");
00248
00249 return connection;
00250 }
00251 catch (SQLException e)
00252 { throw new Fault(e, e); }
00253 }
00257 private final void initialize() throws Fault
00258 {
00259 for (int i = 0; i < driverList.length; i++)
00260 {
00261 String driverClassName = driverList[i];
00262 try
00263 {
00264 Driver driver = (Driver)Class.forName(driverClassName).newInstance();
00265 DriverManager.registerDriver(driver);
00266 }
00267 catch (Exception e)
00268 { throw new Fault("Couldn't register: " + driverClassName, e); }
00269 }
00270 isInitialized = true;
00271 }
00275 public synchronized void releaseAllConnections() throws Fault
00276 {
00277 for (Enumeration e = pooledConnections.elements(); e.hasMoreElements(); )
00278 {
00279 Connection c = (Connection) e.nextElement();
00280 try { c.close(); }
00281 catch (SQLException ex)
00282 { throw new Fault(ex, ex); }
00283 }
00284 pooledConnections.removeAllElements();
00285 }
00286 public final static class Fault extends edu.virtualschool.jwaa.Fault
00287 {
00288 public Fault(Object m, Throwable e) { super(m, e); }
00289 public Fault(Object m) { super(m, null); }
00290 public Fault(Throwable e) { super(e, e); }
00291 }
00292 }