FileDocCategorySizeDatePackage
J2EETransactionManagerImpl.javaAPI DocGlassfish v2 API51387Tue Jul 24 22:42:38 BST 2007com.sun.enterprise.distributedtx

J2EETransactionManagerImpl

public class J2EETransactionManagerImpl extends Object implements J2EETransactionManager
This class implements the Transaction Manager for the J2EE RI. It provides implementations of the JTA TransactionManager interface, which delegates actual transaction work to JTS. It also implements the association between transactions, resources and components at various stages of the component lifecycle.
author
Tony Ng

Fields Summary
static Logger
_logger
private static final String
TX_TIMEOUT
private static final String
TX_OPT
private TransactionManager
tm
private boolean
multipleEnlistDelists
private static com.sun.enterprise.util.i18n.StringManager
sm
protected InvocationManager
invMgr
protected PoolManager
poolmgr
protected int
transactionTimeout
protected ThreadLocal
txnTmout
protected boolean
useLAO
protected Hashtable
statusMap
protected Vector
activeTransactions
protected boolean
monitoringEnabled
protected static int[]
JTAStatus
protected static String[]
STATUS
protected int
m_transCommitted
protected int
m_transRolledback
protected int
m_transInFlight
private com.sun.appserv.util.cache.Cache
resourceTable
instance -> resource list mapping // START IASRI 4705808 TTT002 -- use List instead of Vector For EJB, a mapping of EnterpriseBean -> ArrayList For Servlets/JSPs, a mapping of -> ArrayList // END IASRI 4705808 TTT002
Constructors Summary
public J2EETransactionManagerImpl()

    // END IASRI 4705808 TTT001



      
		if (_logger.isLoggable(Level.FINE))
        	_logger.log(Level.FINE,"TM: Initializing distributed TM...");
        //tm = TransactionManagerImpl.getTransactionManagerImpl();
        if( Switch.getSwitch().getPoolManager() == null ) {
	    poolmgr = new PoolManagerImpl();
	    Switch.getSwitch().setPoolManager( poolmgr );
	} else {
            poolmgr = Switch.getSwitch().getPoolManager();
	}
        Switch.getSwitch().setPoolManager(poolmgr);

        ResourceInstaller installer = new ResourceInstaller();
        Switch.getSwitch().setResourceInstaller(installer);

	// START IASRI 4705808 TTT001 -- use BaseCache instead of Hashtable
        //int maxEntries = 16000; // FIXME: this maxEntry should be a config
        int maxEntries = 8192; // FIXME: this maxEntry should be a config
        float loadFactor = 0.75f; // FIXME: this loadFactor should be a config
        // for now, let's get it from system prop
        try {
            String mEnlistDelists 
                = System.getProperty("ALLOW_MULTIPLE_ENLISTS_DELISTS");
            if ("true".equals(mEnlistDelists)) {
                multipleEnlistDelists = true;
		if (_logger.isLoggable(Level.FINE))
        	    _logger.log(Level.FINE,"TM: multiple enlists, delists are enabled");
            }
	    String maxEntriesValue
		= System.getProperty("JTA_RESOURCE_TABLE_MAX_ENTRIES");
            if (maxEntriesValue != null) {
                int temp = Integer.parseInt(maxEntriesValue);
                if (temp > 0) {
                    maxEntries = temp;
                }
            }
	    String loadFactorValue
		= System.getProperty("JTA_RESOURCE_TABLE_DEFAULT_LOAD_FACTOR");
            if (loadFactorValue != null) {
                float f = Float.parseFloat(loadFactorValue);
                if (f > 0) {
                     loadFactor = f;
                }
            }
        } catch (Exception ex) {
            // ignore
        }
	Properties cacheProps = null;

        resourceTable = new BaseCache();
        ((BaseCache)resourceTable).init(maxEntries, loadFactor, cacheProps); 
	// END IASRI 4705808 TTT001

        invMgr = Switch.getSwitch().getInvocationManager();
	if (invMgr == null) { // Stand Alone Clients
		invMgr = new InvocationManagerImpl();
		// Switch.getSwitch().setInvocationManager(invMgr);
		// createJTSTransactionManager();
	}
        // START IASRI 4662745

        ServerContext sCtx = ApplicationServer.getServerContext();
        // running on the server side
        if (sCtx != null) {
            ConfigContext ctx = sCtx.getConfigContext();
            TransactionService txnService = null;
            try {
                txnService = ServerBeansFactory.getTransactionServiceBean(ctx);
                transactionTimeout = Integer.parseInt(txnService.getTimeoutInSeconds());
                ElementProperty[] eprops = txnService.getElementProperty();
                for (int index = 0; index < eprops.length; index++) {
                    if ("use-last-agent-optimization".equals(eprops[index].getName())) {
                        if ("false".equals(eprops[index].getValue())) {
                            useLAO = false;
		            if (_logger.isLoggable(Level.FINE))
        	                _logger.log(Level.FINE,"TM: LAO is disabled");
                        }
                    }
                }
            } catch(ConfigException e) {
                throw new RuntimeException(sm.getString("enterprise_distributedtx.config_excep",e));
            } catch (NumberFormatException ex) {
            }
        }
        // ENF OF BUG 4665539
		if (_logger.isLoggable(Level.FINE))
        	_logger.log(Level.FINE,"TM: Tx Timeout = " + transactionTimeout);

        // monitor and administration
	activeTransactions = new Vector();
        statusMap = new Hashtable();
        for (int i=0; i<JTAStatus.length; i++) {
            statusMap.put(new Integer(JTAStatus[i]),STATUS[i]);
        }
        // END IASRI 4662745

	// START IASRI 4705808 TTT004 -- monitor resource table stats
        try {
	    String doStats
		= System.getProperty("MONITOR_JTA_RESOURCE_TABLE_STATISTICS");
            if (Boolean.getBoolean(doStats)) {
		registerStatisticMonitorTask();
	    }
        } catch (Exception ex) {
            // ignore
        }
	// END IASRI 4705808 TTT004
    
