Package org.objectweb.speedo.jca

Source Code of org.objectweb.speedo.jca.SpeedoManagedConnection

/**
* perseus/connector: this is an implementation of some JCA-related technologies
* (resource adapters and managers) for the ObjectWeb consortium.
* Copyright (C) 2001-2004 France Telecom R&D
*
* 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 of the License, or (at your option) 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
*
* Contact: speedo@objectweb.org
*
*/

package org.objectweb.speedo.jca;

import org.objectweb.speedo.api.Debug;
import org.objectweb.speedo.api.ExceptionHelper;
import org.objectweb.speedo.pm.api.POManagerItf;
import org.objectweb.speedo.workingset.api.TransactionItf;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;

import javax.jdo.JDOFatalException;
import javax.resource.ResourceException;
import javax.resource.cci.Connection;
import javax.resource.spi.*;
import javax.security.auth.Subject;
import javax.transaction.RollbackException;
import javax.transaction.TransactionManager;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;

/**
* @author  P. Dechamboux
*/
public class SpeedoManagedConnection
    implements ManagedConnection,
    javax.resource.spi.LocalTransaction,
    javax.resource.cci.LocalTransaction,
    XAResource,
        ManagedConnectionMetaData {

  public final static String EIS_PRODUCT_NAME = "Speedo Resource Adapter";
  public final static String EIS_PRODUCT_VERSION = "1.0";
  public final static String USER_NAME = "No user name needed to use the Speedo driver";

  /**
   * The logger into which traces about SpeedoManagedConnection are produced.
   */
  private Logger logger;

  /**
   * The ManagedConnectionFactory that have requested the allocation of this
   * ManagedConnection.
   */
  private SpeedoManagedConnectionFactory mcf;

  /**
   * The logical Connections associated with this ManagedConnection. Always
   * at least one connection except when the MC is in the pool.
   */
  private ArrayList logicalConnections = new ArrayList(1);

  /**
   * The ConnectionEventListener list associated with this ManagedConnection.
   */
  private ArrayList listeners = null;

  /**
   * It is set if the ManagedConnection execute within a LocalTransaction.
   */
  private POManagerItf localTransactionPM = null;

  /**
   * It is the current SpeedoXAContext. It is not null when the ManagedConnection
   * is used in a XA transaction through the XAResource interface.
   */
  public SpeedoXAContext xac;

  /**
   * It is set if Speedo operation occurs outside any explicit (LocalTransaction)
   * or implicit (XAResource) transaction context.
   */
  private POManagerItf defaultPM = null;

  protected SpeedoConnectionSpec cri = null;

  /**
   * Constructs a SpeedoManagedConnection.
   * @param el  The logger into which to produce ManagedConnection-related
   *         traces.
   * @param fmcf  The ManagedConnectionFactory that has requested the
   *         ManagedConnection creation.
   */
  SpeedoManagedConnection(Logger el, SpeedoManagedConnectionFactory fmcf) {
    logger = el;
    if (Debug.ON && logger != null)
      logger.log(BasicLevel.DEBUG,
             "Constructs a new SpeedoManagedConnection");
    mcf = fmcf;
    listeners = null;
  }

  /**
   * Retrieves the right POManagerItf in according the managed connection
   * state (in a local transaction, in a XA transaction or out of transaction)
   *
   * @return a POManagerItf instance (never null).
   */
  public POManagerItf getPOManager() {
    if (localTransactionPM != null) {
      if (Debug.ON && logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
        logger.log(BasicLevel.DEBUG, "return localTransactionPM: "
                       + localTransactionPM);
      }
      return localTransactionPM;
    }
    if (xac != null) {
      if (Debug.ON && logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
        logger.log(BasicLevel.DEBUG,
               "xac.status= " + xac.status
               + "xac.xid= " + xac.xid);
      }
      if (xac.status != SpeedoXAContext.STARTED) {
        throw new JDOFatalException(
            "XA context should have been started here: xac.status= "
            + xac.status + "xac.xid= " + xac.xid);
      }
      if (xac.pm == null) {
        synchronized(xac) {
          if (xac.pm == null) {
            xac.pm = (POManagerItf) mcf.pmf.getPOManager();
            if (Debug.ON && logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
              logger.log(BasicLevel.DEBUG,
                  "Creates a PersistenceManager (" + xac.pm
                  + ") associated to the XID: " + xac.xid);
            }
          }
        }
      }
      if (!xac.synchroRegistred) {
        //Register the PersistenceManager on the first use
        try {
          registerSynchronization();
        } catch (XAException ex) {
            JDOFatalException e = new JDOFatalException(
               "Problem while registering a synchronization.", ex);
                    if (logger != null) {
                        logger.log(BasicLevel.ERROR, e.getMessage(), ex);
                    }
          throw e;
        }
      }
      return xac.pm;
    }
    if (defaultPM == null) {
      defaultPM = (POManagerItf) mcf.pmf.getPOManager();
    }
    if (Debug.ON && logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
      logger.log(BasicLevel.DEBUG,
             "return the default persistence manager: " + defaultPM);
    }
    return defaultPM;
  }


  /**
   * find the SpeedoXAContext matching an Xid.
   * @param flag indicates expecting behavior:<UL>
   * <LI>0: create the SpeedoXAContext if it does not already exist</LI>
   * <LI>1: return an existing SpeedoXAContext</LI>
   * <LI>otherwise: return an SpeedoXAContext or null it is not found</LI>
   * </UL>
   */
  public SpeedoXAContext getXAContext(Xid xid, int flag)
      throws XAException {
        if (mcf == null) {
            //The MC has been destroyed, and the contexts has beean rolled back
            return null;
        }
    SpeedoXAContext _xac = mcf.getXAContext(xid);
    if (_xac == null) {
      if (flag == 0) { //create it
        try {
          _xac = mcf.createXAContext(xid);
        } catch (RuntimeException fe) {
          Exception ie = ExceptionHelper.getNested(fe);
          XAException e = new XAException(
              "Error during the creation of the XA context with the xid: "
              + xid + ", error message:" + ie.getMessage());
                    if (logger != null) {
                        logger.log(BasicLevel.ERROR, ie.getMessage(), ie);
                    }
          throw e;
        }
      } else if (flag == 1) { // throw an exception
        XAException e = new XAException("No XA context found for the xid=" + xid);
                if (logger != null) {
                    logger.log(BasicLevel.ERROR, e.getMessage(), e);
                }
        throw e;
      } // else return null
    }
    return _xac;
  }

  /**
   * Registers the POManagerItf of the current SpeedoXAContext to the current
   * transaction, if it is not already done.
   *
   * @throws XAException if the registering is not possible:
   * - TM not availlable
   * - Pr
   */
  public synchronized void registerSynchronization() throws XAException {
    if (xac.synchroRegistred) {
      return;
    }
    TransactionItf tx = xac.pm.getSpeedoTransaction();
    if (tx.isActive() && logger != null) {
      logger.log(BasicLevel.WARN, "Speedo TransactionItf started and the " +
          "PersistenceManager is not marked as registered to " +
          "the XA transaction");
    }
    if (Debug.ON && logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
      logger.log(BasicLevel.DEBUG, "registerSynchronization");
    }
    TransactionManager tm = mcf.tm;
    if (tm == null) {
      String msg = "Impossible to register the Speedo " +
          "container as synchronization on the current transaction: " +
          (tm == null
          ? "The transaction manager has not found with the JNDI name: "
          + mcf.getTransactionManagerJNDIName()
          : "The TransactionItf object of the Speedo implementation does not implement javax.transaction.Synchronization");
      if (logger != null) {
          logger.log(BasicLevel.ERROR, msg);
            }
      throw new XAException(msg);
    }
    try {
      tm.getTransaction().registerSynchronization(xac.pm);
      if (!tx.isActive()) {
        tx.begin();
      }
      xac.synchroRegistred = true;
    } catch (RollbackException e) {
      //The JDO container cannot be registered then the transaction
      // must be rolledback
      if (tx.isActive()) {
        tx.rollback();
      }
    } catch (Exception e) {
      String msg = "Impossible to register the Speedo " +
          "container as synchronization on the current" +
          " transaction: " + e.getMessage();
            if (logger != null) {
                logger.log(BasicLevel.ERROR, msg, e);
            }
      throw new XAException(msg);
    }
  }

  /**
   * Specifies if this ManagedConnection still has an active LocalTransaction.
   * @return  true if a LocalTransaction is still active.
   */
  public boolean localTransactionTerminated() {
    return localTransactionPM == null;
  }

  /**
   * Dissociates a Connection from the ones that are associated to this
   * ManagedConnection.
   * @param conn  The Connection to be dissociated.
   */
  public synchronized void dissociateConnection(Object conn) throws ResourceException {
    int ind = logicalConnections.indexOf(conn);
        if (ind == -1) {
            throw new ResourceException("Speedo Connector: cannot dissociate an unknown Connection:"
                    + conn + "\n among " + logicalConnections);
        }
        if (Debug.ON && logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
            logger.log(BasicLevel.DEBUG, "Dissociates Connection (" + ind + "): " + conn);
        }
    logicalConnections.remove(ind);
    ConnectionEvent ce = new ConnectionEvent(this, ConnectionEvent.CONNECTION_CLOSED);
    ce.setConnectionHandle(conn);
        if (listeners != null) {
      synchronized(this) {
        for (int i=0; i<listeners.size();) {
          ConnectionEventListener cel = (ConnectionEventListener) listeners.get(i);
          cel.connectionClosed(ce);
          if (i<listeners.size() && cel == listeners.get(i)) {
            i++;
          }// else the listeners has been removed
        }
      }
        }
  }

 
  // IMPLEMENTATION OF METHODS FROM THE (cci)ManagedConnectionMetaData INTERFACE

    public String getEISProductName() throws ResourceException {
        return EIS_PRODUCT_NAME;
    }

    public String getEISProductVersion() throws ResourceException {
        return EIS_PRODUCT_VERSION;
    }

    public int getMaxConnections() throws ResourceException {
    // TODO: analysis of ra.xml values
    return 10;
    }

    public String getUserName() throws ResourceException {
        return USER_NAME;
    }


  // IMPLEMENTATION OF METHODS FROM THE (cci)ManagedConnection INTERFACE //
  //---------------------------------------------------------------------//

  /**
   * Delegates the creation of a Connection to the ConnectionFactory.
   * "subject" and "info" parameters are ignored.
   */
  public Object getConnection(Subject subject, ConnectionRequestInfo info)
      throws ResourceException {
    SpeedoConnection rac = (SpeedoConnection) mcf.connectionFactory.createConnection();
    rac.initialize(this);
        associateConnection(rac);
    return rac;
  }

  /**
   * Cleans up the connection.
   */
  public void cleanup() throws ResourceException {
    if (Debug.ON && logger != null)
      logger.log(BasicLevel.DEBUG, "Cleans up ManagedConnection");
    int s = (logicalConnections == null ? 0 : logicalConnections.size());
    if (s > 0) {
      s -=1;
      for(int i=s; i>=0; i--) {
        ((Connection) logicalConnections.get(i)).close();
      }
    }
    if (localTransactionPM != null) {
      localTransactionPM.closePOManager();
      localTransactionPM = null;
    }
    if (defaultPM != null) {
      defaultPM.closePOManager();
      defaultPM = null;
    }
    //The specification requires to keep the XAResource associated to MC
  }

  /**
   * Called when ManagedConnection is removed.
   */
  public void destroy() throws ResourceException {
    cleanup();
    logger = null;
    mcf = null;
    logicalConnections = null;
    listeners = null;
    localTransactionPM = null;
  }

  /**
   * Associates a new Connection to this ManagedConnection. Nothing is done
   * if it has already been associated (enforces no duplicate).
   */
  public synchronized void associateConnection(Object o) throws ResourceException {
    if (Debug.ON && logger != null)
      logger.log(BasicLevel.DEBUG, "Associates Connection: " + o + " to the MC " + this);
    if (!logicalConnections.contains(o))
      logicalConnections.add(o);
    else if (logger != null)
      logger.log(BasicLevel.WARN, "Connection: " + o
                    + "has already been associated: ignored!");
  }

  /**
   * Adds a listener to the listeners list if it has not
   * already been done. This means that duplicates are ignored.
   * It first creates this list if needed (creation at first add).
   */
  public synchronized void addConnectionEventListener(
      ConnectionEventListener listener) {
    if (listeners == null)
      listeners = new ArrayList();
    if (Debug.ON && logger != null)
      logger.log(BasicLevel.DEBUG, "Associates ConnectionEventListener: "
                     + listener);
    if (!listeners.contains(listener))
      listeners.add(listener);
    else if (logger != null)
      logger.log(BasicLevel.WARN, "ConnectionEventListener: " + listener
                    + "has already been associated: ignored!");
  }

  /**
   * Removes a listener from the listeners list. If the list does
   * not eist (null), or if this listener does not belong to this list,
   * nothing is done.
   */
  public synchronized void removeConnectionEventListener(
      ConnectionEventListener listener) {
    if (listeners == null) {
      if (logger != null) {
          logger.log(BasicLevel.WARN,
             "No associated ConnectionEventListener: ignored!");
            }
      return;
    }
    int ind = listeners.indexOf(listener);
    if (Debug.ON && logger != null)
      logger.log(BasicLevel.DEBUG,
             "Index within the listeners: " + ind);
    if (ind == -1 && logger != null)
      logger.log(BasicLevel.WARN, "ConnectionEventListener" + listener
                    + "not associated here: ignored!");
    else
      listeners.remove(ind);
  }

  /**
   * Retrieves an XA resource. Switches running mode to XA.
   */
  public synchronized XAResource getXAResource() throws ResourceException {
        if (logger != null) {
            logger.log(BasicLevel.DEBUG, "getXAResource()");
        }
    if (localTransactionPM != null) {
      throw new ResourceException(
          "Try switching to XA mode while running a LocalTransaction.");
    }
    if (defaultPM != null) {
      defaultPM.closePOManager();
      defaultPM = null;
    }
    return this;
  }

  public LocalTransaction getLocalTransaction() throws ResourceException {
    return this;
  }

  public ManagedConnectionMetaData getMetaData() throws ResourceException {
    return this;
  }

  /**
   * Not supported yet.
   */
  public void setLogWriter(PrintWriter writer) throws ResourceException {
    throw new ResourceException("Speedo Connector: logging to PrintWriter not supported yet.");
  }

  /**
   * Not supported yet.
   */
  public PrintWriter getLogWriter() throws ResourceException {
    throw new ResourceException("Speedo Connector: logging to PrintWriter not supported yet.");
  }


  // IMPLEMENTATION OF METHODS FROM THE (cci)LocalTransaction INTERFACE //
  //--------------------------------------------------------------------//

  /**
   * Begins the LocalTransaction if it has not already been started.
   */
  public synchronized void begin() throws ResourceException {
    if (localTransactionPM != null) {
      throw new ResourceException("Speedo Connector: a LocalTransaction has already begun.");
    }
    try {
      if (defaultPM != null) {
        defaultPM.closePOManager();
        defaultPM = null;
      }
      localTransactionPM = (POManagerItf)
          mcf.pmf.getPOManager();
      localTransactionPM.getSpeedoTransaction().begin();
      if (Debug.ON && logger != null)
        logger.log(BasicLevel.DEBUG, "LocalTransaction begin - txContext: "
                       + localTransactionPM);
      if (xac != null && logger != null)
        logger.log(BasicLevel.WARN,
               "Begins a LocalTransaction on a ManagedConnection that runs in XA mode!");
      ConnectionEvent ce = new ConnectionEvent(this, ConnectionEvent.LOCAL_TRANSACTION_STARTED);
      if (listeners != null) {
        synchronized(this) {
            for (Iterator it = listeners.iterator(); it.hasNext();) {
            ((ConnectionEventListener) it.next()).localTransactionStarted(ce);
          }
        }
            }
    } catch (RuntimeException fe) {
      ResourceException re = new ResourceException(
          "Speedo Connector: cannot begin LocalTransaction [nested exception].");
      re.setLinkedException(fe);
      throw re;
    }
  }

  /**
   * Commits the LocalTransaction if it is active.
   */
  public synchronized void commit() throws ResourceException {
    if (localTransactionPM == null)
      throw new ResourceException("Speedo Connector: no LocalTransaction has been begun.");
    if (Debug.ON && logger != null)
      logger.log(BasicLevel.DEBUG, "LocalTransaction commit - txContext: "
                     + localTransactionPM);
    try {
      localTransactionPM.getSpeedoTransaction().commit();
      ConnectionEvent ce = new ConnectionEvent(this, ConnectionEvent.LOCAL_TRANSACTION_COMMITTED);
            if (listeners != null) {
        synchronized(this) {
            for (Iterator it = listeners.iterator(); it.hasNext();) {
              ((ConnectionEventListener) it.next()).localTransactionCommitted(ce);
          }
        }
            }
    } catch (RuntimeException fe) {
      ResourceException re = new ResourceException(
          "Speedo Connector: cannot commit LocalTransaction [nested exception].");
      re.setLinkedException(fe);
      throw re;
    } finally {
      localTransactionPM.closePOManager();
      localTransactionPM = null;
    }
  }

  /**
   * Rollbacks the LocalTransaction if it is active.
   */
  public synchronized void rollback() throws ResourceException {
    if (localTransactionPM == null)
      throw new ResourceException("Speedo Connector: no LocalTransaction has been begun.");
    if (Debug.ON && logger != null)
      logger.log(BasicLevel.DEBUG, "LocalTransaction rollback - txContext: "
                     + localTransactionPM);
    try {
      localTransactionPM.getSpeedoTransaction().rollback();
      ConnectionEvent ce = new ConnectionEvent(this, ConnectionEvent.LOCAL_TRANSACTION_ROLLEDBACK);
            if (listeners != null) {
        synchronized(this) {
            for (Iterator it = listeners.iterator(); it.hasNext();) {
              ((ConnectionEventListener) it.next()).localTransactionRolledback(ce);
          }
        }
            }
    } catch (RuntimeException fe) {
      ResourceException re = new ResourceException(
          "Speedo Connector: cannot rollback LocalTransaction [nested exception].");
      re.setLinkedException(fe);
      throw re;
    } finally {
      localTransactionPM.closePOManager();
      localTransactionPM = null;
    }
  }


  // IMPLEMENTATION OF METHODS FROM THE (jta)XAResource INTERFACE //
  //--------------------------------------------------------------//

  /**
   * Assigns an actual Speedo transaction context to the XAResource
   * within the give DTP context.
   */
  public void start(Xid xid, int i) throws XAException {
    try {
      switch(i) {
      case XAResource.TMRESUME:
        if (Debug.ON && logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
          logger.log(BasicLevel.DEBUG, "start(" + xid + ", TMRESUME)");
        }
        xac = getXAContext(xid, 1);
        if (xac.pm != null) {
          mcf.pmf.bindPM2Thread(xac.pm);
        }
        break;
      case XAResource.TMJOIN:
        if (Debug.ON && logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
          logger.log(BasicLevel.DEBUG, "start(" + xid + ", TMJOIN)");
        }
        xac = getXAContext(xid, 1);
        break;
      case XAResource.TMNOFLAGS:
        if (Debug.ON && logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
          logger.log(BasicLevel.DEBUG, "start(" + xid + ", TMNOFLAGS)");
        }
        xac = getXAContext(xid, 0);
        break;
      default:
        String msg = "Unexpected flag: " + i;
                if (logger != null) {
                    logger.log(BasicLevel.ERROR, msg);
                }
        throw new XAException(msg);
      }
      xac.status = SpeedoXAContext.STARTED;
    } catch (XAException e) {
            if (logger != null) {
                logger.log(BasicLevel.ERROR,
          "Error in the Jdo XAResource starting (" + i + ")", e);
            }
      throw e;
    } catch (RuntimeException e) {
            if (logger != null) {
                logger.log(BasicLevel.ERROR,
          "Error in the Jdo XAResource starting (" + i + ")", e);
            }
      throw e;
    }
  }

  /**
   * Unbind this instance to the PersistenceManager.
   */
  public void end(Xid xid, int i) throws XAException {
    if (Debug.ON && logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
      logger.log(BasicLevel.DEBUG, "xid=" + xid);
    }
    SpeedoXAContext _xac = getXAContext(xid, 2);
    if (_xac != null) {
      _xac.status = SpeedoXAContext.ENDED;
      if (xac == _xac) {
        xac = null;
      }
    } // else the XAcontext has been committed or rolled back before the end
  }

  /**
   * Used by JTA in order to verify that it has not already registered a
   * XAResource to manage this transaction context from this RM. If it is the
   * case, both XAResource are warned of this fact (endWithNoSameRM = false).
   * This means that these XAResource will be released at "end" time.
   * @param resource  The resource to be compared against this one wrt RM.
   */
  public boolean isSameRM(XAResource resource) throws XAException {
    boolean res = (resource instanceof SpeedoManagedConnection)
        && ((SpeedoManagedConnection) resource).mcf == mcf;
    if (Debug.ON && logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
      logger.log(BasicLevel.DEBUG, "isSameRM(" + resource + "): " + res);
    }
    return res;
  }

  // Management of transaction termination: prepare, commit, rollback

  /**
   * Prepares the underlying JdoTxContext (prepare phase of the 2PC).
   */
  public int prepare(Xid xid) throws XAException {
    if (Debug.ON && logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
      logger.log(BasicLevel.DEBUG, "prepare(" + xid + ")");
    }
    SpeedoXAContext _xac = getXAContext(xid, 1);
    if (Debug.ON && logger.isLoggable(BasicLevel.DEBUG)) {
      if (_xac.pm == null) {
        logger.log(BasicLevel.DEBUG, "prepare(" + xid
            + "): no PersistenceManager");
      } else {
        logger.log(BasicLevel.DEBUG, "prepare(" + xid
            + "): speedo Tx status="
            + _xac.pm.getSpeedoTransaction().getStatus());
      }
    }
    return XAResource.XA_OK;
  }

  /**
   * Unbind the PersistenceManager to the xid. The real commit is done by the
   * PersistenceManager registered as a Synchronization.
   */
  public void commit(Xid xid, boolean b) throws XAException {
    if (Debug.ON && logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
      logger.log(BasicLevel.DEBUG, "commit(" + xid + ", 1PC: " + b + ")");
    }
    SpeedoXAContext _xac = mcf.releaseXAContext(xid, true);
    if (xac == _xac) {
      this.xac = null;
    }
  }

  /**
   * Unbind the PersistenceManager to the xid. The real commit is done by the
   * PersistenceManager registered as a Synchronization.
   */
  public void rollback(Xid xid) throws XAException {
    if (Debug.ON && logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
      logger.log(BasicLevel.DEBUG, "rollback(" + xid + ")");
    }
    SpeedoXAContext _xac = mcf.releaseXAContext(xid, true);
    if (xac == _xac) {
      this.xac = null;
    }
  }

  public void forget(Xid xid) throws XAException {
    SpeedoXAContext _xac = mcf.releaseXAContext(xid, false);
    if (xac == _xac) {
      this.xac = null;
    }
  }

  /**
   * Gets the Xid of distributed transactions to be recovered from the Speedo
   * manager.
   */
  public Xid[] recover(int i) throws XAException {
    return new Xid[0];
  }

  public int getTransactionTimeout() throws XAException {
    return 0;
  }

  public boolean setTransactionTimeout(int i) throws XAException {
    return false;
  }
}
TOP

Related Classes of org.objectweb.speedo.jca.SpeedoManagedConnection

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.