FileDocCategorySizeDatePackage
OracleXAResource.javaAPI DocGlassfish v2 API9385Fri May 04 22:35:58 BST 2007com.sun.enterprise.transaction

OracleXAResource.java

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 * 
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License. You can obtain
 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.  If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [year]
 * [name of copyright owner]"
 * 
 * Contributor(s):
 * 
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

//Source File Name:   OracleXAResource.java

package com.sun.enterprise.transaction;

import java.sql.*;
import javax.transaction.xa.*;

import com.sun.enterprise.util.i18n.StringManager;
import java.util.logging.Logger;
import java.util.logging.Level;
import com.sun.logging.LogDomains;


/**
 * This implements workaround for Oracle XAResource. Oracle's 8.1.7 XAResource implementation
 * doesn't work fine while recovery. This class fires sql statements to achieve same.
 *
 * @author <a href="mailto:bala.dutt@sun.com">Bala Dutt</a>
 * @version 1.0
 */
public class OracleXAResource extends XAResourceWrapper
{

	// Sting Manager for Localization
    private static final StringManager sm = StringManager.getManager(OracleXAResource.class);
    private static final Logger _logger = LogDomains.getLogger(LogDomains.JTA_LOGGER);

	
  /**
   * Recovers list of xids in transaction table. Recover on oracle ignores flags sent to it, this method
   * takes care of flags in addition to calling recoverList for xid list.
   *
   * @param flag an <code>int</code> value
   * @return a <code>Xid[]</code> value
   * @exception XAException if an error occurs
   */
    public Xid[] recover(int flag) throws XAException {
        if(flag==XAResource.TMNOFLAGS)
            return null;
	return recoverList(flag);
    }
  /**
   * Fires a select statement so that transaction xids are updated and retrieve the xid list. Oracle
   * doesn't update the xid's for sometime. After this update, recover of real oracle xa resource is
   * is used get xid list.
   *
   * @return a <code>Xid[]</code> value
   * @exception XAException if an error occurs
   */
  private Xid [] recoverList(int flag) throws XAException{
        Statement stmt = null;
        ResultSet resultset = null;
        Connection con = null;
        try{
            con=(Connection)m_xacon.getConnection(subject,null);
            if(null == con)
                // throw new XAException("Oracle XA Resource wrapper : connection could not be got");
                throw new XAException(sm.getString("transaction.oracle_xa_wrapper_connection_failed"));
            stmt = con.createStatement();
            resultset = stmt.executeQuery(
                "select pending.local_tran_id from SYS.PENDING_TRANS$ pending, SYS.DBA_2PC_NEIGHBORS");
            resultset.close();
            resultset = null;
            stmt.close();
            stmt=null;
            return m_xacon.getXAResource().recover(flag);
        }
        catch(SQLException sqlexception){
            //Trace.info("Failed to recover xid list");
            // throw new XAException("oracle XA Resource wrapper : "+sqlexception);
            throw new XAException(sm.getString("transaction.oracle_sqlexception_occurred",sqlexception));
        }
        catch(Exception e){
            throw new XAException(sm.getString("transaction.oracle_unknownexception_occurred",e));
            // throw new XAException("oracle XA Resource wrapper : "+e);
        }
        finally{
            if(null != resultset)
                try{
                    resultset.close();
                }
                catch(SQLException sqlexception1) { }
            if(null != stmt)
                try{
                    stmt.close();
                }
                catch(SQLException sqlexception2) { }
        }
    }
    public void commit(Xid xid, boolean flag) throws XAException{
        doRecovery(xid, true);
    }
    public void rollback(Xid xid) throws XAException{
        doRecovery(xid, false);
    }
  /**
   * Does actual recovery depending on boolean argument - true for commmit.
   *
   * @param xid a <code>Xid</code> value
   * @param isCommit a <code>boolean</code> value
   * @exception XAException if an error occurs
   */
  private void doRecovery(Xid xid, boolean isCommit) throws XAException{

        try {
            if (isCommit)
                m_xacon.getXAResource().commit(xid,true);
            else
                m_xacon.getXAResource().rollback(xid);
        } catch (XAException ex) {
            _logger.log(Level.FINEST," An XAException occurred while calling XAResource method " , ex);
        } catch (Exception ex) {
            _logger.log(Level.FINEST," An Exception occurred while calling XAResource method " , ex);
        }

        Statement stmt = null;
        ResultSet resultset = null;
        Connection con = null;
        try{
            con=(Connection)m_xacon.getConnection(subject,null);
            if(null == con)
                throw new XAException(sm.getString("transaction.oracle_xa_wrapper_connection_failed"));
                // throw new XAException("Oracle XA Resource wrapper : connection could not be got");
            stmt = con.createStatement();
            resultset = stmt.executeQuery(
                "select pending.local_tran_id from SYS.PENDING_TRANS$ pending, SYS.DBA_2PC_NEIGHBORS dba where pending.global_foreign_id = '"
                + toHexString(xid.getGlobalTransactionId()) +
                "' and pending.local_tran_id = dba.local_tran_id and dba.branch = '"
                + toHexString(xid.getBranchQualifier()) +
                "' and pending.state = 'prepared'");
            if(resultset.next()){
                String s = resultset.getString(1);
                resultset.close();
                resultset = null;
                stmt.executeUpdate((isCommit ? "commit force '" : "rollback force '") + s + "'");
                stmt.close();
                stmt=null;
            }
        }
        catch(SQLException sqlexception){
            //Trace.info("Failed to recover " + xid+" "+ sqlexception);
            _logger.log(Level.FINE," An SQLException during recovery " , sqlexception);
            throw new XAException(sm.getString("transaction.oracle_sqlexception_occurred",sqlexception));
            // throw new XAException("oracle XA Resource wrapper : "+sqlexception);
        }
        catch(Exception e){
            //Trace.info("Exception while RecoveryTestRI recover "+e);
            _logger.log(Level.FINE," An Exception during recovery " , e);
            throw new XAException(sm.getString("transaction.oracle_unknownexception_occurred",e));
            // throw new XAException("oracle XA Resource wrapper : "+e);
        }
        finally{
            if(null != resultset)
                try{
                    resultset.close();
                }
                catch(SQLException sqlexception1) { }
            if(null != stmt)
                try{
                    stmt.close();
                }
                catch(SQLException sqlexception2) { }
        }
    }
    private static final char HEX_DIGITS[] = {
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        'A', 'B', 'C', 'D', 'E', 'F'
    };
  /**
   * Converts Xids into string that can be used in sql statements for oracle.
   *
   * @param abyte0[] a <code>byte</code> value
   * @return a <code>String</code> value
   */
  private static String toHexString(byte abyte0[]) {
        StringBuffer stringbuffer = new StringBuffer();
        if(null != abyte0 && 0 < abyte0.length) {
            for(int i = 0; i < abyte0.length; i++) {
                stringbuffer.append(HEX_DIGITS[(abyte0[i] & 0xf0) >> 4]);
                stringbuffer.append(HEX_DIGITS[abyte0[i] & 0xf]);
            }
            return stringbuffer.toString();
         } else {
            return "";
         }
    }
}