Methods Summary
public voidbegin(int timeout)


		//START RI PERFIMPROVEMENT
		/***
		// Just to tell that, use this timeout for the transaction, there is no need
		// to synchronized and thus serrialize the activity. Now this is avoided by
		// the introduction of two new methods begin(timeout) in TransactionManagerImpl
		// and CurrentImpl

        // ensure no other thread change the timeout
		synchronized(tm) {
            tm.setTransactionTimeout(timeout);
            tm.begin();
            tm.setTransactionTimeout(0);
            // START IASRI 4662745
            if (monitoringEnabled) {
				Transaction tran = tm.getTransaction();
                activeTransactions.addElement(tran);
                m_transInFlight++;
            }
            // END IASRI 4662745
	 	}
		**/

        ((TransactionManagerImpl)tm).begin(timeout);
        // START IASRI 4662745
        if (monitoringEnabled) {
			Transaction tran = tm.getTransaction();
            activeTransactions.addElement(tran);
            m_transInFlight++;
        }
        // END IASRI 4662745
		//END RI PERFIMPROVEMENT
    
public voidbegin()
/ /** Create a new transaction and associate it with the current thread.

exception
NotSupportedException Thrown if the thread is already associated with a transaction.
exception
SystemException Thrown if the transaction manager encounters an unexpected error condition

		if (_logger.isLoggable(Level.FINE))
        	_logger.log(Level.FINE,"TM: begin");

		//START RI PERFIMPROVEMENT
		/***
		// Just to tell that, use this timeout for the transaction, there is no need
		// to synchronize and thus serrialize the activity. Now this is avoided by
		// the introduction of two new methods begin(timeout) in TransactionManagerImpl
		// and CurrentImpl

        synchronized(tm) {
            // ensure no other thread change the timeout
            tm.setTransactionTimeout(transactionTimeout);
            tm.begin();
            tm.setTransactionTimeout(0);

            // START IASRI 4662745
            if (monitoringEnabled) {
                Transaction tran = tm.getTransaction();
                activeTransactions.addElement(tran);
                m_transInFlight++;
            }
            // END IASRI 4662745
	 	}
		***/
        ((TransactionManagerImpl)tm).begin(getEffectiveTimeout());

        // START IASRI 4662745
        if (monitoringEnabled) {
        	Transaction tran = tm.getTransaction();
        	activeTransactions.addElement(tran);
        	m_transInFlight++;
       	}
       // END IASRI 4662745
       // END IASRI PERFIMPROVEMENT
    
public voidcheckTransactionExport(boolean isLocal)

 
public voidcheckTransactionImport()

 
public voidcleanTxnTimeout()

        txnTmout.set(null);
    
public voidcommit()
Complete the transaction associated with the current thread. When this method completes, the thread becomes associated with no transaction.

