Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

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) // paranoia
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 }