XAResourceImpl.java

00001 /*
00002  * JOnAS: Java(TM) Open Application Server
00003  * Copyright (C) 1999 Bull S.A.
00004  * Contact: jonas-team@objectweb.org
00005  * 
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or any later version.
00010  * 
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  * 
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
00019  * USA
00020  *
00021  * --------------------------------------------------------------------------
00022  * $Id: XAResourceImpl.java,v 1.13 2004/04/28 15:31:21 durieuxp Exp $
00023  * --------------------------------------------------------------------------
00024  */
00025 
00026 
00027 package org.objectweb.jonas.jdbc_xa;
00028 
00029 import java.sql.Connection;
00030 import java.sql.SQLException;
00031 import javax.transaction.xa.*;
00032 import org.objectweb.jonas.common.Log;
00033 import org.objectweb.util.monolog.api.Logger;
00034 import org.objectweb.util.monolog.api.BasicLevel;
00035 
00049 public class XAResourceImpl implements XAResource {
00050 
00051     private static Logger logger = null;
00052 
00053     private Connection actConn = null;
00054     private XAConnectionImpl xac = null;
00055     private int timeout;
00056     private Xid currXid = null;
00057     private boolean xaStarted = false;
00058     private String rmid = null;
00059 
00060     // -----------------------------------------------------------------
00061     // Constructors
00062     // -----------------------------------------------------------------
00063 
00070     public XAResourceImpl(XAConnectionImpl xac, Connection actual, XADataSourceImpl ds) {
00071         this.xac = xac;
00072         this.actConn = actual;
00073         this.rmid = ds.getDataSourceName();
00074         logger = Log.getLogger(Log.JONAS_JDBCXA_PREFIX);
00075         logger.log(BasicLevel.DEBUG, "new object for " + this);
00076     }
00077 
00078     // -----------------------------------------------------------------
00079     // XAResource implementation
00080     // -----------------------------------------------------------------
00081 
00088     public synchronized void commit(Xid xid, boolean onePhase) throws XAException {
00089 
00090         logger.log(BasicLevel.DEBUG, "XA-COMMIT for " + this);
00091         logger.log(BasicLevel.DEBUG, "Xid = " + xid);
00092 
00093         // Make sure that we do not mix transactions
00094         // Since start and end are not sent to database, we must check here
00095         // the xids.
00096         if (currXid != null && !currXid.equals(xid)) {
00097             logger.log(BasicLevel.DEBUG, "mixed xids: " + xid + " != " + currXid);
00098             XAException ex = new XAException("cannot mix transactions");
00099             throw(ex);
00100         }
00101         currXid = null;         // just for cleaning
00102         if (xaStarted) {
00103             // Unbalance start/end. Probably a close is missing.
00104             // We decide to unset xa_start here to avoid a further error, but
00105             // I'm not sure it's a good idea.
00106             logger.log(BasicLevel.WARN, "XA START without XA END");
00107             
00108             xaStarted = false;
00109         }
00110 
00111         // Commit the transaction
00112         try {
00113             actConn.commit();
00114         } catch (SQLException e) {
00115             logger.log(BasicLevel.ERROR, "Cannot commit transaction:" + e);
00116             xac.notifyError(e);
00117             throw(new XAException("Error on commit"));
00118         }
00119     }
00120 
00127     public synchronized void end(Xid xid, int flags) throws XAException {
00128 
00129         logger.log(BasicLevel.DEBUG, "XA-END for " + this);
00130         logger.log(BasicLevel.DEBUG, "Xid = " + xid);
00131 
00132         // Check that we got a start on this Xid first.
00133         if (currXid == null || !currXid.equals(xid)) {
00134             logger.log(BasicLevel.WARN, "END without START or mixed xids: " + xid + " != " + currXid);
00135             XAException ex = new XAException(XAException.XA_RBPROTO);
00136             throw(ex);
00137         }
00138         xaStarted = false;
00139     }
00140 
00147     public synchronized void forget(Xid xid) throws XAException {
00148 
00149         // not implemented. XXX
00150         logger.log(BasicLevel.DEBUG, "XA-FORGET for " + this);
00151         logger.log(BasicLevel.DEBUG, "Xid = " + xid);
00152         currXid = null;
00153     }
00154 
00161     public synchronized int getTransactionTimeout() throws XAException {
00162         logger.log(BasicLevel.DEBUG, "getTransactionTimeout for " + this);
00163         return timeout;
00164     }
00165 
00173     public boolean isSameRM(XAResource xares) throws XAException {
00174 
00175 
00176         // In this pseudo-driver, we must return true only if
00177         // both objects refer to the same XAResource, and not
00178         // the same Resource Manager, because actually, we must
00179         // send commit/rollback on each XAResource involved in
00180         // the transaction.
00181         if (xares.equals(this)) {
00182             logger.log(BasicLevel.DEBUG, "isSameRM = true " + this);
00183             return true;
00184         }
00185         logger.log(BasicLevel.DEBUG, "isSameRM = false " + this);
00186         return false;
00187     }
00188 
00189 
00196     public synchronized int prepare(Xid xid) throws XAException {
00197 
00198         logger.log(BasicLevel.DEBUG, "XA-PREPARE for " + this);
00199         logger.log(BasicLevel.DEBUG, "Xid = " + xid);
00200         // No 2PC on standard JDBC drivers
00201         return XA_OK;
00202     }
00203 
00210     public synchronized Xid[] recover(int flag) throws XAException {
00211 
00212         logger.log(BasicLevel.DEBUG, "XA-RECOVER for " + this);
00213         // Not implemented
00214         return null;
00215     }
00216     
00223     public synchronized void rollback(Xid xid) throws XAException {
00224 
00225         logger.log(BasicLevel.DEBUG, "XA-ROLLBACK for " + this);
00226         logger.log(BasicLevel.DEBUG, "Xid = " + xid);
00227 
00228         // Make sure that we do not mix transactions
00229         // Since start and end are not sent to database, we must check here
00230         // the xids.
00231         if (currXid != null && !currXid.equals(xid)) {
00232             logger.log(BasicLevel.DEBUG, "mixed xids: " + xid + " != " + currXid);
00233             XAException ex = new XAException("Cannot mix transactions");
00234             throw(ex);
00235         }
00236         currXid = null;         // just for cleaning
00237         if (xaStarted) {
00238             // Unbalance start/end. Probably a close is missing.
00239             // We decide to unset xa_start here to avoid a further error, but
00240             // I'm not sure it's a good idea.
00241             logger.log(BasicLevel.WARN, "XA START without XA END");
00242             xaStarted = false;
00243         }
00244 
00245         // Make sure that we are not in AutoCommit mode
00246         try {
00247             if (actConn.getAutoCommit() == true) {
00248                 logger.log(BasicLevel.ERROR, "Rollback called on XAResource with AutoCommit set");
00249                 throw (new XAException(XAException.XA_HEURCOM));
00250             }
00251         } catch (SQLException e) {
00252             logger.log(BasicLevel.ERROR, "Cannot getAutoCommit:" + e);
00253             xac.notifyError(e);
00254             throw(new XAException("Error on getAutoCommit"));
00255         }
00256         
00257         // Rollback the transaction
00258         try {
00259             actConn.rollback();
00260         } catch (SQLException e) {
00261             logger.log(BasicLevel.ERROR, "Cannot rollback transaction:" + e);
00262             xac.notifyError(e);
00263             throw(new XAException("Error on rollback"));
00264         }
00265     }
00266 
00274     public synchronized boolean setTransactionTimeout(int seconds) throws XAException {
00275 
00276         logger.log(BasicLevel.DEBUG, "setTransactionTimeout " + this);
00277         timeout = seconds;
00278         return true;
00279     }
00280 
00286     public synchronized void start(Xid xid, int flags) throws XAException {
00287 
00288         logger.log(BasicLevel.DEBUG, "XA-START for " + this);
00289         logger.log(BasicLevel.DEBUG, "Xid = " + xid);
00290         if (xaStarted) {
00291             logger.log(BasicLevel.DEBUG, "mixed xids: " + xid + " != " + currXid);
00292             XAException ex = new XAException("XA START: mixed transactions");
00293             throw ex;
00294         }
00295         currXid = xid;
00296         xaStarted = true;
00297     }
00298 
00299     // ---------------------------------------------------------------------
00300     // Other methods
00301     // ---------------------------------------------------------------------
00302 
00303     /*
00304      * get the RMID
00305      * @return the rmid.
00306      */
00307     public String getRMID() {
00308         return rmid;
00309     }
00310 }

Generated on Tue Feb 15 15:05:16 2005 for JOnAS by  doxygen 1.3.9.1