exception
RollbackException Thrown to indicate that the transaction has been rolled back rather than committed.
exception
HeuristicMixedException Thrown to indicate that a heuristic decision was made and that some relevant updates have been committed while others have been rolled back.
exception
HeuristicRollbackException Thrown to indicate that a heuristic decision was made and that some relevant updates have been rolled back.
exception
SecurityException Thrown to indicate that the thread is not allowed to commit the transaction.
exception
IllegalStateException Thrown if the current thread is not associated with a transaction.
exception
SystemException Thrown if the transaction manager encounters an unexpected error condition

		if (_logger.isLoggable(Level.FINE))
        	_logger.log(Level.FINE,"TM: commit");
        validateTransactionManager();
        Object obj = null;
        if(monitoringEnabled){
            obj = tm.getTransaction();
        }
        if (invMgr.isInvocationStackEmpty()) {
            try{
                tm.commit();
                if (monitoringEnabled){
                    monitorTxCompleted(obj, true);
                }
            }catch(RollbackException e){
                if (monitoringEnabled){
                    monitorTxCompleted(obj, false);
                }
                throw e;
            }catch(HeuristicRollbackException e){
                if (monitoringEnabled){
                    monitorTxCompleted(obj, false);
                }
                throw e;
            }catch(HeuristicMixedException e){
                if (monitoringEnabled){
                    monitorTxCompleted(obj, true);
                }
                throw e;
            }
        } else {
            ComponentInvocation curr = null;
            try {
                curr = invMgr.getCurrentInvocation();
                if (curr != null)
                    curr.setTransactionCompeting(true);
                tm.commit();
                if (monitoringEnabled){
                    monitorTxCompleted(obj, true);
                }
            } catch (InvocationException ex) {
                assert false;
            }catch(RollbackException e){
                if (monitoringEnabled){
                    monitorTxCompleted(obj, false);
                }
                throw e;
            }catch(HeuristicRollbackException e){
                if (monitoringEnabled){
                    monitorTxCompleted(obj, false);
                }
                throw e;
            }catch(HeuristicMixedException e){
                if (monitoringEnabled){
                    monitorTxCompleted(obj, true);
                }
                throw e;
            } finally {
                if (curr != null) {
                    curr.setTransactionCompeting(false);
                }
            }
        }
        
    
public voidcomponentDestroyed(java.lang.Object instance)

		if (_logger.isLoggable(Level.FINE))
        	_logger.log(Level.FINE,"TM: componentDestroyed" + instance);
	// START IASRI 4705808 TTT002 -- use List instead of Vector
        // Mod: remove the bad behavior of adding an empty list then remove it
        List l = (List)resourceTable.get(getInstanceKey(instance));
        if (l != null && l.size() > 0) {
			//START IASRI 4720840
            resourceTable.remove(getInstanceKey(instance));
			//END IASRI 4720840
            Iterator it = l.iterator();
            while (it.hasNext()) {
                ResourceHandle h = (ResourceHandle) it.next();
                try {
                    h.getResourceAllocator().closeUserConnection(h);
                } catch (PoolingException ex) {
                    /** IASRI 4664284
                    if (debug) ex.printStackTrace();
                    **/
                    // START OF IASRI 4664284
					if (_logger.isLoggable(Level.FINE))
                    	_logger.log(Level.WARNING,"enterprise_distributedtx.pooling_excep", ex);
                    // END OF IASRI 4664284
                }
            }
            l.clear();
			//START IASRI 4720840
            // resourceTable.remove(getInstanceKey(instance));
			//END IASRI 4720840
        }
	// END IASRI 4705808 TTT002
    
public static voidcreateJTSTransactionManager()

        // It is assumed that transaction manager is already created
        // and is available in switch.
        J2EETransactionManagerImpl impl = (J2EETransactionManagerImpl) 
        Switch.getSwitch().getTransactionManager();
	if (impl.tm != null)
		return;

        impl.tm = TransactionManagerImpl.getTransactionManagerImpl();
       
    
public static J2EETransactionManagercreateTransactionManager()

        ServerConfiguration sc = ServerConfiguration.getConfiguration();
	String txOpt = sc.getProperty(TX_OPT);

		if (_logger.isLoggable(Level.FINE))
	    	_logger.log(Level.FINE,"TM: Tx Opt = " + txOpt);

	J2EETransactionManager j2eeTM;
	if ( txOpt != null && txOpt.equals("false") )
	    j2eeTM = new J2EETransactionManagerImpl();
	else {
	    j2eeTM = new J2EETransactionManagerOpt();
            J2EETransaction.j2eeTM = (J2EETransactionManagerOpt)j2eeTM;
        }

	return j2eeTM;
    
public voiddelistComponentResources(boolean suspend)

		if (_logger.isLoggable(Level.FINE))
        	_logger.log(Level.FINE,"TM: delistComponentResources");
        ComponentInvocation inv = invMgr.getCurrentInvocation();
        // BEGIN IASRI# 4646060
        if (inv == null) {
            return;
        }
        // END IASRI# 4646060
        try {
            delistComponentResources(inv, suspend);
        } catch (InvocationException ex) {
            /** IASRI 4664284
            ex.printStackTrace();
            ex.printStackTrace(Log.err);
            **/
            // START OF IASRI 4664284
            _logger.log(Level.SEVERE,"enterprise_distributedtx.excep_in_delist",ex);
            // END OF IASRI 4664284

            throw new RemoteException("", ex.getNestedException());
        } catch (Exception ex) {
            /** IASRI 4664284
            ex.printStackTrace();
            ex.printStackTrace(Log.err);
            **/
            // START OF IASRI 4664284
            _logger.log(Level.SEVERE,"enterprise_distributedtx.excep_in_delist",ex);
            // END OF IASRI 4664284
            throw new RemoteException("", ex);
        }
    
