package org.jfox.jdbc.xa;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.StringRefAddr;
import javax.sql.DataSource;
import javax.sql.XAConnection;
import javax.sql.XADataSource;
import javax.transaction.Status;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import org.huihoo.jfox.system.ComponentSupport;
import org.jfox.tm.TxManager;
public class TxDataSource extends ComponentSupport
implements DataSource,
XADataSource,
Referenceable {
private String dsName = null;
private String dbUrl = null;
private String user = null;
private String password = null;
private int initNum = 5;
private int maxRest = 10;
private int transactionIsolation = Connection.TRANSACTION_READ_COMMITTED;
private XAConnectionPool pool = null;
private static TransactionManager tm = null;
TxDataSource(String dsName, String dbUrl, String user, String password) {
this.dsName = dsName;
this.dbUrl = dbUrl;
this.user = user;
this.password = password;
}
TxDataSource(String dbUrl, String user, String password) {
this.dbUrl = dbUrl;
this.user = user;
this.password = password;
}
public int getLoginTimeout() throws SQLException {
return ((XAConnectionFactory)pool.getObjectFactory()).getLoginTimeout();
}
public void setLoginTimeout(int seconds) throws SQLException {
((XAConnectionFactory)pool.getObjectFactory()).setLoginTimeout(seconds);
}
public PrintWriter getLogWriter() throws SQLException {
return ((XAConnectionFactory)pool.getObjectFactory()).getLogWriter();
}
public void setLogWriter(PrintWriter out) throws SQLException {
((XAConnectionFactory)pool.getObjectFactory()).setLogWriter(out);
}
public Connection getConnection() throws SQLException {
return getConnection(user,password);
}
public Connection getConnection(String username, String password) throws SQLException {
return getXAConnection(username,password).getConnection();
}
public XAConnection getXAConnection() throws SQLException {
return getXAConnection(user,password);
}
public XAConnection getXAConnection(String user, String password) throws SQLException {
if(pool == null) throw new SQLException("please run init() to build connection pool first.");
int txStatus = Status.STATUS_NO_TRANSACTION;
Transaction tran = null;
try {
txStatus = tm.getStatus();
if(txStatus == Status.STATUS_NO_TRANSACTION) {
throw new SQLException("can not getXAConnection while current thread is not in Transaction context!");
}
tran = tm.getTransaction();
if(XAConnectionManager.isAssociated(tran,dbUrl,user,password)){
return XAConnectionManager.getXAConnection(tran,dbUrl,user,password);
}
}
catch(SystemException e){
logger.error("getXAConnection associate current transaction error", e);
}
XAConnection xaconn = null;
try {
if(!user.equals(this.user) || !password.equals(this.password)) {
xaconn = (XAConnection)pool.retrieveObject(user,password);
}
else{
xaconn = (PoolableXAConnection)pool.retrieveObject();
}
}
catch(Exception e){
logger.warn("retrieve object exception ", e);
if(e instanceof SQLException) {
throw (SQLException)e;
}
else {
throw new SQLException(e.getMessage());
}
}
return xaconn;
}
public Reference getReference() throws NamingException {
Reference ref = new Reference(getClass().getName(), XADataSourceObjectFactory.class.getName(), null);
ref.add(new StringRefAddr("user", getUser()));
ref.add(new StringRefAddr("password", getPassword()));
ref.add(new StringRefAddr("dbURL", getDbUrl()));
ref.add(new StringRefAddr("dsName", getDsName()));
return ref;
}
public String getDsName() {
return dsName;
}
public String getDbUrl() {
return dbUrl;
}
public String getUser() {
return user;
}
public String getPassword() {
return password;
}
public int getMaxRest() {
return maxRest;
}
public int getInitNum(){
return initNum;
}
public void setInitNum(int initNum) {
this.initNum = initNum;
}
public void setMaxRest(int maxRest) {
this.maxRest = maxRest;
}
public void setTransactionIsolation(int level) {
transactionIsolation = level;
}
public int getTransactionIsolation() {
return transactionIsolation;
}
static TransactionManager getTransactionManager(){
return tm;
}
protected void doInit() throws Exception {
if(tm==null){
try {
tm = TxManager.getInstance();
}
catch(Exception e){
throw new RuntimeException(e);
}
}
XAConnectionFactory xaConnFactory = new XAConnectionFactory(dbUrl,user,password);
xaConnFactory.setTransactionIsolation(transactionIsolation);
pool = new XAConnectionPool(xaConnFactory,initNum,maxRest);
pool.init();
}
protected void doDestroy() throws Exception {
pool.destroy();
pool = null;
XADataSourceManager.unregisterDataSource(dsName);
}
public static void main(String[] args) {
}
}