import java.io.*;
import java.sql.*;
import java.util.*;
import java.util.date;
/**
* this class is a singleton that provides access to one or many
* connection pools defined in a property file. a client gets
* access to the single instance through the static getinstance()
* method and can then check-out and check-in connections from a pool.
* when the client shuts down it should call the release() method
* to close all open connections and do other clean up.
*/
public class dbconnectionmanager {
static private dbconnectionmanager instance; // the single instance
static private int clients;
private vector drivers = new vector();
private printwriter log;
private hashtable pools = new hashtable();
/**
* returns the single instance, creating one if it's the
* first time this method is called.
*
* @return dbconnectionmanager the single instance.
*/
static synchronized public dbconnectionmanager getinstance() {
if (instance == null) {
instance = new dbconnectionmanager();
}
clients++;
return instance;
}
/**
* a private constructor since this is a singleton
*/
private dbconnectionmanager() {
init();
}
/**
* returns a connection to the named pool.
*
* @param name the pool name as defined in the properties file
* @param con the connection
*/
public void freeconnection(string name, connection con) {
dbconnectionpool pool = (dbconnectionpool) pools.get(name);
if (pool != null) {
pool.freeconnection(con);
}
}
/**
* returns an open connection. if no one is available, and the max
* number of connections has not been reached, a new connection is
* created.
*
* @param name the pool name as defined in the properties file
* @return connection the connection or null
*/
public java.sql.connection getconnection(string name) {
dbconnectionpool pool = (dbconnectionpool) pools.get(name);
if (pool != null) {
return pool.getconnection();
}
return null;
}
/**
* returns an open connection. if no one is available, and the max
* number of connections has not been reached, a new connection is
* created. if the max number has been reached, waits until one
* is available or the specified time has elapsed.
*
* @param name the pool name as defined in the properties file
* @param time the number of milliseconds to wait
* @return connection the connection or null
*/
public java.sql.connection getconnection(string name, long time) {
dbconnectionpool pool = (dbconnectionpool) pools.get(name);
if (pool != null) {
return pool.getconnection(time);
}
return null;
}
/**
* closes all open connections and deregisters all drivers.
*/
public synchronized void release() {
// wait until called by the last client
if (--clients != 0) {
return;
}
enumeration allpools = pools.elements();
while (allpools.hasmoreelements()) {
dbconnectionpool pool = (dbconnectionpool) allpools.nextelement();
pool.release();
}
enumeration alldrivers = drivers.elements();
while (alldrivers.hasmoreelements()) {
driver driver = (driver) alldrivers.nextelement();
try {
drivermanager.deregisterdriver(driver);
log("deregistered jdbc driver " + driver.getclass().getname());
}
catch (sqlexception e) {
log(e, "can't deregister jdbc driver: " + driver.getclass().getname());
}
}
}
/**
* creates instances of dbconnectionpool based on the properties.
* a dbconnectionpool can be defined with the following properties:
*
* <poolname>.url the jdbc url for the database
* <poolname>.user a database user (optional)
* <poolname>.password a database user password (if user specified)
* <poolname>.maxconn the maximal number of connections (optional)
*
*
* @param props the connection pool properties
*/
private void createpools(properties props) {
enumeration propnames = props.propertynames();
while (propnames.hasmoreelements()) {
string name = (string) propnames.nextelement();
if (name.endswith(".url")) {
string poolname = name.substring(0, name.lastindexof("."));
string url = props.getproperty(poolname + ".url");
if (url == null) {
log("no url specified for " + poolname);
continue;
}
string user = props.getproperty(poolname + ".user");
string password = props.getproperty(poolname + ".password");
string maxconn = props.getproperty(poolname + ".maxconn", "0");
int max;
try {
max = integer.valueof(maxconn).intvalue();
}
catch (numberformatexception e) {
log("invalid maxconn value " + maxconn + " for " + poolname);
max = 0;
}
dbconnectionpool pool =
new dbconnectionpool(poolname, url, user, password, max);
pools.put(poolname, pool);
log("initialized pool " + poolname);
}
}
}
/**
* loads properties and initializes the instance with its values.
*/
private void init() {
inputstream is = getclass().getresourceasstream("/db.properties");
properties dbprops = new properties();
try {
dbprops.load(is);
}
catch (exception e) {
system.err.println("can't read the properties file. " +
"make sure db.properties is in the classpath");
return;
}
string logfile = dbprops.getproperty("logfile", "dbconnectionmanager.log");
try {
log = new printwriter(new filewriter(logfile, true), true);
}
catch (ioexception e) {
system.err.println("can't open the log file: " + logfile);
log = new printwriter(system.err);
}
loaddrivers(dbprops);
createpools(dbprops);
}
/**
* loads and registers all jdbc drivers. this is done by the
* dbconnectionmanager, as opposed to the dbconnectionpool,
* since many pools may share the same driver.
*
* @param props the connection pool properties
闽公网安备 35060202000074号