private voiddelistComponentResources(ComponentInvocation inv, boolean suspend)


        try {
            Transaction tran = inv.getTransaction();
            if (isTransactionActive(tran)) {
				/** IASRI 4658504
                Vector v = getResourceList(inv.getInstance());
                Enumeration e = v.elements();
                int flag = XAResource.TMSUCCESS;
                if (suspend) flag = XAResource.TMSUSPEND;
                while (e.hasMoreElements()) {
                    ResourceHandle h = (ResourceHandle) e.nextElement();
                    try {
                        delistResource(tran, h, flag);
                    } catch (IllegalStateException ex) {
                        // ignore error due to tx time out
                    } catch (Exception ex) {
                        handleResourceError(h, ex, tran, inv);
                    }
                }
                **IASRI 4658504 **/ 

                List l = getExistingResourceList(inv.getInstance(), inv);
                if (l == null || l.size() == 0)
                    return;
                Iterator it = l.iterator();
		// END IASRI 4705808 TTT002
		int flag = XAResource.TMSUCCESS;
		if(suspend)flag = XAResource.TMSUSPEND;
		while(it.hasNext()){
		    ResourceHandle h = (ResourceHandle)it.next();
		    try{
                        if ( h.isEnlisted() ) {
			    delistResource(tran,h,flag);
                        }
		    } catch (IllegalStateException ex) {
			// ignore error due to tx time out
		    }catch(Exception ex){
			it.remove();
			handleResourceError(h,ex,tran,inv);
		    }  
		}
		//END OF IASRI 4658504
            }
        } catch (Exception ex) {
            /** IASRI 4664284
            ex.printStackTrace();
            ex.printStackTrace(Log.err);
            **/
            // START OF IASRI 4664284
            _logger.log(Level.SEVERE,"enterprise_distributedtx.excep_in_delist",ex);
            // END OF IASRI 4664284
            //throw new InvocationException(ex);
        }
    
public booleandelistResource(javax.transaction.Transaction tran, ResourceHandle h, int flag)

param
suspend true if the transaction association should be suspended rather than ended.

		if (_logger.isLoggable(Level.FINE))
        	_logger.log(Level.FINE,"TM: delistResource");
        if (!h.isShareable() || multipleEnlistDelists) {
            if (h.isTransactional() && h.isEnlisted()) {
                return tran.delistResource(h.getXAResource(), flag);
            } else {
                return true;
            }
        }
        return true;
    
public voidejbDestroyed(com.sun.ejb.ComponentContext context)

	if (_logger.isLoggable(Level.FINE))
            _logger.log(Level.FINE, " ejbDestroyed: " + context);
        List l = (List)context.getResourceList();
        if (l != null && l.size() > 0) {
            Iterator it = l.iterator();
            while (it.hasNext()) {
                ResourceHandle h = (ResourceHandle) it.next();
                try {
                    h.getResourceAllocator().closeUserConnection(h);
                } catch (PoolingException ex) {
		    if (_logger.isLoggable(Level.FINE))
                        _logger.log(Level.WARNING,"enterprise_distributedtx.pooling_excep", ex);
                }
            }
            l.clear();
        }
    
private voidenlistComponentResources(ComponentInvocation inv)


        // Exception ex1 = null;
        try {
            Transaction tran = inv.getTransaction();
            if (isTransactionActive(tran)) {
		/** IASRI 4658504
                Vector v = getResourceList(inv.getInstance());
                Enumeration e = v.elements();
                while (e.hasMoreElements()) {
                    ResourceHandle h = (ResourceHandle) e.nextElement();
                    try {
                        enlistResource(tran, h);
                    } catch (Exception ex) {
                        handleResourceError(h, ex, tran, inv);
                    }
                }
		** IASRI 4658504    **/
		
                List l = getExistingResourceList(inv.getInstance(), inv);
                if (l == null || l.size() == 0) return;
                Iterator it = l.iterator();
		// END IASRI 4705808 TTT002
		while(it.hasNext()) {
		    ResourceHandle h = (ResourceHandle) it.next();
		    try{
			enlistResource(tran,h);
		    }catch(Exception ex){
                        // ex1 = ex;
			it.remove();
			handleResourceError(h,ex,tran,inv);
		    }
		}
		//END OF IASRI 4658504		
            }
        } catch (Exception ex) {
            /** IASRI 4664284
            ex.printStackTrace();
            ex.printStackTrace(Log.err);
            **/
            // START OF IASRI 4664284
            _logger.log(Level.SEVERE,"enterprise_distributedtx.excep_in_enlist",ex);
            // END OF IASRI 4664284
            //throw new InvocationException(ex);
        }
        /**
        if (ex1 != null) {
            InvocationException ivx = new InvocationException(ex1.getMessage());
            ivx.initCause(ex1);
            throw ivx;
        }
        **/
    
