StandardXAPoolDataSource.java :  » Database-JDBC-Connection-Pool » xapool » org » enhydra » jdbc » pool » Java Open Source

Java Open Source » Database JDBC Connection Pool » xapool 
xapool » org » enhydra » jdbc » pool » StandardXAPoolDataSource.java
/*
 * XAPool: Open Source XA JDBC Pool
 * Copyright (C) 2003 Objectweb.org
 * Initial Developer: Lutris Technologies Inc.
 * Contact: xapool-public@lists.debian-sf.objectweb.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 */
package org.enhydra.jdbc.pool;

import java.sql.SQLException;
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.XAConnection;
import javax.sql.XADataSource;
import javax.transaction.TransactionManager;
import javax.transaction.Transaction;
import javax.transaction.SystemException;
import javax.transaction.xa.XAResource;
import org.enhydra.jdbc.standard.StandardXADataSource;
import org.enhydra.jdbc.standard.StandardXAConnection;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.sql.Connection;
import java.sql.Statement;
import javax.sql.PooledConnection;
import javax.transaction.Status;

/**
 * StandardXAPoolDataSource class allows to make some operations on
 * XAConnection. It implements PoolHelper for the 3 methods :<p>
 * create   : create an XAConnection<p>
 * create(user,password)   : create a PooledConnection with an other user/password<p>
 * testThisObject : check if the object is still valid<p>
 * checkThisObject : check if the object is closed<p>
 * expire   : kill the object<p>
 */
public class StandardXAPoolDataSource extends StandardPoolDataSource {

  public XADataSource xads; // object to build XAConnection
  public TransactionManager transactionManager;
    public String transactionManagerName;

  // the current Transaction Manager
  public Log glog = LogFactory.getLog("org.enhydra.jdbc.xapool");

  /**
   * Constructor
   */
  public StandardXAPoolDataSource() {
    super();
  }

  /**
   * Constructor
   */
  public StandardXAPoolDataSource(int initSize) {
    super(initSize);
  }

  /**
   * Constructor
   */
  public StandardXAPoolDataSource(StandardXADataSource ds) {
    super(ds);
                setDataSource(ds);
  }

  /**
   * Constructor
   */
  public StandardXAPoolDataSource(StandardXADataSource ds, int initSize) {
    super(ds, initSize);
                setDataSource(ds);
  }

  public void setTransactionManager(TransactionManager tm) {
    log.debug("StandardXAPoolDataSource:setTransactionManager");
    transactionManager = tm;
  }

  /**
   * Invoked when the application calls close()
   * on its representation of the connection
   */
  public void connectionClosed(ConnectionEvent event) {
    Object obj = event.getSource();
    log.debug("StandardXAPoolDataSource:connectionClosed");
    XAConnection xac = (XAConnection) obj; // cast it into an xaConnection

    Transaction tx = null;
    try {
      if (transactionManager == null) {
        TransactionManager tm =
          ((StandardXADataSource) xads).getTransactionManager();
        if (tm == null) {
          throw new NullPointerException("TM is null");
        } else
          // here we use tm instead to setup transactionManager = tm
          // if the current transactionManager property is null, it stays
          // there, and we continue to use the TM from the XADataSource
          tx = tm.getTransaction();
      } else {
        tx = transactionManager.getTransaction();
      }
      log.debug(
        "StandardXAPoolDataSource:connectionClosed get a transaction");
    } catch (NullPointerException n) {
      // current is null: we are not in EJBServer.
      log.error(
        "StandardXAPoolDataSource:connectionClosed should not be used outside an EJBServer");
    } catch (SystemException e) {
      log.error(
        "StandardXAPoolDataSource:connectionClosed getTransaction failed:"
          + e);
    }

    // delist Resource if in transaction
    // We must keep the connection till commit or rollback
    if ((tx != null)
      && (((StandardXAConnection) xac).connectionHandle.isReallyUsed)) {
      try {
        tx.delistResource(xac.getXAResource(), XAResource.TMSUCCESS);
        // delist the xaResource
        log.debug(
          "StandardXAPoolDataSource:connectionClosed the resourse is delisted");
      } catch (Exception e) {
        log.error(
          "StandardXAPoolDataSource:connectionClosed Exception in connectionClosed:"
            + e);
      }
    }
    log.debug(
      "StandardXAPoolDataSource:connectionClosed checkIn an object to the pool");
    pool.checkIn(obj); // return the connection to the pool
  }

  public GenerationObject create(String _user, String _password)
    throws SQLException {
    GenerationObject genObject;
    XAConnection xaCon = xads.getXAConnection(_user, _password);
    // get the xa connection
    xaCon.addConnectionEventListener(this); // add it to the event listener
    log.debug(
      "StandardXAPoolDataSource:create create a object for the pool");
    genObject =
      new GenerationObject(xaCon, pool.getGeneration(), _user, _password);

    return genObject;
  }

