package org.enhydra.jdbc.pool;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import javax.sql.ConnectionEvent;
import javax.sql.ConnectionEventListener;
import javax.sql.ConnectionPoolDataSource;
import javax.sql.DataSource;
import javax.sql.PooledConnection;
import org.enhydra.jdbc.core.CoreDataSource;
import org.enhydra.jdbc.core.JdbcThreadFactory;
import org.enhydra.jdbc.util.Logger;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class StandardPoolDataSource
extends CoreDataSource
implements DataSource, PoolHelper, ConnectionEventListener {
public ConnectionPoolDataSource cpds;
public GenericPool pool;
public String dataSourceName;
public String jdbcTestStmt;
public boolean onOff;
public Context ictx;
public Log glog = LogFactory.getLog("org.enhydra.jdbc.xapool");
public StandardPoolDataSource() {
log = new Logger(glog);
super.setLogWriter(log);
pool = new GenericPool(this);
pool.setLogger(log);
onOff = false;
dataSourceName = null;
}
public StandardPoolDataSource(int initSize) {
log = new Logger(glog);
super.setLogWriter(log);
pool = new GenericPool(this, initSize);
pool.setLogger(log);
onOff = false;
dataSourceName = null;
}
public StandardPoolDataSource(ConnectionPoolDataSource cc) {
cpds = cc;
log = new Logger(glog);
super.setLogWriter(log);
pool = new GenericPool(this);
pool.setLogger(log);
try {
cpds.setLogWriter(log);
} catch (SQLException sqle) {
}
onOff = false;
dataSourceName = null;
}
public StandardPoolDataSource(
ConnectionPoolDataSource cc,
int initSize) {
cpds = cc;
log = new Logger(glog);
super.setLogWriter(log);
pool = new GenericPool(this, initSize);
pool.setLogger(log);
onOff = false;
dataSourceName = null;
}
public void setDataSourceName(String dataSourceName) {
log.debug("StandardPoolDataSource:setDataSourceName");
this.dataSourceName = dataSourceName;
}
public String getDataSourceName() {
return dataSourceName;
}
public Connection getConnection() throws SQLException {
return getConnection(getUser(), getPassword());
}
public Connection getConnection(String _user, String _password)
throws SQLException {
log.debug("StandardPoolDataSource:getConnection");
Connection ret = null;
PooledConnection con = null;
synchronized (this) {
if (!onOff) {
log.debug(
"StandardPoolDataSource:getConnection must configure the pool...");
pool.start();
onOff = true;
log.debug(
"StandardPoolDataSource:getConnection pool config : \n"
+ pool.toString());
}
}
try {
try {
log.debug(
"StandardPoolDataSource:getConnection Try to give a "
+ "connection (checkOut)");
con = (PooledConnection) pool.checkOut(_user, _password);
log.debug(
"StandardPoolDataSource:getConnection checkOut return"
+ "a new connection");
} catch (Exception e) {
e.printStackTrace();
log.debug(
"StandardPoolDataSource:getConnection SQLException in StandardPoolDataSource:getConnection"
+ e);
throw new SQLException(
"SQLException in StandardPoolDataSource:getConnection no connection available "
+ e);
}
ret = con.getConnection();
} catch (Exception e) {
log.debug("StandardPoolDataSource:getConnection exception" + e);
e.printStackTrace();
SQLException sqle =
new SQLException(
"SQLException in StandardPoolDataSource:getConnection exception: "
+ e);
if (e instanceof SQLException)
sqle.setNextException((SQLException) e);
if (con != null) {
pool.checkIn(con);
}
throw sqle;
}
log.debug("StandardPoolDataSource:getConnection return a connection");
return ret;
}
public void connectionErrorOccurred(ConnectionEvent event) {
Object obj = event.getSource();
PooledConnection pc = (PooledConnection) obj;
pool.nextGeneration(pc);
pool.removeLockedObject(pc);
expire(pc);
log.debug(
"StandardXAPoolDataSource:connectionErrorOccurred remove the object from the pool");
}
public void connectionClosed(ConnectionEvent event) {
log.debug(
"StandardPoolDataSource:connectionClosed close the connection");
Object obj = event.getSource();
pool.checkIn(obj);
}
public void expire(Object o) {
log.debug(
"StandardPoolDataSource:expire expire a connection, remove from the pool");
if (o == null)
return;
try {
PooledConnection pooledCon = (PooledConnection) o;
pooledCon.close();
pooledCon.removeConnectionEventListener(this);
log.debug("StandardPoolDataSource:expire close the connection");
} catch (java.sql.SQLException e) {
log.error(
"StandardPoolDataSource:expire Error java.sql.SQLException in StandardPoolDataSource:expire");
}
}
public boolean checkThisObject(Object o) {
PooledConnection con;
Connection ret;
log.debug(
"StandardPoolDataSource:checkThisObject verify the current object");
try {
con = (PooledConnection) o;
ret = con.getConnection();
if (ret.isClosed()) {
return false;
}
try {
ret.close();
} catch (Exception e) {
log.error(
"StandardPoolDataSource:checkThisObject can't closed the connection: "
+ e);
}
return true;
} catch (java.sql.SQLException e) {
log.error(
"StandardPoolDataSource:checkThisObject Error java.sql.SQLException in StandardPoolDataSource:checkThisObject");
return false;
}
}
public boolean testThisObject(Object o) {
Connection ret = null;
log.debug(
"StandardPoolDataSource:testThisObject verify the current object");
try {
PooledConnection con = (PooledConnection) o;
ret = con.getConnection();
Statement s = ret.createStatement();
s.execute(jdbcTestStmt);
s.close();
try {
ret.close();
} catch (Exception e) {
log.error(
"StandardPoolDataSource:checkThisObject can't closed the connection: "
+ e);
}
return true;
} catch (java.sql.SQLException e) {
log.error(
"StandardPoolDataSource:checkThisObject Error java.sql.SQLException in StandardPoolDataSource:testThisObject");
return false;
}
}
public GenerationObject create() throws SQLException {
return create(getUser(), getPassword());
}
public GenerationObject create(String _user, String _password)
throws SQLException {
log.debug(
"StandardPoolDataSource:create create a connection for the pool");
GenerationObject genObject;
PooledConnection pooledCon = cpds.getPooledConnection(_user, _password);
pooledCon.addConnectionEventListener(this);
log.debug("StandardPoolDataSource:create create a object for the pool");
genObject =
new GenerationObject(
pooledCon,
pool.getGeneration(),
_user,
_password);
return genObject;
}
public void stopPool() {
pool.stop();
onOff = false;
log.debug("StandardPoolDataSource:stopPool stop now the pool");
}
public void shutdown(boolean force) {
stopPool();
}
public void setLogWriter(PrintWriter logWriter) {
pool.setLogger(log);
super.setLogger(log);
}
public void setDebug(boolean debug) {
super.setDebug(debug);
pool.setDebug(debug);
}
public void setMinSize(int minSize) throws Exception {
pool.setMinSize(minSize);
}
public void setMaxSize(int maxSize) throws Exception {
pool.setMaxSize(maxSize);
}
public void setLifeTime(long lifeTime) {
pool.setLifeTime(lifeTime);
}
public void setSleepTime(long sleepTime) {
pool.setSleepTime(sleepTime);
}
public void setGC(boolean gc) {
pool.setGC(gc);
}
public void setCheckLevelObject(int checkLevelObject) {
pool.setCheckLevelObject(checkLevelObject);
}
public void setJdbcTestStmt(String jdbcTestStmt) {
this.jdbcTestStmt = jdbcTestStmt;
}
public void setGeneration(int generation) {
pool.setGeneration(generation);
}
public void setDeadLockMaxWait(long deadLock) {
pool.setDeadLockMaxWait(deadLock);
}
public void setDeadLockRetryWait(long loopWait) {
pool.setDeadLockRetryWait(loopWait);
}
public PrintWriter getLogWriter() {
return log;
}
public int getMinSize() {
return pool.getMinSize();
}
public int getMaxSize() {
return pool.getMaxSize();
}
public long getLifeTime() {
return pool.getLifeTime();
}
public long getSleepTime() {
return pool.getSleepTime();
}
public int getGeneration() {
return pool.generation;
}
public boolean isGC() {
return pool.isGC();
}
public int getLockedObjectCount() {
return pool.getLockedObjectCount();
}
public int getUnlockedObjectCount() {
return pool.getUnlockedObjectCount();
}
public int getCheckLevelObject() {
return pool.getCheckLevelObject();
}
public String getJdbcTestStmt() {
return jdbcTestStmt;
}
public long getDeadLockMaxWait() {
return pool.getDeadLockMaxWait();
}
public long getDeadLockRetryWait() {
return pool.getDeadLockRetryWait();
}
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append("StandardPoolDataSource:\n");
sb.append(" data source name=<"+this.dataSourceName+">\n");
sb.append(" jdbc test stmt=<"+this.jdbcTestStmt+">\n");
sb.append(" user=<"+this.user+">\n");
if (this.cpds != null)
sb.append(this.cpds.toString());
sb.append(pool.toString());
return sb.toString();
}
public Reference getReference() throws NamingException {
log.debug(
"StandardPoolDataSource:getReference return a reference of the object");
Reference ref = super.getReference();
ref.add(
new StringRefAddr(
"checkLevelObject",
Integer.toString(getCheckLevelObject())));
ref.add(new StringRefAddr("lifeTime", Long.toString(getLifeTime())));
ref.add(new StringRefAddr("jdbcTestStmt", getJdbcTestStmt()));
ref.add(new StringRefAddr("maxSize", Integer.toString(getMaxSize())));
ref.add(new StringRefAddr("minSize", Integer.toString(getMinSize())));
ref.add(new StringRefAddr("dataSourceName", getDataSourceName()));
return ref;
}
public Object getObjectInstance(
Object refObj,
Name name,
Context nameCtx,
Hashtable env)
throws Exception {
super.getObjectInstance(refObj, name, nameCtx, env);
Reference ref = (Reference) refObj;
this.setLifeTime(
Long.parseLong((String) ref.get("lifeTime").getContent()));
this.setJdbcTestStmt((String) ref.get("jdbcTestStmt").getContent());
this.setMaxSize(
Integer.parseInt((String) ref.get("maxSize").getContent()));
this.setMinSize(
Integer.parseInt((String) ref.get("minSize").getContent()));
this.setDataSourceName((String) ref.get("dataSourceName").getContent());
InitialContext ictx = new InitialContext(env);
cpds = (ConnectionPoolDataSource) ictx.lookup(this.dataSourceName);
return this;
}
public void setThreadFactory(JdbcThreadFactory tf) {
super.setThreadFactory(tf);
pool.setThreadFactory(tf);
}
}