public voidenlistComponentResources()

		if (_logger.isLoggable(Level.FINE))
        	_logger.log(Level.FINE,"TM: enlistComponentResources");
        ComponentInvocation inv = invMgr.getCurrentInvocation();
        if (inv == null)
            return;
        try {
            Transaction tran = getTransaction();
            inv.setTransaction(tran);
            enlistComponentResources(inv);
        } catch (InvocationException ex) {
            /** IASRI 4664284
            ex.printStackTrace();
            ex.printStackTrace(Log.err);
            **/
            //START OF IASRI 4664284
            _logger.log(Level.SEVERE,"enterprise_distributedtx.excep_in_enlist" ,ex);
            //END OF IASRI 4664284
            
            throw new RemoteException(ex.getMessage(), ex.getNestedException());
        } catch (Exception ex) {
            /** IASRI 4664284
            ex.printStackTrace();
            ex.printStackTrace(Log.err);
            **/
            //START OF IASRI 4664284
            _logger.log(Level.SEVERE,"enterprise_distributedtx.excep_in_enlist" ,ex);
            //END OF IASRI 4664284
            throw new RemoteException(ex.getMessage(), ex);
        }
    
public booleanenlistLAOResource(javax.transaction.Transaction tran, ResourceHandle h)

		if (_logger.isLoggable(Level.FINE))
        	_logger.log(Level.FINE,"TM: enlistLAOResource");
        if (h.isTransactional()) {
            XAResource res = h.getXAResource();
            boolean result = tran.enlistResource(res);
            return result;
        } else {
            return true;
        }
    
public booleanenlistResource(javax.transaction.Transaction tran, ResourceHandle h)

		if (_logger.isLoggable(Level.FINE))
        	_logger.log(Level.FINE,"TM: enlistResource");
        if (h.isTransactional() && (!h.isEnlisted() || !h.isShareable() || multipleEnlistDelists)) {
            XAResource res = h.getXAResource();
            boolean result = tran.enlistResource(res);
            if (!h.isEnlisted())
                poolmgr.resourceEnlisted(tran, h);
            return result;
        } else {
            return true;
        }
    
public voidforceRollback(javax.transaction.Transaction tran)

        if (tran != null){
            tran.setRollbackOnly();
        }
    
public synchronized voidfreeze()

        if(com.sun.jts.CosTransactions.AdminUtil.isFrozenAll()){
            //multiple freezes will hang this thread, therefore just return
            return;
        }
        com.sun.jts.CosTransactions.AdminUtil.freezeAll();
    
public java.util.ArrayListgetActiveTransactions()

	ArrayList tranBeans = new ArrayList();
        Vector active = (Vector)activeTransactions.clone(); // get the clone of the active transactions
        for(int i=0;i<active.size();i++){
            try{
                Transaction tran = (Transaction)active.elementAt(i);
                String id="unknown";
                long startTime = 0;
                long elapsedTime = 0;
                String status = "unknown";
                String componentName = "unknown";
                ArrayList<String> resourceNames = null;
                if(tran instanceof com.sun.jts.jta.TransactionImpl){
                    id=((com.sun.jts.jta.TransactionImpl)tran).getTransactionId();
                    startTime = ((com.sun.jts.jta.TransactionImpl)tran).getStartTime();

                }else if(tran instanceof J2EETransaction){
                    J2EETransaction tran1 = (J2EETransaction)tran;
                    id=tran1.getTransactionId();
                    startTime = tran1.getStartTime();
                    componentName = tran1.getComponentName();
                    resourceNames = tran1.getResourceNames();
                }
                elapsedTime = System.currentTimeMillis()-startTime;
                status = (String)statusMap.get(new Integer(tran.getStatus()));
                TransactionAdminBean tBean = new TransactionAdminBean(tran,id,status,elapsedTime,
                                             componentName, resourceNames);
                tranBeans.add(tBean);
            }catch(Exception ex){
                //LOG !!!
            }
        }
	return tranBeans;
    
intgetEffectiveTimeout()

        Integer tmout = txnTmout.get();
        if (tmout ==  null) {
            return transactionTimeout;
        }
        else {
            return tmout;
        }
    
