Index: src/edu/ucsb/nceas/metacat/DBConnectionPool.java
===================================================================
--- src/edu/ucsb/nceas/metacat/DBConnectionPool.java	(revision 1088)
+++ src/edu/ucsb/nceas/metacat/DBConnectionPool.java	(revision 1089)
@@ -30,9 +30,7 @@
 
 import java.io.*;
 import java.util.Vector;
-import java.util.zip.*;
-import java.net.URL;
-import java.net.MalformedURLException;
+import java.lang.*;
 import java.sql.*;
 import java.util.Stack;
 import java.util.Hashtable;
@@ -46,28 +44,39 @@
  */
 public class DBConnectionPool
 {
-  private String DBDriver;
-  private String DBConnectedJDBC;
-  private String userName;
-  private String passWord;
-  private int currentConnectionNumber;
-  
+
   //static attributes
   private static DBConnectionPool instance;
   private static Vector connectionPool;
   
-  
-  final static int maximumConnectionNumber=
+  //maximum connection number in the connection pool
+  final static int MAXIMUMCONNECTIONNUMBER=
                   Integer.parseInt(MetaCatUtil.getOption("maximumConnections"));
-  final static int initialConnectionNumber=
+  //inintila connection number int the connection pool
+  final static int INITIALCONNECTIONNUMBER=
                   Integer.parseInt(MetaCatUtil.getOption("initialConnections"));
- 
+  //the number to increase connection pool size
+  final static int INCREASECONNECTIONNUMBER=
+                Integer.parseInt(MetaCatUtil.getOption("incrementConnections"));
+  //maximum age for a connection (in milli seconds)
+  final static long MAXIMUMAGE =
+                  Long.parseLong(MetaCatUtil.getOption("maximumConnectionAge"));
+  //maximum connection time for a connection ( in milli second)
+  final static long MAXIMUMCONNECTIONTIME =
+                 Long.parseLong(MetaCatUtil.getOption("maximumConnectionTime"));
+  //maximum number for using a connection.
+  final static int MAXIMUMUSAGENUMBER =
+                  Integer.parseInt(MetaCatUtil.getOption("maximumUsageNumber"));  
+               
+  
+  final static int FREE = 0; //status of a connection
+  final static int BUSY = 1; //statis of a connection
   /**
    * Returns the single instance, creating one if it's the
    * first time this method is called.
    */
   static synchronized public DBConnectionPool getInstance()
-                                 throws SQLException, ClassNotFoundException 
+                                 throws SQLException 
   {
     if (instance == null) 
     {
@@ -75,66 +84,39 @@
     }
     return instance;
   }//getInstance
+
+  /**
+   * Method to get the size of DBConnectionPool
+   */
+  public int getSizeOfDBConnectionPool()
+  {
+    return connectionPool.size();
+  }
   
   /**
    * This is a private constructor since it is singleton
    */
    
-  private DBConnectionPool()  throws SQLException, ClassNotFoundException 
+  private DBConnectionPool()  throws SQLException 
   {
-    DBDriver=MetaCatUtil.getOption("dbDriver");
-    DBConnectedJDBC=MetaCatUtil.getOption("defaultDB");
-    userName=MetaCatUtil.getOption("user");
-    passWord=MetaCatUtil.getOption("password");
+
+    initialDBConnectionPool();
   }//DBConnection
   
-  /** 
-   * Method to establish a JDBC database connection 
-   */
-  private Connection openConnection()
-                  throws SQLException, ClassNotFoundException 
-  {
-    return openConnection(DBDriver, DBConnectedJDBC, userName, passWord);
-  }//openDBConnection
-
-  /** 
-   * Method to establish a JDBC database connection 
-   *
-   * @param dbDriver the string representing the database driver
-   * @param connection the string representing the database connectin parameters
-   * @param user name of the user to use for database connection
-   * @param password password for the user to use for database connection
-   */
-  private Connection openConnection(String dbDriver, String connection,
-                String user, String password)
-                throws SQLException, ClassNotFoundException 
- {
-
-     // Load the Oracle JDBC driver
-     Class.forName (dbDriver);
-     // Connect to the database
-     Connection conn = DriverManager.getConnection( connection, user, password);
-     return conn;
-  }//OpenDBConnection
-
   /**
    * Method to initial a pool of DBConnection objects 
    */
-  public Vector initialDBConnectionPool()
-                throws SQLException, ClassNotFoundException 
+  private Vector initialDBConnectionPool() throws SQLException 
  {
 
-    Connection conn = null;
     DBConnection dbConn = null;
     
-    for ( int i = 0; i < initialConnectionNumber; i++ ) 
+    for ( int i = 0; i < INITIALCONNECTIONNUMBER; i++ ) 
     {
-      //open a connection to db
-      conn = openConnection();
       //create a new object of DBConnection
+      //this DBConnection object has a new connection in it
+      //it automatically generate the createtime and tag
       dbConn = new DBConnection();
-      //set connetion to DBConnection
-      dbConn.setDBConnection(conn);
       //put DBConnection into vetor
       connectionPool.add(dbConn);
     }    
@@ -142,8 +124,148 @@
     return connectionPool;
   }
   
+ 
+
+
+  /**
+   * Method to get a DBConnection in connection pool
+   */
+  public static DBConnection getDBConnection() throws SQLException
+  {
+    DBConnection db = null;    
+    //try every DBConnection in the pool
+    synchronized(connectionPool)
+    {
+      for (int i=0; i<connectionPool.size(); i++)
+      {
+        db = (DBConnection) connectionPool.elementAt(i);
+        //check if the connection is free
+        if (db.getStatus()==FREE)
+        {
+          //If this connection is good, return this DBConnection
+          if (validateDBConnection(db))
+          {
+            //set this DBConnection status
+            db.setStatus(BUSY);
+            //set check out time
+            db.setCheckOutTime(System.currentTimeMillis());
+            //check it out
+            return db;
+          }//if
+          else//The DBConnection has some problem
+          {
+            //close this DBConnection
+            db.close();
+            //remove it form connection pool
+            connectionPool.remove(i);
+            //insert a new DBConnection to same palace
+            db = new DBConnection();
+            connectionPool.insertElementAt(db, i);
+          }//else
+        }//if
+      }//for
+    }//sychronize
+    
+    //if couldn't get a connection, we should increase DBConnection pool
+    //if the connection pool size is less than maximum connection number
+    int poolSize = connectionPool.size(); 
+    if ( poolSize < MAXIMUMCONNECTIONNUMBER )
+    {
+       if ((poolSize+INCREASECONNECTIONNUMBER) < MAXIMUMCONNECTIONNUMBER)
+       { 
+         //if we can create INCREASECONNECTIONNUMBER of new DBConnection
+         //add to connection pool
+         for ( int i=0; i<INCREASECONNECTIONNUMBER; i++)
+         {
+           DBConnection dbConn = new DBConnection();
+           connectionPool.add(dbConn);
+         }//for
+       }//if
+       else
+       {
+         //There is no enough room to increase INCREASECONNECTIONNUMBER 
+         //we create new DBCoonection to Maximum connection number
+         for (int i= poolSize+1; i<= MAXIMUMCONNECTIONNUMBER; i++)
+         {
+           DBConnection dbConn = new DBConnection();
+           connectionPool.add(dbConn);
+         }//for
+       }//else
+   
+    }//if
+    else
+    {
+      throw new SQLException("The maximum of " +MAXIMUMCONNECTIONNUMBER + 
+                            " open db connections is reached." +
+                            " New db connection to MetaCat" +
+                            " cannot be established.");
+    }//else
+    
+    //recursive to get new connection    
+    return getDBConnection();
+  }//getDBConnection
   
   
   
+  /** 
+   * Method to check if a db connection works fine or not
+   * Check points include:
+   * 1. check the usageCount if it is too many
+   * 2. check the dbconne age if it is too old
+   * 3. check the connection time if it is too long
+   * 4. run simple sql query
+   *
+   * @param dbConn, the DBConnection object need to check
+   */
+  private static boolean validateDBConnection (DBConnection dbConn)
+  {
+    Connection conn = null;
+    
+    //Check if the DBConnection usageCount if it is too many
+    if (dbConn.getUsageCount() >= MAXIMUMUSAGENUMBER )
+    {
+      MetaCatUtil.debugMessage("Connection usageCount is too many: "+
+      dbConn.getUsageCount(), 50);
+      return false;
+    }
+    
+    //Check if the DBConnection has too much connection time
+    if (dbConn.getConnectionTime() >= MAXIMUMCONNECTIONTIME)
+    {
+      MetaCatUtil.debugMessage("Connection has too much connection time: "+
+      dbConn.getConnectionTime(), 50);
+      return false;
+    }
+    
+    //Check if the DBConnection is too old
+    if (dbConn.getAge() >=MAXIMUMAGE)
+    {
+      MetaCatUtil.debugMessage("Connection is too old: "+dbConn.getAge(), 50);
+      return false;
+    }
+    
+    //Try to run a simple query
+    conn = dbConn.getConnection();
+    try
+    {
+      long startTime=System.currentTimeMillis();
+      conn.getMetaData();
+      long stopTime=System.currentTimeMillis();
+      //increase one usagecount
+      dbConn.increaseUsageCount(1);
+      //increase connection time
+      dbConn.setConnectionTime(stopTime-startTime);
   
+    }
+    catch (Exception e)
+    {
+      MetaCatUtil.debugMessage("Error in validateDBConnection: "
+                                +e.getMessage(), 30);
+      return false;
+    }
+    
+    return true;
+    
+  }//validateDBConnection()
+  
 }//DBConnectionPool