  /**
   * Retrieves the Reference of this object. Used at binding time by JNDI
   * to build a reference on this object.
   *
   * @return  The non-null Reference of this object.
   * @exception  NamingException  If a naming exception was encountered while
   * retrieving the reference.
   */
  public Reference getReference() throws NamingException {
    log.debug(
      "StandardXAPoolDataSource:getReference return a reference of the object");
    Reference ref = super.getReference();
    ref.add(new StringRefAddr("transactionManagerName", this.transactionManagerName));

    return ref;
  }

  /* (non-Javadoc)
   * @see javax.naming.spi.ObjectFactory#getObjectInstance(java.lang.Object, javax.naming.Name, javax.naming.Context, java.util.Hashtable)
   */
  public Object getObjectInstance(
    Object refObj,
    Name name,
    Context nameCtx,
    Hashtable env)
    throws Exception {

    super.getObjectInstance(refObj, name, nameCtx, env);
    Reference ref = (Reference) refObj;
    InitialContext ictx = new InitialContext(env);
    this.setTransactionManagerName((String) ref.get("transactionManagerName").getContent());
    if (this.transactionManagerName != null) {
        try {
      this.setTransactionManager(
               (TransactionManager) ictx.lookup(this.transactionManagerName));
        } catch (NamingException e) {
      // ignore, TransactionManager might be set later enlisting the XAResouce on the Transaction
        }
    }
    

    this.setDataSource((XADataSource) ictx.lookup(this.dataSourceName));
    log.debug("StandardXAPoolDataSource:getObjectInstance: instance created");
    return this;
  }

  /** Getter for property dataSource.
   * @return Value of property dataSource.
   */
  public XADataSource getDataSource() {
    return xads;
  }

  /** Setter for property dataSource.
   * @param dataSource New value of property dataSource.
   */
  public void setDataSource(XADataSource dataSource) {
    this.xads = dataSource;
    if (transactionManager != null)
      ((StandardXADataSource) dataSource).setTransactionManager(
        transactionManager);
    if (transactionManagerName != null)
        ((StandardXADataSource) dataSource).setTransactionManagerName(transactionManagerName);
  }
  
  
  public String toString() {
    StringBuffer sb = new StringBuffer();
    sb.append("StandardXAPoolDataSource:\n");
                if (this.transactionManager != null)
            sb.append("     transaction manager=<"+this.transactionManager.toString()+">\n");
                if (this.xads != null)
            sb.append(this.xads.toString());
    sb.append(super.toString());    
    return sb.toString();
  }

    /**
     * This method tests if a connection is valid or not. It overrides the
     * method in StandardPoolDataSource to take into account global transactions:
     * if global transaction is in progress - suspend it so that
     * connection testing happens ouside of transaction.
     * If connection testing fails - it will not affect transaction
     * and next good connection can join the transaction
     */
     public boolean testThisObject(Object o) {
        Connection ret = null;
        log.debug(
            "StandardXAPoolDataSource:testThisObject verify the current object");
        Transaction suspended = null;
        try {
            Transaction tx = transactionManager == null
                                ? null
                                : transactionManager.getTransaction();
            boolean isActive = tx == null
                                ? false
                                : tx.getStatus() == Status.STATUS_ACTIVE;
            if (isActive) {
                suspended = transactionManager.suspend();
            }


            PooledConnection con = (PooledConnection) o;
            ret = con.getConnection();



            Statement s = ret.createStatement();
            s.execute(jdbcTestStmt);
            s.close();
            try {
                ret.close();
            } catch (Exception e) {
                log.error(
                    "StandardXAPoolDataSource:checkThisObject can't closed the connection: "
                        + e);
            }
            return true;
        } catch (SQLException e) {
            log.error(
                "StandardXAPoolDataSource:checkThisObject Error java.sql.SQLException in StandardXAPoolDataSource:testThisObject");
            return false;
        } catch (SystemException e) {
            log.error(
                "StandardXAPoolDataSource:checkThisObject Error java.sql.SystemException in StandardXAPoolDataSource:testThisObject");
            return false;
        } finally {
            if (suspended != null) {
                try {
                    transactionManager.resume(suspended);
                } catch (Exception ex) {
                    log.error(
                        "StandardXAPoolDataSource:checkThisObject Error Exception in StandardXAPoolDataSource:testThisObject");
                    return false;
                }
            }
        }
    }
    public void setTransactionManagerName(String tmName) {
        log.debug("StandardXAPoolDataSource:setTransactionManagerName");
        transactionManagerName = tmName;
    }



}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.