public java.util.ListgetExistingResourceList(java.lang.Object instance)

        if (instance == null)
            return null;
        Object key = getInstanceKey(instance);
        if (key == null)
            return null;
        return (List) resourceTable.get(key);
    
public java.util.ListgetExistingResourceList(java.lang.Object instance, ComponentInvocation inv)

       if (inv == null)
           return null;
        List l = null;
        if (inv.getInvocationType() == ComponentInvocation.EJB_INVOCATION) {
            ComponentContext ctx = inv.context;
            if (ctx != null)
                l = ctx.getResourceList();
            return l;
        }
        else {
            Object key = getInstanceKey(instance);
            if (key == null)
                return null;
            return (List) resourceTable.get(key);
       }
    
private java.lang.ObjectgetInstanceKey(java.lang.Object instance)

        Object key = null;
        if (instance instanceof Servlet ||
            instance instanceof Filter) {
            // Servlet or Filter
            if (instance instanceof SingleThreadModel) {
                key = instance;
            } else {
                Vector pair = new Vector(2);
                pair.addElement(instance);
                pair.addElement(Thread.currentThread());
                key = pair;
            }
        } else {
            key = instance;
        }
        return key;
    
public intgetNumberOfActiveTransactions()

        return m_transInFlight;
    
public intgetNumberOfTransactionsCommitted()

        return m_transCommitted;
    
public intgetNumberOfTransactionsRolledBack()

        return m_transRolledback;
    
public java.util.ListgetResourceList(java.lang.Object instance)

        Object key = getInstanceKey(instance);
        List l = (List) resourceTable.get(key);
        if (l == null) {
            l = new ArrayList(); //FIXME: use an optimum size?
            resourceTable.put(key, l);
        }
        return l;
    
public java.util.ListgetResourceList(java.lang.Object instance, ComponentInvocation inv)

        if (inv == null)
            return new ArrayList(0);
        List l = null;
        if (inv.getInvocationType() == ComponentInvocation.EJB_INVOCATION) {
            ComponentContext ctx = inv.context;
            if (ctx != null)
                l = ctx.getResourceList();
            else {
	        l = new ArrayList(0);
            }
        }
        else {
            Object key = getInstanceKey(instance);
            if (key == null)
                return new ArrayList(0);
            l = (List) resourceTable.get(key);
            if (l == null) {
                l = new ArrayList(); //FIXME: use an optimum size?
                resourceTable.put(key, l);
            }
        }
        return l;
    
public intgetStatus()
Obtain the status of the transaction associated with the current thread.

return
The transaction status. If no transaction is associated with the current thread, this method returns the Status.NoTransaction value.
exception
SystemException Thrown if the transaction manager encounters an unexpected error condition

        if (tm != null) {
            return tm.getStatus();
        } else {
            return javax.transaction.Status.STATUS_NO_TRANSACTION;
        }
    
public javax.transaction.TransactiongetTransaction()
Get the transaction object that represents the transaction context of the calling thread

exception
SystemException Thrown if the transaction manager encounters an unexpected error condition

        if (tm == null) {
            return null;
        } else {
            return tm.getTransaction();
        }
    
public javax.resource.spi.XATerminatorgetXATerminator()
Provides a handle to a XATerminator instance. The XATerminator instance could be used by a resource adapter to flow-in transaction completion and crash recovery calls from an EIS.

This is used by importing transactions via the Connector contract.

return
a XATerminator instance.

        return ((TransactionManagerImpl) tm).getXATerminator();
    
private voidhandleResourceError(ResourceHandle h, java.lang.Exception ex, javax.transaction.Transaction tran, ComponentInvocation inv)


		if (_logger.isLoggable(Level.FINE)) {
            if (h.isTransactional()) {
                _logger.log(Level.FINE,"TM: HandleResourceError " +
                                   h.getXAResource() +
                                   "," + ex);
            }
        }
		/** IASRI 4658504
        // unregister resource
        Object instance = inv.getInstance();
        if (instance == null) return;
        Vector v = getResourceList(instance);
        v.removeElement(h);

		** IASRI 4658504 **/
        try {
            if (tran != null && h.isTransactional() && h.isEnlisted() ) {
                tran.delistResource(h.getXAResource(), XAResource.TMSUCCESS);
            }
        } catch (Exception ex2) {
            // ignore
        }  


        if (ex instanceof RollbackException) {
            // transaction marked as rollback
            return;
        } else if (ex instanceof IllegalStateException) {
            // transaction aborted by time out
            // close resource
            try {
                h.getResourceAllocator().closeUserConnection(h);
            } catch (Exception ex2) {
                //Log.err.println(ex2);
            }
        } else {
            // destroy resource. RM Error.
            try {
                h.getResourceAllocator().destroyResource(h);
            } catch (Exception ex2) {
                //Log.err.println(ex2);
            }
        }
    
public synchronized booleanisFrozen()

        return com.sun.jts.CosTransactions.AdminUtil.isFrozenAll();
    
public booleanisNullTransaction()
/ /** Return true if a "null transaction context" was received from the client. See EJB2.0 spec section 19.6.2.1. A null tx context has no Coordinator objref. It indicates that the client had an active tx but the client container did not support tx interop.

	try {
	    return com.sun.jts.pi.InterceptorImpl.isTxCtxtNull();
	} catch ( Exception ex ) {
	    // sometimes JTS throws an EmptyStackException if isTxCtxtNull
	    // is called outside of any CORBA invocation.
	    return false;
	}
    
public booleanisTimedOut()

		com.sun.enterprise.admin.event.AdminEventListenerRegistry.addEventListener(JTSEvent.eventType, new JTSConfigChangeEventListener()); 
    
        return false;
    
private booleanisTransactionActive(javax.transaction.Transaction tran)

        return (tran != null);
    
protected voidmonitorTxCompleted(java.lang.Object tran, boolean committed)

        if(tran==null || !activeTransactions.remove(tran)){
            // WARN !!!
            return;
        }
        if(committed){
            m_transCommitted++;
        }else{
            m_transRolledback++;
        }
        m_transInFlight--;
    
public voidpostInvoke(ComponentInvocation curr, ComponentInvocation prev)

        
        if ( curr != null && curr.getTransaction() != null )
            delistComponentResources(curr, false);  // delist with TMSUCCESS
        if ( prev != null && prev.getTransaction() != null &&
        prev.isTransactionCompleting() == false) {
            // do not worry about re-enlisting previous invocation resources
            // if transaction is being completed
            enlistComponentResources(prev);
        }
        
    
public voidpreInvoke(ComponentInvocation prev)

        if ( prev != null && prev.getTransaction() != null &&
        prev.isTransactionCompleting() == false) {
            // do not worry about delisting previous invocation resources
            // if transaction is being completed
            delistComponentResources(prev, true);  // delist with TMSUSPEND
        }
        
    
private static voidprint(java.lang.String s)

        /** IASRI 4664284
        System.err.println(s);
        **/
        // START OF IASRI 4664284
        _logger.log(Level.FINE,s);
        // END OF IASRI 4664284

    
public voidrecover(javax.transaction.xa.XAResource[] resourceList)

        int size = resourceList.length;
        Vector v = new Vector();
        for (int i=0; i<size; i++) {
            v.addElement(resourceList[i]);
        }
        ((TransactionManagerImpl)tm).recover(v.elements());
    
public voidrecreate(javax.transaction.xa.Xid xid, long timeout)
Recreate a transaction based on the Xid. This call causes the calling thread to be associated with the specified transaction.

This is used by importing transactions via the Connector contract.

param
xid the Xid object representing a transaction.

        ((TransactionManagerImpl) tm).recreate(xid, timeout);
    
public voidregisterComponentResource(ResourceHandle h)

        ComponentInvocation inv = invMgr.getCurrentInvocation();
        if (inv != null) {
            Object instance = inv.getInstance();
            if (instance == null) return;
            h.setComponentInstance(instance);
            List l = getResourceList(instance, inv);
            l.add(h);
        }
    
private voidregisterStatisticMonitorTask()

        TimerTask task = new StatisticMonitorTask();
        Timer timer = Switch.getSwitch().getTimer();
        // for now, get monitoring interval from system prop
	int statInterval = 2 * 60 * 1000;
        try {
	    String interval
		= System.getProperty("MONITOR_JTA_RESOURCE_TABLE_SECONDS");
            int temp = Integer.parseInt(interval);
            if (temp > 0) {
                statInterval = temp;
            }
        } catch (Exception ex) {
            // ignore
        }

        timer.scheduleAtFixedRate(task, 0, statInterval);
    
public voidregisterSynchronization(javax.transaction.Synchronization sync)

		if (_logger.isLoggable(Level.FINE))
        	_logger.log(Level.FINE,"TM: registerSynchronization");
        try {
            Transaction tran = getTransaction();
            if (tran != null) {
                tran.registerSynchronization(sync);
            }
        } catch (RollbackException ex) {
            /** IASRI 4664284
            ex.printStackTrace();
            ex.printStackTrace(Log.err);
            **/
            //START OF IASRI 4664284
            _logger.log(Level.SEVERE,"enterprise_distributedtx.rollbackexcep_in_regsynch",ex);
            //END OF IASRI 4664284

            throw new IllegalStateException();
        }
    
public voidrelease(javax.transaction.xa.Xid xid)
Release a transaction. This call causes the calling thread to be dissociated from the specified transaction.

This is used by importing transactions via the Connector contract.

param
xid the Xid object representing a transaction.

        ((TransactionManagerImpl) tm).release(xid);
    
public voidresume(javax.transaction.Transaction tobj)
Resume the transaction context association of the calling thread with the transaction represented by the supplied Transaction object. When this method returns, the calling thread is associated with the transaction context specified.

exception
InvalidTransactionException Thrown if the parameter transaction object contains an invalid transaction
exception
IllegalStateException Thrown if the thread is already associated with another transaction.
exception
SystemException Thrown if the transaction manager encounters an unexpected error condition

		if (_logger.isLoggable(Level.FINE))
        	_logger.log(Level.FINE,"TM: resume");
        tm.resume(tobj);
    
public voidrollback()
Roll back the transaction associated with the current thread. When this method completes, the thread becomes associated with no transaction.

exception
SecurityException Thrown to indicate that the thread is not allowed to roll back the transaction.
exception
IllegalStateException Thrown if the current thread is not associated with a transaction.
exception
SystemException Thrown if the transaction manager encounters an unexpected error condition

		if (_logger.isLoggable(Level.FINE))
        	_logger.log(Level.FINE,"TM: rollback");
        validateTransactionManager();
        // START IASRI 4662745
        Object obj = null;
        if (monitoringEnabled){
            obj = tm.getTransaction();
        }
        if (invMgr.isInvocationStackEmpty()) {
            tm.rollback();
        } else {
            ComponentInvocation curr = null;
            try {
                curr = invMgr.getCurrentInvocation();
                if (curr != null)
                    curr.setTransactionCompeting(true);
                tm.rollback();
            } catch (InvocationException ex) {
                assert false;
            } finally {
                if (curr != null) {
                    curr.setTransactionCompeting(false);
                }
            }
        }
        
        if (monitoringEnabled){
            monitorTxCompleted(obj, false);
        }
        // END IASRI 4662745
        
    
public voidsetDefaultTransactionTimeout(int seconds)

        if (seconds < 0) seconds = 0;
        transactionTimeout = seconds;
    
public voidsetMonitoringEnabled(boolean enabled)

        monitoringEnabled = enabled;
	//reset the variables
    	m_transCommitted = 0;
    	m_transRolledback = 0;
    	m_transInFlight = 0;
        activeTransactions.removeAllElements();
    
public voidsetRollbackOnly()
Modify the transaction associated with the current thread such that the only possible outcome of the transaction is to roll back the transaction.

exception
IllegalStateException Thrown if the current thread is not associated with a transaction.
exception
SystemException Thrown if the transaction manager encounters an unexpected error condition

		if (_logger.isLoggable(Level.FINE))
        	_logger.log(Level.FINE,"TM: setRollbackOnly");
        validateTransactionManager();
        tm.setRollbackOnly();
    
public voidsetTransactionTimeout(int seconds)
Modify the value of the timeout value that is associated with the transactions started by the current thread with the begin method.

If an application has not called this method, the transaction service uses some default value for the transaction timeout.

param
seconds The value of the timeout in seconds. If the value is zero, the transaction service restores the default value.
exception
SystemException Thrown if the transaction manager encounters an unexpected error condition

        if (seconds < 0) seconds = 0;
        txnTmout.set(seconds);
        // transactionTimeout = seconds;
    
public javax.transaction.Transactionsuspend()
Suspend the transaction currently associated with the calling thread and return a Transaction object that represents the transaction context being suspended. If the calling thread is not associated with a transaction, the method returns a null object reference. When this method returns, the calling thread is associated with no transaction.

exception
SystemException Thrown if the transaction manager encounters an unexpected error condition
exception
SystemException Thrown if the transaction manager encounters an unexpected error condition

		if (_logger.isLoggable(Level.FINE))
        	_logger.log(Level.FINE,"TM: suspend");
        validateTransactionManager();
        return tm.suspend();
    
public synchronized voidunfreeze()

        if(com.sun.jts.CosTransactions.AdminUtil.isFrozenAll()){
            com.sun.jts.CosTransactions.AdminUtil.unfreezeAll();
        }
    
public voidunregisterComponentResource(ResourceHandle h)

        Object instance = h.getComponentInstance();
        if (instance == null) return;
        h.setComponentInstance(null);
        ComponentInvocation inv = invMgr.getCurrentInvocation();
        List l = null;
        if (inv != null)
            l = getExistingResourceList(instance, inv);
        else
            l = getExistingResourceList(instance);
	if (l != null) {
            l.remove(h);
	}
    
private voidvalidateTransactionManager()

        if (tm == null) {
            throw new IllegalStateException
            (sm.getString("enterprise_distributedtx.transaction_notactive"));
        }