[jboss-svn-commits] JBL Code SVN: r24424 - in labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243: ArjunaJTA/jta and 5 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Thu Dec 18 10:33:12 EST 2008


Author: jhalliday
Date: 2008-12-18 10:33:11 -0500 (Thu, 18 Dec 2008)
New Revision: 24424

Added:
   labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/
   labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/SubordinateTestCase.java
   labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/TestSynchronization.java
   labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/TestXAResource.java
Removed:
   labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/SubordinateTestCase.java
   labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/TestSynchronization.java
   labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/TestXAResource.java
Modified:
   labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/ActionManager.java
   labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/BasicAction.java
   labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/build.xml
   labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/TransactionImple.java
   labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/XATerminatorImple.java
   labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/SubordinateAtomicAction.java
   labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/TransactionImple.java
Log:
Ported assorted subtransaction fixes from the 4.2.3.CP branch.  JBPAPP-1511


Modified: labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/ActionManager.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/ActionManager.java	2008-12-18 15:29:00 UTC (rev 24423)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/ActionManager.java	2008-12-18 15:33:11 UTC (rev 24424)
@@ -33,42 +33,87 @@
 
 import com.arjuna.ats.arjuna.common.Uid;
 
+import java.util.Collection;
 import java.util.Hashtable;
 
 /*
  * @author Mark Little (mark_little at hp.com)
- * @version $Id: ActionManager.java 2342 2006-03-30 13:06:17Z  $
+ * 
+ * @version $Id: ActionManager.java 2342 2006-03-30 13:06:17Z $
  * @since JTS 3.0
  */
 
 public class ActionManager
 {
 
-    public static final ActionManager manager ()
-    {
-	return _theManager;
-    }
-    
-    public void put (BasicAction act)
-    {
-	_allActions.put(act.get_uid(), act);
-    }
-    
-    public BasicAction get (Uid id)
-    {
-	return (BasicAction) _allActions.get(id);
-    }
-    
-    public void remove (Uid id)
-    {
- 	_allActions.remove(id);
-    }
-    
-    private ActionManager ()
-    {
-    }
-    
-    private static ActionManager _theManager = new ActionManager();
-    private static Hashtable     _allActions = new Hashtable();
+	class Lifetime
+	{
+		public Lifetime (BasicAction act)
+		{
+			theAction = act;
+			timeAdded = System.currentTimeMillis();
+		}
+		
+		public BasicAction getAction ()
+		{
+			return theAction;
+		}
+		
+		public long getTimeAdded ()
+		{
+			return timeAdded;
+		}
+		
+		private BasicAction theAction;
+		private long timeAdded;
+	}
+	
+	public static final ActionManager manager()
+	{
+		return _theManager;
+	}
 
+	public void put(BasicAction act)
+	{
+		_allActions.put(act.get_uid(), new Lifetime(act));
+	}
+
+	public BasicAction get(Uid id)
+	{
+		Lifetime lt = (Lifetime) _allActions.get(id);
+		
+		if (lt != null)
+			return lt.getAction();
+		else
+			return null;
+	}
+
+	public long getTimeAdded (Uid id)
+	{
+		Lifetime lt = (Lifetime) _allActions.get(id);
+		
+		if (lt != null)
+			return lt.getTimeAdded();
+		else
+			return 0;
+	}
+	
+	public void remove(Uid id)
+	{
+		_allActions.remove(id);
+	}
+
+	public Collection inflightTransactions ()
+	{
+		return _allActions.values();
+	}
+	
+	private ActionManager()
+	{
+	}
+
+	private static final ActionManager _theManager = new ActionManager();
+
+	private static final Hashtable _allActions = new Hashtable();
+
 }

Modified: labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/BasicAction.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/BasicAction.java	2008-12-18 15:29:00 UTC (rev 24423)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/BasicAction.java	2008-12-18 15:33:11 UTC (rev 24424)
@@ -1,20 +1,20 @@
 /*
  * JBoss, Home of Professional Open Source
- * Copyright 2006, Red Hat Middleware LLC, and individual contributors 
- * as indicated by the @author tags. 
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
  * See the copyright.txt in the distribution for a
- * full listing of individual contributors. 
+ * full listing of individual contributors.
  * This copyrighted material is made available to anyone wishing to use,
  * modify, copy, or redistribute it subject to the terms and conditions
  * of the GNU Lesser General Public License, v. 2.1.
- * This program is distributed in the hope that it will be useful, but WITHOUT A 
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * 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,
  * v.2.1 along with this distribution; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  * MA  02110-1301, USA.
- * 
+ *
  * (C) 2005-2006,
  * @author JBoss Inc.
  */
@@ -24,7 +24,7 @@
  * Arjuna Solutions Limited,
  * Newcastle upon Tyne,
  * Tyne and Wear,
- * UK.  
+ * UK.
  *
  * $Id: BasicAction.java 2342 2006-03-30 13:06:17Z  $
  */
@@ -53,13 +53,13 @@
 /**
  * BasicAction does most of the work of an atomic action, but does not manage
  * thread scoping. This is the responsibility of any derived classes.
- * 
+ *
  * @author Mark Little (mark at arjuna.com)
  * @version $Id: BasicAction.java 2342 2006-03-30 13:06:17Z  $
  * @since JTS 1.0.
- * 
- * 
- * 
+ *
+ *
+ *
  * @message com.arjuna.ats.arjuna.coordinator.BasicAction_1
  *          [com.arjuna.ats.arjuna.coordinator.BasicAction_1] - Action nesting
  *          error - deletion of action id {0} invoked while child actions active
@@ -472,7 +472,7 @@
 	/**
 	 * Force the only outcome for the transaction to be to rollback. Only
 	 * possible if this transaction has not (or is not) terminated.
-	 * 
+	 *
 	 * @return <code>true</code> if successful, <code>false</code>
 	 *         otherwise.
 	 */
@@ -510,7 +510,7 @@
 	 * Add a record to the atomic action. This function returns AR_ADDED if the
 	 * record is added. AR_REJECTED if the record cannot be added because the
 	 * action is past the prepare phase, and IGNORED otherwise.
-	 * 
+	 *
 	 * @return <code>AddOutcome</code> indicating outcome.
 	 */
 
@@ -550,7 +550,7 @@
 	/**
 	 * boolean function that checks whether the Uid passed as an argument is the
 	 * Uid for an ancestor of the current atomic action.
-	 * 
+	 *
 	 * @return <code>true</code> if the parameter represents an ancestor,
 	 *         <code>false</code> otherwise.
 	 */
@@ -607,7 +607,7 @@
 
 	/**
 	 * Set up an object store and assign it to the currentStore variable.
-	 * 
+	 *
 	 * @return the object store implementation to use.
 	 * @see com.arjuna.ats.arjuna.objectstore.ObjectStore
 	 */
@@ -631,7 +631,7 @@
 	 * The following function returns the Uid of the top-level atomic action. If
 	 * this is the top-level transaction then it is equivalent to calling
 	 * get_uid().
-	 * 
+	 *
 	 * @return the top-level transaction's <code>Uid</code>.
 	 */
 
@@ -664,7 +664,7 @@
 	/**
 	 * Overloaded version of activate -- sets up the store, performs read_state
 	 * followed by restore_state. The store root is <code>null</code>.
-	 * 
+	 *
 	 * @return <code>true</code> if successful, <code>false</code>
 	 *         otherwise.
 	 */
@@ -678,7 +678,7 @@
 	 * Overloaded version of activate -- sets up the store, performs read_state
 	 * followed by restore_state. The root of the object store to use is
 	 * specified in the <code>root</code> parameter.
-	 * 
+	 *
 	 * @return <code>true</code> if successful, <code>false</code>
 	 *         otherwise.
 	 */
@@ -740,10 +740,10 @@
 	 * This operation deactivates a persistent object. It behaves in a similar
 	 * manner to the activate operation, but has an extra argument which defines
 	 * whether the object's state should be committed or written as a shadow.
-	 * 
+	 *
 	 * The root of the object store is <code>null</code>. It is assumed that
 	 * this is being called during a transaction commit.
-	 * 
+	 *
 	 * @return <code>true</code> on success, <code>false</code> otherwise.
 	 */
 
@@ -810,7 +810,7 @@
 	/**
 	 * Add the current thread to the list of threads associated with this
 	 * transaction.
-	 * 
+	 *
 	 * @return <code>true</code> if successful, <code>false</code>
 	 *         otherwise.
 	 */
@@ -823,7 +823,7 @@
 	/**
 	 * Add the specified thread to the list of threads associated with this
 	 * transaction.
-	 * 
+	 *
 	 * @return <code>true</code> if successful, <code>false</code>
 	 *         otherwise.
 	 */
@@ -874,7 +874,7 @@
 
 	/**
 	 * Remove a child thread. The current thread is removed.
-	 * 
+	 *
 	 * @return <code>true</code> if successful, <code>false</code>
 	 *         otherwise.
 	 */
@@ -886,7 +886,7 @@
 
 	/**
 	 * Remove the specified thread from the transaction.
-	 * 
+	 *
 	 * @return <code>true</code> if successful, <code>false</code>
 	 *         otherwise.
 	 */
@@ -932,7 +932,7 @@
 
 	/**
 	 * Add a new child action to the atomic action.
-	 * 
+	 *
 	 * @return <code>true</code> if successful, <code>false</code>
 	 *         otherwise.
 	 */
@@ -990,7 +990,7 @@
 
 	/**
 	 * Remove a child action.
-	 * 
+	 *
 	 * @return <code>true</code> if successful, <code>false</code>
 	 *         otherwise.
 	 */
@@ -1036,7 +1036,7 @@
 
 	/**
 	 * Add the specified CheckedAction object to this transaction.
-	 * 
+	 *
 	 * @return the previous <code>CheckedAction</code>.
 	 * @see com.arjuna.ats.arjuna.coordinator.CheckedAction
 	 */
@@ -1076,17 +1076,17 @@
 
 	/**
 	 * Redefined version of save_state and restore_state from StateManager.
-	 * 
+	 *
 	 * Normal operation (no crashes):
-	 * 
+	 *
 	 * BasicAction.save_state is called after a successful prepare. This causes
 	 * and BasicAction object to be saved in the object store. This object
 	 * contains primarily the "intentions list" of the BasicAction. After
 	 * successfully completing phase 2 of the commit protocol, the BasicAction
 	 * object is deleted from the store.
-	 * 
+	 *
 	 * Failure cases:
-	 * 
+	 *
 	 * If a server crashes after successfully preparing, then upon recovery the
 	 * action must be resolved (either committed or aborted) depending upon
 	 * whether the co-ordinating atomic action committed or aborted. Upon server
@@ -1094,20 +1094,20 @@
 	 * in the object store and attempts to activate the BasicAction object of
 	 * the co-ordinating action. If this is successful then the SAA is committed
 	 * else aborted.
-	 * 
+	 *
 	 * If, when processing phase 2 of the commit protocol, the co-ordinator
 	 * experiences a failure to commit from one of the records then the
 	 * BasicAction object is NOT deleted. It is rewritten when a new state which
 	 * contains a list of the records that failed during phase 2 commit. This
 	 * list is called the "failedList".
-	 * 
+	 *
 	 * The crash recovery manager will detect local BasicAction objects in
 	 * addition to SAA objects in the objectstore. An attempt will be made to
 	 * commit these actions. If the action contained a call to a now dead
 	 * server, this action can never be resolved and the AA object can never be
 	 * removed. However, if the action is purely local then after the processing
 	 * is complete the removed by crash recovery.
-	 * 
+	 *
 	 * @return <code>true</code> if successful, <code>false</code>
 	 *         otherwise.
 	 */
@@ -1133,7 +1133,7 @@
 		 * successful prepare - to save the intentions list. b) After a failure
 		 * during phase 2 of commit - to overwrite the intentions list by the
 		 * failedList.
-		 * 
+		 *
 		 * If we're using presumed nothing, then it could be called: a) Whenever
 		 * a participant is registered.
 		 */
@@ -1338,7 +1338,7 @@
 
 	/**
 	 * This assumes the various lists are zero length when it is called.
-	 * 
+	 *
 	 * @return <code>true</code> if successful, <code>false</code>
 	 *         otherwise.
 	 */
@@ -1558,7 +1558,7 @@
 	 * we have received all outcomes from registered resources). By specifying
 	 * otherwise, we will always maintain the heuristic information, which may
 	 * prove useful for logging and off-line resolution.
-	 * 
+	 *
 	 * @return <code>true</code> if the transaction should save its heuristic
 	 *         information, <code>false</code> otherwise.
 	 */
@@ -1571,7 +1571,7 @@
 	/**
 	 * Overloads <code>StateManager.destroy</code> to prevent destroy being
 	 * called on a BasicAction. Could be a *very* bad idea!!
-	 * 
+	 *
 	 * @return <code>false</code>.
 	 * @see com.arjuna.ats.arjuna.StateManager
 	 */
@@ -1615,7 +1615,7 @@
 	/**
 	 * Forget any heuristics we may have received, and tell the resources which
 	 * generated them to forget too.
-	 * 
+	 *
 	 * @return <code>true</code> if heuristic information (if any) was
 	 *         successfully forgotten, <code>false</code> otherwise.
 	 */
@@ -1639,7 +1639,7 @@
 	/**
 	 * Atomic action Begin operation. Does not change the calling thread's
 	 * notion of the current transaction.
-	 * 
+	 *
 	 * @return <code>ActionStatus</code> indicating outcome.
 	 */
 
@@ -1650,7 +1650,7 @@
 			tsLogger.arjLogger.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PROTECTED, FacilityCode.FAC_ATOMIC_ACTION, "BasicAction::Begin() for action-id "
 					+ get_uid());
 		}
-		
+
 		if (actionStatus != ActionStatus.CREATED)
 		{
 			if (tsLogger.arjLoggerI18N.isWarnEnabled())
@@ -1708,16 +1708,16 @@
 	 * preparedList and the readonlyList, also if the action is topLevel then
 	 * the intention list will have been written to the object store. Then
 	 * invoke phase2Commit and clean up the object store if necessary
-	 * 
+	 *
 	 * If prepare() fails invoke phase2Abort. In this case the pendingList may
 	 * still contain records but phase2Abort takes care of these. Also in this
 	 * case no intention list has been written.
-	 * 
+	 *
 	 * Does not change the calling thread's notion of the current transaction.
-	 * 
+	 *
 	 * Any heuristic outcomes will only be reported if the parameter is
 	 * <code>true</code>.
-	 * 
+	 *
 	 * @return <code>ActionStatus</code> indicating outcome.
 	 */
 
@@ -1766,7 +1766,7 @@
 		{
 			return Abort();
 		}
-	
+
 		if (pendingList != null)
 		{
 			/*
@@ -1777,9 +1777,11 @@
 			if (doOnePhase())
 			{
 				onePhaseCommit(reportHeuristics);
+
+				ActionManager.manager().remove(get_uid());
 			}
 			else
-			{			
+			{
 				if (prepare(reportHeuristics) == TwoPhaseOutcome.PREPARE_NOTOK)
 				{
 					if (tsLogger.arjLoggerI18N.isWarnEnabled())
@@ -1821,11 +1823,12 @@
 			}
 		}
 		else
+		{
+			ActionManager.manager().remove(get_uid());
+
 			actionStatus = ActionStatus.COMMITTED;
+		}
 
-		//BasicAction.allActions.remove(get_uid());
-		ActionManager.manager().remove(get_uid());
-
 		boolean returnCurrentStatus = false;
 
 		if (reportHeuristics || (!reportHeuristics && !TxControl.asyncCommit))
@@ -1865,9 +1868,9 @@
 	 * This is the user callable abort operation. It is invoked prior to the
 	 * start of two-phase commit and hence only processes records in the
 	 * pendingList (the other lists should be empty).
-	 * 
+	 *
 	 * Does not change the calling thread's notion of the current transaction.
-	 * 
+	 *
 	 * @return <code>ActionStatus</code> indicating outcome.
 	 */
 
@@ -2040,10 +2043,10 @@
 	 * we need to cleanup. This is essentially the same as phase2Abort but we
 	 * call cleanup ops rather than abort ops and let the records take care of
 	 * appropriate cleanup.
-	 * 
+	 *
 	 * The pendingList is processed because it may not be empty - since
 	 * prepare() stops processing the list at the first PREPARE_NOTOK result.
-	 * 
+	 *
 	 * The read_only list is processed to ensure that actions are aborted
 	 * immediately and any servers killed at that point since they need not hang
 	 * around. This contrasts with commit where readonlyList entries are simply
@@ -2080,12 +2083,12 @@
 	 * This ensures that the appropriate commit operation is performed on each
 	 * entry which is then either deleted (top_level) or merged into the
 	 * parent's pendingList.
-	 * 
+	 *
 	 * Processing of the readonlyList is different in that if the action is
 	 * top_level then all records in the readonlyList are deleted without
 	 * further processing. If nested the records must be merged. This is an
 	 * optimisation to avoid unnecessary processing.
-	 * 
+	 *
 	 * Note that at this point the pendingList SHOULD be empty due to the prior
 	 * invocation of prepare().
 	 */
@@ -2168,6 +2171,8 @@
 
 			updateState();
 
+			ActionManager.manager().remove(get_uid());
+
 			criticalEnd();
 		}
 	}
@@ -2176,10 +2181,10 @@
 	 * Second phase of the two phase commit protocol for aborting actions.
 	 * Actions are aborted by invoking the doAbort operation on the
 	 * preparedList, the readonlyList, and the pendingList.
-	 * 
+	 *
 	 * The pendingList is processed because it may not be empty - since
 	 * prepare() stops processing the list at the first PREPARE_NOTOK result.
-	 * 
+	 *
 	 * By default, records that responsed PREPARE_READONLY will not be contacted
 	 * during second-phase abort, just as they are not during second-phase
 	 * commit. This can be overridden at runtime using the READONLY_OPTIMISATION
@@ -2227,6 +2232,8 @@
 		updateState(); // we may end up saving more than the heuristic list
 					   // here!
 
+		ActionManager.manager().remove(get_uid());
+
 		criticalEnd();
 	}
 
@@ -2236,7 +2243,7 @@
 	 * if not PREPARE_NOTOK. The value PREPARE_READONLY may also be returned if
 	 * all the records indicate that they are readonly records. Such records do
 	 * not take part in the second phase commit processing.
-	 * 
+	 *
 	 * @return <code>TwoPhaseOutcome</code> indicating outcome.
 	 */
 
@@ -2290,7 +2297,7 @@
 		 * invoking the appropriate prepare operation. If it succeeds put the
 		 * record on either the preparedList or the read_only list and continue
 		 * until the pendingList is exhausted.
-		 * 
+		 *
 		 * If prepare fails on any record stop processing immediately and put
 		 * the offending record back on the pendingList
 		 */
@@ -2488,16 +2495,16 @@
 		/*
 		 * The actual state we want to write depends upon whether or not we are
 		 * in charge of the transaction outcome:
-		 * 
+		 *
 		 * (i) if we are a root transaction, or an interposed transaction which
 		 * received a commit_one_phase call, then we have complete control over
 		 * what the transaction outcome will be. So, we will always try to
 		 * commit, and can set the state to committing.
-		 * 
+		 *
 		 * (ii) if we are an interposed transaction and it receives a complete
 		 * two-phase protocol, then the root is in control. So, we set the state
 		 * to prepared.
-		 * 
+		 *
 		 * (iii) nested transactions never write state, so the state is set to
 		 * prepared anyway.
 		 */
@@ -2538,7 +2545,7 @@
 			if (state.notempty())
 			{
 				try
-				{				
+				{
 					if (!currentStore.write_committed(u, tn, state))
 					{
 						if (tsLogger.arjLoggerI18N.isWarnEnabled())
@@ -2615,10 +2622,10 @@
 		boolean stateToSave = false;
 
 		recordBeingHandled = pendingList.getFront();
-	
+
 		int p = ((actionType == ActionType.TOP_LEVEL) ? recordBeingHandled.topLevelOnePhaseCommit()
 				: recordBeingHandled.nestedOnePhaseCommit());
-	
+
 		if ((p == TwoPhaseOutcome.FINISH_OK)
 				|| (p == TwoPhaseOutcome.PREPARE_READONLY))
 		{
@@ -2701,7 +2708,7 @@
 		}
 
 		if (actionType == ActionType.TOP_LEVEL)
-		{			
+		{
 			if (stateToSave && (heuristicList.size() > 0))
 			{
 				if (store() == null)
@@ -2722,6 +2729,8 @@
 
 		forgetHeuristics();
 
+		ActionManager.manager().remove(get_uid());
+
 		criticalEnd();
 	}
 
@@ -2751,7 +2760,7 @@
 
 	/**
 	 * @return the transaction's prepared status.
-	 * 
+	 *
 	 * @since JTS 2.0.
 	 */
 
@@ -2799,7 +2808,7 @@
 		 * invoking the appropriate prepare operation. If it succeeds put the
 		 * record on either the preparedList or the read_only list and continue
 		 * until the pendingList is exhausted.
-		 * 
+		 *
 		 * If prepare fails on any record stop processing immediately and put
 		 * the offending record back on the pendingList.
 		 */
@@ -2830,7 +2839,7 @@
 				/*
 				 * If failure then it's back on the pending list by now. Move on
 				 * or terminate?
-				 * 
+				 *
 				 * Move on if a cohesion, but terminate if an atom!!
 				 */
 			}
@@ -2858,7 +2867,7 @@
 		 * invoking the appropriate prepare operation. If it succeeds put the
 		 * record on either the preparedList or the read_only list and continue
 		 * until the pendingList is exhausted.
-		 * 
+		 *
 		 * If prepare fails on any record stop processing immediately and put
 		 * the offending record back on the pendingList.
 		 */
@@ -2919,12 +2928,12 @@
 								 * invocation must come from that since they
 								 * have already been told this transaction has
 								 * committed!
-								 * 
+								 *
 								 * However, since we may be multi-threaded
 								 * (asynchronous prepare) we don't do the
 								 * merging yet. Wait until all threads have
 								 * terminated and then do it.
-								 * 
+								 *
 								 * Therefore, can't force parent to rollback
 								 * state at present, or merge will fail.
 								 */
@@ -3120,7 +3129,7 @@
 																	  // committed
 				}
 				else
-				{				
+				{
 					if (tsLogger.arjLoggerI18N.debugAllowed(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PRIVATE, FacilityCode.FAC_ATOMIC_ACTION))
 					{
 						tsLogger.arjLoggerI18N.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PRIVATE, FacilityCode.FAC_ATOMIC_ACTION, "com.arjuna.ats.arjuna.coordinator.BasicAction_51", new Object[]
@@ -3313,7 +3322,7 @@
 	 * that has it as its current transaction? The base class has this check
 	 * enabled (i.e., we check), but some implementations may wish to override
 	 * this.
-	 * 
+	 *
 	 * @return <code>false</code> to disable checking.
 	 */
 
@@ -3324,7 +3333,7 @@
 
 	/*
 	 * If we get a single heuristic then we will always rollback during prepare.
-	 * 
+	 *
 	 * Getting a heuristic during commit is slightly different, since some
 	 * resources may have already committed, changing the type of heuristic we
 	 * may need to throw. However, once we get to commit we know that it will be
@@ -3485,7 +3494,7 @@
 				try
 				{
 					if (savedIntentionList)
-					{						
+					{
 						if (currentStore.remove_committed(getSavingUid(), type()))
 						{
 							savedIntentionList = false;
@@ -3527,7 +3536,7 @@
 	/**
 	 * Check to see if this transaction is the one that is current for this
 	 * thread. If it isn't, then we mark this transaction as rollback only.
-	 * 
+	 *
 	 * @return <code>true</code> if the transaction is current,
 	 *         <code>false</code> otherwise.
 	 */
@@ -3628,7 +3637,7 @@
 			 * We may have already aborted our children, e.g., because of an
 			 * out-of-sequence commit, so we check here to reduce the number of
 			 * error messages!
-			 * 
+			 *
 			 * We can't just remove the children when we are finished with them
 			 * because BasicAction is not responsible for action tracking.
 			 */
@@ -3688,7 +3697,7 @@
 	 * Just in case we are deleted/terminated with threads still registered. We
 	 * must make sure those threads don't try to remove themselves from this
 	 * action later. So we unregister them ourselves now.
-	 * 
+	 *
 	 * This is only called by End/Abort and so all child actions will have been
 	 * previously terminated as well.
 	 */
@@ -3811,7 +3820,7 @@
 		 * we never explicitly tell resources to forget. We assume that the user
 		 * (or some management tool) will do this, and simply save as much
 		 * information as we can into the action state to allow them to do so.
-		 * 
+		 *
 		 * However, if we had a resource that returned a heuristic outcome and
 		 * we managed to make the outcome of this transaction the same as that
 		 * outcome, we removed the heuristic. So, we need to tell the resource
@@ -3857,9 +3866,9 @@
 	 * cleanup function. Discard records when done. NOTE: We only need to do
 	 * cleanup at top level since cleanup at nested level would be subsumed when
 	 * the parent action is forced to abort
-	 * 
+	 *
 	 * Ignore heuristics. Who can we report them to?
-	 * 
+	 *
 	 * This routine is called by phase2Cleanup, which gets called only in
 	 * exceptional circumstances. By default we leave cleaning up the various
 	 * lists until the action instance goes out of scope.
@@ -3941,7 +3950,7 @@
 	protected RecordList failedList;
 	protected RecordList heuristicList;
 	protected boolean savedIntentionList;
-	
+
 	private ActionHierarchy currentHierarchy;
 	private ObjectStore currentStore;
 

Modified: labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/build.xml
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/build.xml	2008-12-18 15:29:00 UTC (rev 24423)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/build.xml	2008-12-18 15:33:11 UTC (rev 24424)
@@ -203,6 +203,7 @@
                 <batchtest haltonerror="yes" haltonfailure="yes" fork="yes"
                     todir="${com.hp.mwlabs.ts.jta.reports.dest}">
                     <fileset dir="${com.hp.mwlabs.ts.jta.tests.src}" includes="**/LastResource*TestCase.java"/>
+                    <fileset dir="${com.hp.mwlabs.ts.jta.tests.src}" includes="**/SubordinateTestCase.java"/>
                 </batchtest>
             </junit>
 	</target>

Modified: labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/TransactionImple.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/TransactionImple.java	2008-12-18 15:29:00 UTC (rev 24423)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/TransactionImple.java	2008-12-18 15:33:11 UTC (rev 24424)
@@ -513,7 +513,7 @@
 	 *          [com.arjuna.ats.internal.jta.transaction.arjunacore.xastart] {0} -
 	 *          caught: {1} for {2}
 	 * @message com.arjuna.ats.internal.jta.transaction.arjunacore.elistwhenmarkedrollback
-	 *          [com.arjuna.ats.internal.jta.transaction.arjunacore.elistwhenmarkedrollback]
+	 *          [com.arjuna.ats.internal.jtamultiple.transaction.arjunacore.elistwhenmarkedrollback]
 	 *          Can't enlist the resource because the transaction is marked for
 	 *          rollback
 	 */

Modified: labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/XATerminatorImple.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/XATerminatorImple.java	2008-12-18 15:29:00 UTC (rev 24423)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/jca/XATerminatorImple.java	2008-12-18 15:33:11 UTC (rev 24424)
@@ -1,20 +1,20 @@
 /*
  * JBoss, Home of Professional Open Source
- * Copyright 2006, Red Hat Middleware LLC, and individual contributors 
- * as indicated by the @author tags. 
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
  * See the copyright.txt in the distribution for a
- * full listing of individual contributors. 
+ * full listing of individual contributors.
  * This copyrighted material is made available to anyone wishing to use,
  * modify, copy, or redistribute it subject to the terms and conditions
  * of the GNU Lesser General Public License, v. 2.1.
- * This program is distributed in the hope that it will be useful, but WITHOUT A 
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * 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,
  * v.2.1 along with this distribution; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  * MA  02110-1301, USA.
- * 
+ *
  * (C) 2005-2006,
  * @author JBoss Inc.
  */
@@ -34,10 +34,7 @@
 import java.io.IOException;
 import java.util.Stack;
 
-import javax.transaction.HeuristicCommitException;
-import javax.transaction.HeuristicMixedException;
-import javax.transaction.HeuristicRollbackException;
-import javax.transaction.SystemException;
+import javax.transaction.*;
 import javax.transaction.xa.*;
 
 import com.arjuna.ats.arjuna.common.Uid;
@@ -51,7 +48,7 @@
 
 /**
  * The XATerminator implementation.
- * 
+ *
  * @author mcl
  *
  */
@@ -62,36 +59,42 @@
 	/**
 	 * Commit the transaction identified and hence any inflow-associated
 	 * work.
-	 * 
+	 *
 	 * @param xid the transaction to commit
 	 * @param onePhase whether or not this is a one-phase commit (should only
 	 * be <code>true</code> if there is a single resource associated with the
 	 * transaction).
-	 * 
+	 *
 	 * @exception XAException thrown if there are any errors, including if
 	 * the transaction cannot commit and has to roll back.
 	 */
-	
+
 	public void commit (Xid xid, boolean onePhase) throws XAException
 	{
 		try
 		{
 			TransactionImple tx = TxImporter.getImportedTransaction(xid);
-			
+
 			if (tx == null)
 				throw new XAException(XAException.XAER_INVAL);
-			
+
 			if (onePhase)
 				tx.doOnePhaseCommit();
 			else
 				tx.doCommit();
-			
+
 			TxImporter.removeImportedTransaction(xid);
 		}
+        catch(RollbackException e) {
+            TxImporter.removeImportedTransaction(xid);
+            XAException xaException = new XAException(XAException.XA_RBROLLBACK);
+            xaException.initCause(e);
+            throw xaException;
+        }
 		catch (XAException ex)
 		{
 			TxImporter.removeImportedTransaction(xid);
-			
+
 			throw ex;
 		}
 		catch (HeuristicRollbackException ex)
@@ -105,30 +108,30 @@
 		catch (SystemException ex)
 		{
 			TxImporter.removeImportedTransaction(xid);
-			
+
 			throw new XAException(XAException.XAER_RMERR);
 		}
 	}
-	
+
 	/**
 	 * If the transaction subordinate generated a heuristic, then
 	 * this operation will be called later once that heuristic has been
 	 * resolved.
-	 * 
+	 *
 	 * @param xid the transaction.
-	 * 
+	 *
 	 * @throws XAException if any error happens.
 	 */
-	
+
 	public void forget (Xid xid) throws XAException
 	{
 		try
 		{
 			TransactionImple tx = TxImporter.getImportedTransaction(xid);
-			
+
 			if (tx == null)
 				throw new XAException(XAException.XAER_INVAL);
-			
+
 			tx.doForget();
 		}
 		catch (Exception ex)
@@ -140,39 +143,58 @@
 			TxImporter.removeImportedTransaction(xid);
 		}
 	}
-	
+
 	/**
 	 * Prepare the imported transaction.
-	 * 
+	 *
 	 * @param xid the transaction to prepare.
-	 * 
+	 *
 	 * @throws XAException thrown if any error occurs, including if the
 	 * transaction has rolled back.
-	 * 
+	 *
 	 * @return either XAResource.XA_OK if the transaction prepared, or
 	 * XAResource.XA_RDONLY if it was a read-only transaction (and in
 	 * which case, a second phase message is not expected/required.)
 	 */
-	
+
 	public int prepare (Xid xid) throws XAException
 	{
 		try
 		{
 			TransactionImple tx = TxImporter.getImportedTransaction(xid);
-			
+
 			if (tx == null)
 				throw new XAException(XAException.XAER_INVAL);
-			
+
 			switch (tx.doPrepare())
 			{
 			case TwoPhaseOutcome.PREPARE_READONLY:
 				TxImporter.removeImportedTransaction(xid);
-				
-				return XAResource.XA_RDONLY;				
+				return XAResource.XA_RDONLY;
 			case TwoPhaseOutcome.PREPARE_NOTOK:
-				TxImporter.removeImportedTransaction(xid);  // TODO check if rollback is going to be called first
-				
-				throw new XAException(XAException.XA_RBROLLBACK);
+                // the JCA API spec limits what we can do in terms of reporting problems.
+                // try to use the exception code and cause to provide info whilst
+                // ramining API compliant.  JBTM-427.
+                Exception initCause = null;
+                int xaExceptionCode = XAException.XA_RBROLLBACK;
+                try {
+                    tx.doRollback();
+                } catch(HeuristicCommitException e) {
+                    initCause = e;
+                    xaExceptionCode = XAException.XAER_RMERR;
+                } catch (HeuristicMixedException e) {
+                    initCause = e;
+                    xaExceptionCode = XAException.XAER_RMERR;
+                } catch (SystemException e) {
+                    initCause = e;
+                    xaExceptionCode = XAException.XAER_RMERR;
+                }
+                TxImporter.removeImportedTransaction(xid);
+                XAException xaException = new XAException(xaExceptionCode);
+                if(initCause != null) {
+                    xaException.initCause(initCause);
+                }
+				throw xaException;
 			case TwoPhaseOutcome.PREPARE_OK:
 				return XAResource.XA_OK;
 			default:
@@ -184,29 +206,29 @@
 			throw ex;
 		}
 	}
-	
+
 	/**
 	 * Return a list of indoubt transactions. This may include those
 	 * transactions that are currently in-flight and running 2PC and do not need recovery
 	 * invoked on them.
-	 * 
+	 *
 	 * @param flag either XAResource.TMSTARTRSCAN to indicate the start of
 	 * a recovery scan, or XAResource.TMENDRSCAN to indicate the end of
 	 * the recovery scan.
-	 * 
+	 *
 	 * @throws XAException thrown if any error occurs.
-	 * 
+	 *
 	 * @return a list of potentially indoubt transactions or <code>null</code>.
 	 */
-	
+
 	public Xid[] recover (int flag) throws XAException
-	{	
+	{
 		/*
 		 * Requires going through the objectstore for the states of imported
 		 * transactions. Our own crash recovery takes care of transactions imported
 		 * via CORBA, Web Services etc.
 		 */
-		
+
 		switch (flag)
 		{
 		case XAResource.TMSTARTRSCAN: // check the object store
@@ -227,23 +249,23 @@
 		default:
 			throw new XAException(XAException.XAER_PROTO);
 		}
-		
+
 		// if we are here, then check the object store
-		
+
 		Xid[] indoubt = null;
-		
+
 		try
 		{
 			ObjectStore objStore = new ObjectStore(TxControl.getActionStoreType());
 			InputObjectState states = new InputObjectState();
-			
+
 			// only look in the JCA section of the object store
-			
+
 			if (objStore.allObjUids(SubordinateAtomicAction.getType(), states) && (states.notempty()))
 			{
 				Stack values = new Stack();
 				boolean finished = false;
-				
+
 				do
 				{
 					Uid uid = new Uid(Uid.nullUid());
@@ -258,29 +280,29 @@
 
 						finished = true;
 					}
-					
+
 					if (uid.notEquals(Uid.nullUid()))
 					{
 						TransactionImple tx = TxImporter.recoverTransaction(uid);
-						
+
 						if (tx != null)
 							values.push(tx);
 					}
 					else
 						finished = true;
-					
+
 				} while (!finished);
-				
+
 				if (values.size() > 0)
 				{
 					int index = 0;
 
 					indoubt = new Xid[values.size()];
-								
+
 					while (!values.empty())
 					{
 						com.arjuna.ats.internal.jta.transaction.arjunacore.subordinate.jca.TransactionImple tx = (com.arjuna.ats.internal.jta.transaction.arjunacore.subordinate.jca.TransactionImple) values.pop();
-						
+
 						indoubt[index] = tx.baseXid();
 						index++;
 					}
@@ -291,35 +313,35 @@
 		{
 			ex.printStackTrace();
 		}
-			
+
 		return indoubt;
 	}
 
 	/**
 	 * Rollback the imported transaction subordinate.
-	 * 
+	 *
 	 * @param xid the transaction to roll back.
-	 * 
+	 *
 	 * @throws XAException thrown if there are any errors.
 	 */
-	
+
 	public void rollback (Xid xid) throws XAException
 	{
 		try
 		{
 			TransactionImple tx = TxImporter.getImportedTransaction(xid);
-			
+
 			if (tx == null)
 				throw new XAException(XAException.XAER_INVAL);
-			
+
 			tx.doRollback();
-			
+
 			TxImporter.removeImportedTransaction(xid);
 		}
 		catch (XAException ex)
 		{
 			TxImporter.removeImportedTransaction(xid);
-			
+
 			throw ex;
 		}
 		catch (HeuristicCommitException ex)
@@ -333,11 +355,11 @@
 		catch (SystemException ex)
 		{
 			TxImporter.removeImportedTransaction(xid);
-			
+
 			throw new XAException(XAException.XAER_RMERR);
 		}
 	}
-	
+
 	private boolean _recoveryStarted = false;
-	
+
 }

Modified: labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/SubordinateAtomicAction.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/SubordinateAtomicAction.java	2008-12-18 15:29:00 UTC (rev 24423)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/SubordinateAtomicAction.java	2008-12-18 15:33:11 UTC (rev 24424)
@@ -1,28 +1,28 @@
 /*
  * JBoss, Home of Professional Open Source
- * Copyright 2006, Red Hat Middleware LLC, and individual contributors 
- * as indicated by the @author tags. 
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
  * See the copyright.txt in the distribution for a
- * full listing of individual contributors. 
+ * full listing of individual contributors.
  * This copyrighted material is made available to anyone wishing to use,
  * modify, copy, or redistribute it subject to the terms and conditions
  * of the GNU Lesser General Public License, v. 2.1.
- * This program is distributed in the hope that it will be useful, but WITHOUT A 
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * 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,
  * v.2.1 along with this distribution; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  * MA  02110-1301, USA.
- * 
+ *
  * (C) 2005-2006,
  * @author JBoss Inc.
  */
 /*
  * Copyright (C) 2003,
- * 
+ *
  * Hewlett-Packard Arjuna Labs, Newcastle upon Tyne, Tyne and Wear, UK.
- * 
+ *
  * $Id: SubordinateAtomicAction.java 2342 2006-03-30 13:06:17Z  $
  */
 
@@ -37,7 +37,7 @@
 /**
  * A subordinate JTA transaction; used when importing another transaction
  * context.
- * 
+ *
  * @author mcl
  */
 
@@ -48,18 +48,18 @@
 	public SubordinateAtomicAction ()
 	{
 		super();
-		
+
 		start();
 	}
 
 	public SubordinateAtomicAction (int timeout)
 	{
 		super();
-		
+
 		start();
-		
+
 		// if it has a non-negative timeout, add it to the reaper.
-		
+
 		if (timeout > AtomicAction.NO_TIMEOUT)
 			TransactionReaper.transactionReaper(true).insert(this, timeout);
 	}
@@ -67,7 +67,7 @@
 	/**
 	 * Commit the transaction, and have heuristic reporting. Heuristic reporting
 	 * via the return code is enabled.
-	 * 
+	 *
 	 * @return <code>ActionStatus</code> indicating outcome.
 	 */
 
@@ -79,10 +79,10 @@
 	/**
 	 * Commit the transaction. The report_heuristics parameter can be used to
 	 * determine whether or not heuristic outcomes are reported.
-	 * 
+	 *
 	 * If the transaction has already terminated, or has not begun, then an
 	 * appropriate error code will be returned.
-	 * 
+	 *
 	 * @return <code>ActionStatus</code> indicating outcome.
 	 */
 
@@ -93,10 +93,10 @@
 
 	/**
 	 * Abort (rollback) the transaction.
-	 * 
+	 *
 	 * If the transaction has already terminated, or has not been begun, then an
 	 * appropriate error code will be returned.
-	 * 
+	 *
 	 * @return <code>ActionStatus</code> indicating outcome.
 	 */
 
@@ -108,15 +108,15 @@
 	/**
 	 * The type of the class is used to locate the state of the transaction log
 	 * in the object store.
-	 * 
+	 *
 	 * Overloads BasicAction.type()
-	 * 
+	 *
 	 * @return a string representation of the hierarchy of the class for storing
 	 *         logs in the transaction object store.
 	 */
 
 	// TODO crash recovery!!!!
-	
+
 	public String type ()
 	{
 		return "/StateManager/BasicAction/TwoPhaseCoordinator/AtomicAction/SubordinateAtomicAction";
@@ -124,12 +124,28 @@
 
 	public int doPrepare ()
 	{
-		if (super.beforeCompletion())
-			return super.prepare(true);
+        int status = super.status();
+
+        // In JTA spec, beforeCompletions are run on commit attempts only, not rollbacks.
+        // We attempt to mimic that here, even though we are outside the scope of the spec.
+        // note it's not perfect- async timeout/rollback means there is a race condition in which we
+        // can still call beforeCompletion on rollbacks, but that's not too bad as skipping it is really
+        // just an optimization anyhow.  JBTM-429
+        if ( !(status == ActionStatus.ABORT_ONLY || status == ActionStatus.ABORTING) && super.beforeCompletion())
+        {
+            int outcome = super.prepare(true);
+            if(outcome == TwoPhaseOutcome.PREPARE_READONLY) {
+                // we won't get called again, so we need to clean up
+                // and run the afterCompletions before returning.
+                doCommit();
+            }
+
+            return outcome;
+        }
 		else
 		{
 			super.phase2Abort(true);
-			
+
 			return TwoPhaseOutcome.PREPARE_NOTOK;
 		}
 	}
@@ -139,12 +155,12 @@
 		super.phase2Commit(true);
 
 		int toReturn;
-		
+
 		switch (super.getHeuristicDecision())
 		{
 		case TwoPhaseOutcome.PREPARE_OK:
 		case TwoPhaseOutcome.FINISH_OK:
-			toReturn = super.status();		
+			toReturn = super.status();
 			break;
 		case TwoPhaseOutcome.HEURISTIC_ROLLBACK:
 			toReturn = ActionStatus.H_ROLLBACK;
@@ -160,18 +176,18 @@
 			toReturn = ActionStatus.H_HAZARD;
 			break;
 		}
-		
+
 		super.afterCompletion(toReturn);
-		
+
 		return toReturn;
 	}
 
 	public int doRollback ()
 	{
 		super.phase2Abort(true);
-		
+
 		int toReturn;
-		
+
 		switch (super.getHeuristicDecision())
 		{
 		case TwoPhaseOutcome.PREPARE_OK:
@@ -192,38 +208,56 @@
 			toReturn = ActionStatus.H_HAZARD;
 			break;
 		}
-		
+
 		super.afterCompletion(toReturn);
-		
+
 		return toReturn;
 	}
 
 	public int doOnePhaseCommit ()
-	{
-		return super.End(true);
-	}
+    {
+        int status = super.status();
 
+        // In JTA spec, beforeCompletions are run on commit attempts only, not rollbacks.
+        // We attempt to mimic that here, even though we are outside the scope of the spec.
+        // note it's not perfect- async timeout/rollback means there is a race condition in which we
+        // can still call beforeCompletion on rollbacks, but that's not too bad as skipping it is really
+        // just an optimization anyhow. JBTM-429
+        // behaviour relies on java's lazy evaluation of the if clause:
+        if (status == ActionStatus.ABORT_ONLY || super.beforeCompletion())
+        {
+            status = super.End(true);
+        }
+        else
+        {
+            status = ActionStatus.ABORTED;
+        }
+
+        afterCompletion(status);
+        return status;
+    }
+
 	public void doForget ()
 	{
 		super.forgetHeuristics();
 	}
-	
+
 	/**
 	 * For crash recovery purposes.
-	 * 
+	 *
 	 * @param actId the identifier to recover.
 	 */
-	
+
 	protected SubordinateAtomicAction (Uid actId)
 	{
 		super(actId);
 	}
-	
+
 	/**
 	 * By default the BasicAction class only allows the termination of a
 	 * transaction if it's the one currently associated with the thread. We
 	 * override this here.
-	 * 
+	 *
 	 * @return <code>false</code> to indicate that this transaction can only
 	 *         be terminated by the right thread.
 	 */
@@ -232,5 +266,9 @@
 	{
 		return false;
 	}
-	
+
+    public boolean activated ()
+    {
+    	return true;
+    }
 }

Modified: labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/TransactionImple.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/TransactionImple.java	2008-12-18 15:29:00 UTC (rev 24423)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/subordinate/TransactionImple.java	2008-12-18 15:33:11 UTC (rev 24424)
@@ -1,20 +1,20 @@
 /*
  * JBoss, Home of Professional Open Source
- * Copyright 2006, Red Hat Middleware LLC, and individual contributors 
- * as indicated by the @author tags. 
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
  * See the copyright.txt in the distribution for a
- * full listing of individual contributors. 
+ * full listing of individual contributors.
  * This copyrighted material is made available to anyone wishing to use,
  * modify, copy, or redistribute it subject to the terms and conditions
  * of the GNU Lesser General Public License, v. 2.1.
- * This program is distributed in the hope that it will be useful, but WITHOUT A 
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * 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,
  * v.2.1 along with this distribution; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  * MA  02110-1301, USA.
- * 
+ *
  * (C) 2005-2006,
  * @author JBoss Inc.
  */
@@ -41,10 +41,7 @@
 
 import java.lang.IllegalStateException;
 
-import javax.transaction.HeuristicCommitException;
-import javax.transaction.HeuristicMixedException;
-import javax.transaction.HeuristicRollbackException;
-import javax.transaction.SystemException;
+import javax.transaction.*;
 
 /**
  * @message com.arjuna.ats.internal.jta.transaction.arjunacore.subordinate.invalidstate
@@ -64,9 +61,9 @@
 	{
 		this(new SubordinateAtomicAction(timeout));
 	}
-	
+
 	// TODO use the timeout!
-	
+
 	public TransactionImple (AtomicAction act)
 	{
 		super(act);
@@ -127,7 +124,7 @@
 	}
 
 	// Should probably return XA status codes, c.f., XAResource.prepare
-	
+
 	public int doPrepare ()
 	{
 		try
@@ -136,7 +133,7 @@
 
 			if (!endSuspendedRMs())
 				_theTransaction.preventCommit();
-			
+
 			int res = subAct.doPrepare();
 
 			switch (res)
@@ -171,7 +168,7 @@
 			{
 			case ActionStatus.COMMITTED:
 			case ActionStatus.COMMITTING:
-			case ActionStatus.H_COMMIT:				
+			case ActionStatus.H_COMMIT:
 				TransactionImple.removeTransaction(this);
 				break;
 			case ActionStatus.ABORTED:
@@ -184,7 +181,7 @@
 				throw new HeuristicMixedException();
 			case ActionStatus.INVALID:
 				TransactionImple.removeTransaction(this);
-				
+
 				throw new IllegalStateException();
 			default:
 				throw new HeuristicMixedException(); // not sure what
@@ -214,7 +211,7 @@
 					jtaLogger.loggerI18N.warn("com.arjuna.ats.internal.jta.transaction.arjunacore.endsuspendfailed1");
 				}
 			}
-			
+
 			int res = subAct.doRollback();
 
 			switch (res)
@@ -223,7 +220,7 @@
 			case ActionStatus.ABORTING:
 			case ActionStatus.H_ROLLBACK:
 				TransactionImple.removeTransaction(this);
-				
+
 				break;
 			case ActionStatus.H_COMMIT:
 				throw new HeuristicCommitException();
@@ -259,9 +256,9 @@
 			TransactionImple.removeTransaction(this);
 		}
 	}
-	
+
 	public void doOnePhaseCommit () throws IllegalStateException,
-			javax.transaction.HeuristicRollbackException
+			javax.transaction.HeuristicRollbackException, javax.transaction.SystemException, RollbackException
 	{
 		try
 		{
@@ -269,17 +266,20 @@
 
 			if (!endSuspendedRMs())
 				_theTransaction.preventCommit();
-			
-			int status = subAct.doOnePhaseCommit();		
 
+			int status = subAct.doOnePhaseCommit();
+
 			switch (status)
 			{
 			case ActionStatus.COMMITTED:
 			case ActionStatus.H_COMMIT:
 				TransactionImple.removeTransaction(this);
-				
 				break;
 			case ActionStatus.ABORTED:
+                TransactionImple.removeTransaction(this);
+                // JBTM-428. Note also this may be because the tx was set rollback only,
+                // in which case IllegalState may be a better option?
+                throw new RollbackException();
 			case ActionStatus.ABORTING:
 			case ActionStatus.H_HAZARD:
 			case ActionStatus.H_MIXED:
@@ -307,7 +307,7 @@
 					+ super._theTransaction + " >";
 		}
 	}
-	
+
 	protected void commitAndDisassociate ()
 			throws javax.transaction.RollbackException,
 			javax.transaction.HeuristicMixedException,
@@ -334,5 +334,17 @@
 
 		throw new IllegalStateException();
 	}
-	
+
+    /**
+	 * Because of recovery, it is possible that a transaction may not be able to
+	 * activate itself from the log initially, forcing us to retry later.
+	 *
+	 * @return <code>true</code> if the transaction was activated, <code>false</code>
+	 * otherwise.
+	 */
+
+    public boolean activated ()
+    {
+    	return true;
+    }
 }

Copied: labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate (from rev 24402, labs/jbosstm/branches/JBOSSTS_4_2_3_GA_CP/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate)

Deleted: labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/SubordinateTestCase.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_GA_CP/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/SubordinateTestCase.java	2008-12-17 15:51:25 UTC (rev 24402)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/SubordinateTestCase.java	2008-12-18 15:33:11 UTC (rev 24424)
@@ -1,271 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2006, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags.
- * See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU Lesser General Public License, v. 2.1.
- * This program is distributed in the hope that it will be useful, but WITHOUT A
- * 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,
- * v.2.1 along with this distribution; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- *
- * (C) 2005-2006,
- * @author JBoss Inc.
- */
-package com.hp.mwtests.ts.jta.subordinate;
-
-import junit.framework.TestCase;
-
-import com.arjuna.ats.arjuna.coordinator.ActionManager;
-import com.arjuna.ats.arjuna.coordinator.TwoPhaseOutcome;
-import com.arjuna.ats.arjuna.common.Uid;
-import com.arjuna.ats.internal.jta.transaction.arjunacore.subordinate.TransactionImple;
-import com.arjuna.ats.internal.jta.transaction.arjunacore.jca.TxImporter;
-import com.arjuna.ats.internal.jta.transaction.arjunacore.jca.XATerminatorImple;
-import com.arjuna.ats.jta.xa.XidImple;
-
-import javax.transaction.RollbackException;
-import javax.transaction.xa.XAResource;
-import javax.transaction.xa.Xid;
-import javax.transaction.xa.XAException;
-import javax.resource.spi.XATerminator;
-
-public class SubordinateTestCase extends TestCase
-{
-	public void testCleanupCommit () throws Exception
-	{
-		for (int i = 0; i < 1000; i++)
-		{
-			final TransactionImple tm = new TransactionImple(0); // implicit begin
-
-			tm.doPrepare();
-			tm.doCommit();
-		}
-
-		assertEquals(ActionManager.manager().inflightTransactions().size(), 0);
-	}
-
-	public void testCleanupRollback () throws Exception
-	{
-		for (int i = 0; i < 1000; i++)
-		{
-			final TransactionImple tm = new TransactionImple(0); // implicit begin
-
-			tm.doRollback();
-		}
-
-		assertEquals(ActionManager.manager().inflightTransactions().size(), 0);
-	}
-
-	public void testCleanupSecondPhaseRollback () throws Exception
-	{
-		for (int i = 0; i < 1000; i++)
-		{
-			final TransactionImple tm = new TransactionImple(0); // implicit begin
-
-			tm.doPrepare();
-			tm.doRollback();
-		}
-
-		assertEquals(ActionManager.manager().inflightTransactions().size(), 0);
-	}
-
-	public void testCleanupOnePhaseCommit () throws Exception
-	{
-		for (int i = 0; i < 1000; i++)
-		{
-			final TransactionImple tm = new TransactionImple(0); // implicit begin
-
-			tm.doOnePhaseCommit();
-		}
-
-		assertEquals(ActionManager.manager().inflightTransactions().size(), 0);
-	}
-
-    /////////////
-
-    public void testOnePhaseCommitSync() throws Exception
-    {
-        final TransactionImple tm = new TransactionImple(0);
-        final TestSynchronization sync = new TestSynchronization();
-        tm.registerSynchronization(sync);
-        tm.doOnePhaseCommit();
-        assertTrue(sync.isBeforeCompletionDone());
-        assertTrue(sync.isAfterCompletionDone());
-        assertEquals(javax.transaction.Status.STATUS_COMMITTED, tm.getStatus());
-    }
-
-    public void testOnePhaseCommitSyncViaXATerminator() throws Exception
-    {
-        final Xid xid = new XidImple(new Uid());
-        final TransactionImple tm = TxImporter.importTransaction(xid);
-        final TestSynchronization sync = new TestSynchronization();
-        tm.registerSynchronization(sync);
-        final XATerminator xaTerminator = new XATerminatorImple();
-        xaTerminator.commit(xid, true);
-        assertTrue(sync.isBeforeCompletionDone());
-        assertTrue(sync.isAfterCompletionDone());
-        assertEquals(javax.transaction.Status.STATUS_COMMITTED, tm.getStatus());
-    }
-
-    public void testOnePhaseCommitSyncWithRollbackOnly() throws Exception
-    {
-        final TransactionImple tm = new TransactionImple(0);
-        final TestSynchronization sync = new TestSynchronization();
-        tm.registerSynchronization(sync);
-        tm.setRollbackOnly();
-        try {
-            tm.doOnePhaseCommit();
-            fail("did not get expected rollback exception");
-        } catch(RollbackException e) {
-            // expected - we tried to commit a rollbackonly tx.
-        }
-        assertFalse(sync.isBeforeCompletionDone());
-        assertTrue(sync.isAfterCompletionDone());
-        assertEquals(javax.transaction.Status.STATUS_ROLLEDBACK, tm.getStatus());
-    }
-
-    public void testOnePhaseCommitSyncWithRollbackOnlyViaXATerminator() throws Exception
-    {
-        final Xid xid = new XidImple(new Uid());
-        final TransactionImple tm = TxImporter.importTransaction(xid);
-        final TestSynchronization sync = new TestSynchronization();
-        tm.registerSynchronization(sync);
-        tm.setRollbackOnly();
-        final XATerminator xaTerminator = new XATerminatorImple();
-        try {
-            xaTerminator.commit(xid, true);
-            tm.doOnePhaseCommit();
-            fail("did not get expected rollback exception");
-        } catch(XAException e) {
-            assertEquals("javax.transaction.RollbackException", e.getCause().getClass().getName());
-            assertEquals(XAException.XA_RBROLLBACK, e.errorCode);
-            // expected - we tried to commit a rollbackonly tx.
-        }
-        assertFalse(sync.isBeforeCompletionDone());
-        assertTrue(sync.isAfterCompletionDone());
-        assertEquals(javax.transaction.Status.STATUS_ROLLEDBACK, tm.getStatus());
-    }
-
-    public void testRollbackSync() throws Exception
-    {
-        final TransactionImple tm = new TransactionImple(0);
-        final TestSynchronization sync = new TestSynchronization();
-        tm.registerSynchronization(sync);
-        tm.doRollback();
-        assertFalse(sync.isBeforeCompletionDone());
-        assertTrue(sync.isAfterCompletionDone());
-        assertEquals(javax.transaction.Status.STATUS_ROLLEDBACK, tm.getStatus());
-    }
-
-    public void testRollbackSyncViaXATerminator() throws Exception
-    {
-        final Xid xid = new XidImple(new Uid());
-        final TransactionImple tm = TxImporter.importTransaction(xid);
-        final TestSynchronization sync = new TestSynchronization();
-        tm.registerSynchronization(sync);
-        final XATerminator xaTerminator = new XATerminatorImple();
-        xaTerminator.rollback(xid);
-        assertFalse(sync.isBeforeCompletionDone());
-        assertTrue(sync.isAfterCompletionDone());
-        assertEquals(javax.transaction.Status.STATUS_ROLLEDBACK, tm.getStatus());
-    }
-
-    public void testTwoPhaseCommitSync() throws Exception
-    {
-        final TransactionImple tm = new TransactionImple(0);
-        final TestSynchronization sync = new TestSynchronization();
-        tm.registerSynchronization(sync);
-        assertEquals(TwoPhaseOutcome.PREPARE_READONLY, tm.doPrepare());
-        tm.doCommit();
-        assertTrue(sync.isBeforeCompletionDone());
-        assertTrue(sync.isAfterCompletionDone());
-        assertEquals(javax.transaction.Status.STATUS_COMMITTED, tm.getStatus());
-    }
-
-    public void testTwoPhaseCommitSyncViaXATerminator() throws Exception
-    {
-        final Xid xid = new XidImple(new Uid());
-        final TransactionImple tm = TxImporter.importTransaction(xid);
-        final TestSynchronization sync = new TestSynchronization();
-        tm.registerSynchronization(sync);
-        final XATerminator xaTerminator = new XATerminatorImple();
-        assertEquals(XAResource.XA_RDONLY, xaTerminator.prepare(xid));
-        // note that unlike the above test we don't call commit - the XA_RDONLY means its finished, per XA semantics.
-        assertTrue(sync.isBeforeCompletionDone());
-        assertTrue(sync.isAfterCompletionDone());
-        assertEquals(javax.transaction.Status.STATUS_COMMITTED, tm.getStatus());
-    }
-
-    public void testTwoPhaseCommitSyncWithXAOK() throws Exception
-    {
-        final TransactionImple tm = new TransactionImple(0);
-        final TestSynchronization sync = new TestSynchronization();
-        tm.registerSynchronization(sync);
-        final TestXAResource xaResource = new TestXAResource();
-        xaResource.setPrepareReturnValue(XAResource.XA_OK);
-        tm.enlistResource(xaResource);
-        assertEquals(TwoPhaseOutcome.PREPARE_OK, tm.doPrepare());
-        tm.doCommit();
-        assertTrue(sync.isBeforeCompletionDone());
-        assertTrue(sync.isAfterCompletionDone());
-        assertEquals(javax.transaction.Status.STATUS_COMMITTED, tm.getStatus());
-    }
-
-    public void testTwoPhaseCommitSyncWithXAOKViaXATerminator() throws Exception
-    {
-        final Xid xid = new XidImple(new Uid());
-        final TransactionImple tm = TxImporter.importTransaction(xid);
-        final TestSynchronization sync = new TestSynchronization();
-        tm.registerSynchronization(sync);
-        final TestXAResource xaResource = new TestXAResource();
-        xaResource.setPrepareReturnValue(XAResource.XA_OK);
-        tm.enlistResource(xaResource);
-        final XATerminator xaTerminator = new XATerminatorImple();
-        assertEquals(XAResource.XA_OK, xaTerminator.prepare(xid));
-        xaTerminator.commit(xid, false);
-        assertTrue(sync.isBeforeCompletionDone());
-        assertTrue(sync.isAfterCompletionDone());
-        assertEquals(javax.transaction.Status.STATUS_COMMITTED, tm.getStatus());
-    }
-
-    public void testTwoPhaseCommitSyncWithRollbackOnly() throws Exception
-    {
-        final TransactionImple tm = new TransactionImple(0);
-        final TestSynchronization sync = new TestSynchronization();
-        tm.registerSynchronization(sync);
-        tm.setRollbackOnly();
-        assertEquals(TwoPhaseOutcome.PREPARE_NOTOK, tm.doPrepare());
-        tm.doRollback();
-        assertFalse(sync.isBeforeCompletionDone());
-        assertTrue(sync.isAfterCompletionDone());
-        assertEquals(javax.transaction.Status.STATUS_ROLLEDBACK, tm.getStatus());
-    }
-
-    public void testTwoPhaseCommitSyncWithRollbackOnlyViaXATerminator() throws Exception
-    {
-        final Xid xid = new XidImple(new Uid());
-        final TransactionImple tm = TxImporter.importTransaction(xid);
-        final TestSynchronization sync = new TestSynchronization();
-        tm.registerSynchronization(sync);
-        tm.setRollbackOnly();
-        final XATerminator xaTerminator = new XATerminatorImple();
-
-        try {
-            xaTerminator.prepare(xid);
-        } catch(XAException e) {
-            assertEquals(XAException.XA_RBROLLBACK, e.errorCode);
-            // expected - we tried to prepare a rollbackonly tx.
-        }
-        // no need to call rollback - the XA_RBROLLBACK code indicates it's been done.
-        assertFalse(sync.isBeforeCompletionDone());
-        assertTrue(sync.isAfterCompletionDone());
-        assertEquals(javax.transaction.Status.STATUS_ROLLEDBACK, tm.getStatus());
-    }
-}

Copied: labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/SubordinateTestCase.java (from rev 24402, labs/jbosstm/branches/JBOSSTS_4_2_3_GA_CP/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/SubordinateTestCase.java)
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/SubordinateTestCase.java	                        (rev 0)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/SubordinateTestCase.java	2008-12-18 15:33:11 UTC (rev 24424)
@@ -0,0 +1,271 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * 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,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * (C) 2005-2006,
+ * @author JBoss Inc.
+ */
+package com.hp.mwtests.ts.jta.subordinate;
+
+import junit.framework.TestCase;
+
+import com.arjuna.ats.arjuna.coordinator.ActionManager;
+import com.arjuna.ats.arjuna.coordinator.TwoPhaseOutcome;
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.ats.internal.jta.transaction.arjunacore.subordinate.TransactionImple;
+import com.arjuna.ats.internal.jta.transaction.arjunacore.jca.TxImporter;
+import com.arjuna.ats.internal.jta.transaction.arjunacore.jca.XATerminatorImple;
+import com.arjuna.ats.jta.xa.XidImple;
+
+import javax.transaction.RollbackException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+import javax.transaction.xa.XAException;
+import javax.resource.spi.XATerminator;
+
+public class SubordinateTestCase extends TestCase
+{
+	public void testCleanupCommit () throws Exception
+	{
+		for (int i = 0; i < 1000; i++)
+		{
+			final TransactionImple tm = new TransactionImple(0); // implicit begin
+
+			tm.doPrepare();
+			tm.doCommit();
+		}
+
+		assertEquals(ActionManager.manager().inflightTransactions().size(), 0);
+	}
+
+	public void testCleanupRollback () throws Exception
+	{
+		for (int i = 0; i < 1000; i++)
+		{
+			final TransactionImple tm = new TransactionImple(0); // implicit begin
+
+			tm.doRollback();
+		}
+
+		assertEquals(ActionManager.manager().inflightTransactions().size(), 0);
+	}
+
+	public void testCleanupSecondPhaseRollback () throws Exception
+	{
+		for (int i = 0; i < 1000; i++)
+		{
+			final TransactionImple tm = new TransactionImple(0); // implicit begin
+
+			tm.doPrepare();
+			tm.doRollback();
+		}
+
+		assertEquals(ActionManager.manager().inflightTransactions().size(), 0);
+	}
+
+	public void testCleanupOnePhaseCommit () throws Exception
+	{
+		for (int i = 0; i < 1000; i++)
+		{
+			final TransactionImple tm = new TransactionImple(0); // implicit begin
+
+			tm.doOnePhaseCommit();
+		}
+
+		assertEquals(ActionManager.manager().inflightTransactions().size(), 0);
+	}
+
+    /////////////
+
+    public void testOnePhaseCommitSync() throws Exception
+    {
+        final TransactionImple tm = new TransactionImple(0);
+        final TestSynchronization sync = new TestSynchronization();
+        tm.registerSynchronization(sync);
+        tm.doOnePhaseCommit();
+        assertTrue(sync.isBeforeCompletionDone());
+        assertTrue(sync.isAfterCompletionDone());
+        assertEquals(javax.transaction.Status.STATUS_COMMITTED, tm.getStatus());
+    }
+
+    public void testOnePhaseCommitSyncViaXATerminator() throws Exception
+    {
+        final Xid xid = new XidImple(new Uid());
+        final TransactionImple tm = TxImporter.importTransaction(xid);
+        final TestSynchronization sync = new TestSynchronization();
+        tm.registerSynchronization(sync);
+        final XATerminator xaTerminator = new XATerminatorImple();
+        xaTerminator.commit(xid, true);
+        assertTrue(sync.isBeforeCompletionDone());
+        assertTrue(sync.isAfterCompletionDone());
+        assertEquals(javax.transaction.Status.STATUS_COMMITTED, tm.getStatus());
+    }
+
+    public void testOnePhaseCommitSyncWithRollbackOnly() throws Exception
+    {
+        final TransactionImple tm = new TransactionImple(0);
+        final TestSynchronization sync = new TestSynchronization();
+        tm.registerSynchronization(sync);
+        tm.setRollbackOnly();
+        try {
+            tm.doOnePhaseCommit();
+            fail("did not get expected rollback exception");
+        } catch(RollbackException e) {
+            // expected - we tried to commit a rollbackonly tx.
+        }
+        assertFalse(sync.isBeforeCompletionDone());
+        assertTrue(sync.isAfterCompletionDone());
+        assertEquals(javax.transaction.Status.STATUS_ROLLEDBACK, tm.getStatus());
+    }
+
+    public void testOnePhaseCommitSyncWithRollbackOnlyViaXATerminator() throws Exception
+    {
+        final Xid xid = new XidImple(new Uid());
+        final TransactionImple tm = TxImporter.importTransaction(xid);
+        final TestSynchronization sync = new TestSynchronization();
+        tm.registerSynchronization(sync);
+        tm.setRollbackOnly();
+        final XATerminator xaTerminator = new XATerminatorImple();
+        try {
+            xaTerminator.commit(xid, true);
+            tm.doOnePhaseCommit();
+            fail("did not get expected rollback exception");
+        } catch(XAException e) {
+            assertEquals("javax.transaction.RollbackException", e.getCause().getClass().getName());
+            assertEquals(XAException.XA_RBROLLBACK, e.errorCode);
+            // expected - we tried to commit a rollbackonly tx.
+        }
+        assertFalse(sync.isBeforeCompletionDone());
+        assertTrue(sync.isAfterCompletionDone());
+        assertEquals(javax.transaction.Status.STATUS_ROLLEDBACK, tm.getStatus());
+    }
+
+    public void testRollbackSync() throws Exception
+    {
+        final TransactionImple tm = new TransactionImple(0);
+        final TestSynchronization sync = new TestSynchronization();
+        tm.registerSynchronization(sync);
+        tm.doRollback();
+        assertFalse(sync.isBeforeCompletionDone());
+        assertTrue(sync.isAfterCompletionDone());
+        assertEquals(javax.transaction.Status.STATUS_ROLLEDBACK, tm.getStatus());
+    }
+
+    public void testRollbackSyncViaXATerminator() throws Exception
+    {
+        final Xid xid = new XidImple(new Uid());
+        final TransactionImple tm = TxImporter.importTransaction(xid);
+        final TestSynchronization sync = new TestSynchronization();
+        tm.registerSynchronization(sync);
+        final XATerminator xaTerminator = new XATerminatorImple();
+        xaTerminator.rollback(xid);
+        assertFalse(sync.isBeforeCompletionDone());
+        assertTrue(sync.isAfterCompletionDone());
+        assertEquals(javax.transaction.Status.STATUS_ROLLEDBACK, tm.getStatus());
+    }
+
+    public void testTwoPhaseCommitSync() throws Exception
+    {
+        final TransactionImple tm = new TransactionImple(0);
+        final TestSynchronization sync = new TestSynchronization();
+        tm.registerSynchronization(sync);
+        assertEquals(TwoPhaseOutcome.PREPARE_READONLY, tm.doPrepare());
+        tm.doCommit();
+        assertTrue(sync.isBeforeCompletionDone());
+        assertTrue(sync.isAfterCompletionDone());
+        assertEquals(javax.transaction.Status.STATUS_COMMITTED, tm.getStatus());
+    }
+
+    public void testTwoPhaseCommitSyncViaXATerminator() throws Exception
+    {
+        final Xid xid = new XidImple(new Uid());
+        final TransactionImple tm = TxImporter.importTransaction(xid);
+        final TestSynchronization sync = new TestSynchronization();
+        tm.registerSynchronization(sync);
+        final XATerminator xaTerminator = new XATerminatorImple();
+        assertEquals(XAResource.XA_RDONLY, xaTerminator.prepare(xid));
+        // note that unlike the above test we don't call commit - the XA_RDONLY means its finished, per XA semantics.
+        assertTrue(sync.isBeforeCompletionDone());
+        assertTrue(sync.isAfterCompletionDone());
+        assertEquals(javax.transaction.Status.STATUS_COMMITTED, tm.getStatus());
+    }
+
+    public void testTwoPhaseCommitSyncWithXAOK() throws Exception
+    {
+        final TransactionImple tm = new TransactionImple(0);
+        final TestSynchronization sync = new TestSynchronization();
+        tm.registerSynchronization(sync);
+        final TestXAResource xaResource = new TestXAResource();
+        xaResource.setPrepareReturnValue(XAResource.XA_OK);
+        tm.enlistResource(xaResource);
+        assertEquals(TwoPhaseOutcome.PREPARE_OK, tm.doPrepare());
+        tm.doCommit();
+        assertTrue(sync.isBeforeCompletionDone());
+        assertTrue(sync.isAfterCompletionDone());
+        assertEquals(javax.transaction.Status.STATUS_COMMITTED, tm.getStatus());
+    }
+
+    public void testTwoPhaseCommitSyncWithXAOKViaXATerminator() throws Exception
+    {
+        final Xid xid = new XidImple(new Uid());
+        final TransactionImple tm = TxImporter.importTransaction(xid);
+        final TestSynchronization sync = new TestSynchronization();
+        tm.registerSynchronization(sync);
+        final TestXAResource xaResource = new TestXAResource();
+        xaResource.setPrepareReturnValue(XAResource.XA_OK);
+        tm.enlistResource(xaResource);
+        final XATerminator xaTerminator = new XATerminatorImple();
+        assertEquals(XAResource.XA_OK, xaTerminator.prepare(xid));
+        xaTerminator.commit(xid, false);
+        assertTrue(sync.isBeforeCompletionDone());
+        assertTrue(sync.isAfterCompletionDone());
+        assertEquals(javax.transaction.Status.STATUS_COMMITTED, tm.getStatus());
+    }
+
+    public void testTwoPhaseCommitSyncWithRollbackOnly() throws Exception
+    {
+        final TransactionImple tm = new TransactionImple(0);
+        final TestSynchronization sync = new TestSynchronization();
+        tm.registerSynchronization(sync);
+        tm.setRollbackOnly();
+        assertEquals(TwoPhaseOutcome.PREPARE_NOTOK, tm.doPrepare());
+        tm.doRollback();
+        assertFalse(sync.isBeforeCompletionDone());
+        assertTrue(sync.isAfterCompletionDone());
+        assertEquals(javax.transaction.Status.STATUS_ROLLEDBACK, tm.getStatus());
+    }
+
+    public void testTwoPhaseCommitSyncWithRollbackOnlyViaXATerminator() throws Exception
+    {
+        final Xid xid = new XidImple(new Uid());
+        final TransactionImple tm = TxImporter.importTransaction(xid);
+        final TestSynchronization sync = new TestSynchronization();
+        tm.registerSynchronization(sync);
+        tm.setRollbackOnly();
+        final XATerminator xaTerminator = new XATerminatorImple();
+
+        try {
+            xaTerminator.prepare(xid);
+        } catch(XAException e) {
+            assertEquals(XAException.XA_RBROLLBACK, e.errorCode);
+            // expected - we tried to prepare a rollbackonly tx.
+        }
+        // no need to call rollback - the XA_RBROLLBACK code indicates it's been done.
+        assertFalse(sync.isBeforeCompletionDone());
+        assertTrue(sync.isAfterCompletionDone());
+        assertEquals(javax.transaction.Status.STATUS_ROLLEDBACK, tm.getStatus());
+    }
+}

Deleted: labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/TestSynchronization.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_GA_CP/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/TestSynchronization.java	2008-12-17 15:51:25 UTC (rev 24402)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/TestSynchronization.java	2008-12-18 15:33:11 UTC (rev 24424)
@@ -1,52 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags.
- * See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU Lesser General Public License, v. 2.1.
- * This program is distributed in the hope that it will be useful, but WITHOUT A
- * 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,
- * v.2.1 along with this distribution; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- *
- * (C) 2008,
- * @author JBoss Inc.
- */
-package com.hp.mwtests.ts.jta.subordinate;
-
-import javax.transaction.Synchronization;
-
-/**
- * Implementation of Synchronization for use in tx test cases.
- */
-public class TestSynchronization implements Synchronization
-{
-    private boolean beforeCompletionDone = false;
-    private boolean afterCompletionDone = false;
-
-    public boolean isBeforeCompletionDone()
-    {
-        return beforeCompletionDone;
-    }
-
-    public boolean isAfterCompletionDone()
-    {
-        return afterCompletionDone;
-    }
-
-    public void beforeCompletion() {
-        beforeCompletionDone = true;
-        System.out.println("TestSynchronization.beforeCompletion()");
-    }
-
-    public void afterCompletion(int i) {
-        afterCompletionDone = true;
-        System.out.println("TestSynchronization.afterCompletion("+i+")");
-    }
-}
\ No newline at end of file

Copied: labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/TestSynchronization.java (from rev 24402, labs/jbosstm/branches/JBOSSTS_4_2_3_GA_CP/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/TestSynchronization.java)
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/TestSynchronization.java	                        (rev 0)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/TestSynchronization.java	2008-12-18 15:33:11 UTC (rev 24424)
@@ -0,0 +1,52 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * 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,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * (C) 2008,
+ * @author JBoss Inc.
+ */
+package com.hp.mwtests.ts.jta.subordinate;
+
+import javax.transaction.Synchronization;
+
+/**
+ * Implementation of Synchronization for use in tx test cases.
+ */
+public class TestSynchronization implements Synchronization
+{
+    private boolean beforeCompletionDone = false;
+    private boolean afterCompletionDone = false;
+
+    public boolean isBeforeCompletionDone()
+    {
+        return beforeCompletionDone;
+    }
+
+    public boolean isAfterCompletionDone()
+    {
+        return afterCompletionDone;
+    }
+
+    public void beforeCompletion() {
+        beforeCompletionDone = true;
+        System.out.println("TestSynchronization.beforeCompletion()");
+    }
+
+    public void afterCompletion(int i) {
+        afterCompletionDone = true;
+        System.out.println("TestSynchronization.afterCompletion("+i+")");
+    }
+}
\ No newline at end of file

Deleted: labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/TestXAResource.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_GA_CP/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/TestXAResource.java	2008-12-17 15:51:25 UTC (rev 24402)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/TestXAResource.java	2008-12-18 15:33:11 UTC (rev 24424)
@@ -1,119 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags.
- * See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- * This copyrighted material is made available to anyone wishing to use,
- * modify, copy, or redistribute it subject to the terms and conditions
- * of the GNU Lesser General Public License, v. 2.1.
- * This program is distributed in the hope that it will be useful, but WITHOUT A
- * 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,
- * v.2.1 along with this distribution; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA  02110-1301, USA.
- *
- * (C) 2008,
- * @author JBoss Inc.
- */
-package com.hp.mwtests.ts.jta.subordinate;
-
-import javax.transaction.xa.XAResource;
-import javax.transaction.xa.Xid;
-import javax.transaction.xa.XAException;
-
-/**
- * Created by IntelliJ IDEA.
- * User: jhalli
- * Date: Apr 4, 2008
- * Time: 3:45:55 PM
- * To change this template use File | Settings | File Templates.
- */
-public class TestXAResource implements XAResource
-{
-    private int txTimeout;
-
-    private Xid currentXid;
-
-    private int prepareReturnValue = XAResource.XA_OK;
-
-    public int getPrepareReturnValue()
-    {
-        return prepareReturnValue;
-    }
-
-    public void setPrepareReturnValue(int prepareReturnValue)
-    {
-        this.prepareReturnValue = prepareReturnValue;
-    }
-
-    public void commit(Xid xid, boolean b) throws XAException
-    {
-        System.out.println("XAResourceImpl.commit(Xid="+xid+", b="+b+")");
-        if(!xid.equals(currentXid)) {
-            System.out.println("XAResourceImpl.commit - wrong Xid!");
-        }
-
-        currentXid = null;
-    }
-
-    public void end(Xid xid, int i) throws XAException {
-        System.out.println("XAResourceImpl.end(Xid="+xid+", b="+i+")");
-    }
-
-    public void forget(Xid xid) throws XAException {
-        System.out.println("XAResourceImpl.forget(Xid="+xid+")");
-        if(!xid.equals(currentXid)) {
-            System.out.println("XAResourceImpl.forget - wrong Xid!");
-        }
-        currentXid = null;
-    }
-
-    public int getTransactionTimeout() throws XAException {
-        System.out.println("XAResourceImpl.getTransactionTimeout() [returning "+txTimeout+"]");
-        return txTimeout;
-    }
-
-    public boolean isSameRM(XAResource xaResource) throws XAException {
-        System.out.println("XAResourceImpl.isSameRM(xaResource="+xaResource+")");
-        return false;
-    }
-
-    public int prepare(Xid xid) throws XAException {
-        System.out.println("XAResourceImpl.prepare(Xid="+xid+") returning "+prepareReturnValue);
-        return prepareReturnValue;
-    }
-
-    public Xid[] recover(int i) throws XAException {
-        System.out.println("XAResourceImpl.recover(i="+i+")");
-        return new Xid[0];
-    }
-
-    public void rollback(Xid xid) throws XAException {
-        System.out.println("XAResourceImpl.rollback(Xid="+xid+")");
-        if(!xid.equals(currentXid)) {
-            System.out.println("XAResourceImpl.rollback - wrong Xid!");
-        }
-        currentXid = null;
-    }
-
-    public boolean setTransactionTimeout(int i) throws XAException {
-        System.out.println("XAResourceImpl.setTransactionTimeout(i="+i+")");
-        txTimeout= i;
-        return true;
-    }
-
-    public void start(Xid xid, int i) throws XAException {
-        System.out.println("XAResourceImpl.start(Xid="+xid+", i="+i+")");
-        if(currentXid != null) {
-            System.out.println("XAResourceImpl.start - wrong Xid!");
-        }
-        currentXid = xid;
-    }
-
-    public String toString() {
-        return new String("XAResourceImple("+txTimeout+", "+currentXid+")");
-    }
-}

Copied: labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/TestXAResource.java (from rev 24402, labs/jbosstm/branches/JBOSSTS_4_2_3_GA_CP/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/TestXAResource.java)
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/TestXAResource.java	                        (rev 0)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_SP5_JBTM-423_JBTM-425_JBTM-427_JBTM-428_JBTM-429_JBTM-430_JBTM-243/ArjunaJTA/jta/tests/classes/com/hp/mwtests/ts/jta/subordinate/TestXAResource.java	2008-12-18 15:33:11 UTC (rev 24424)
@@ -0,0 +1,119 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * 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,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * (C) 2008,
+ * @author JBoss Inc.
+ */
+package com.hp.mwtests.ts.jta.subordinate;
+
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+import javax.transaction.xa.XAException;
+
+/**
+ * Created by IntelliJ IDEA.
+ * User: jhalli
+ * Date: Apr 4, 2008
+ * Time: 3:45:55 PM
+ * To change this template use File | Settings | File Templates.
+ */
+public class TestXAResource implements XAResource
+{
+    private int txTimeout;
+
+    private Xid currentXid;
+
+    private int prepareReturnValue = XAResource.XA_OK;
+
+    public int getPrepareReturnValue()
+    {
+        return prepareReturnValue;
+    }
+
+    public void setPrepareReturnValue(int prepareReturnValue)
+    {
+        this.prepareReturnValue = prepareReturnValue;
+    }
+
+    public void commit(Xid xid, boolean b) throws XAException
+    {
+        System.out.println("XAResourceImpl.commit(Xid="+xid+", b="+b+")");
+        if(!xid.equals(currentXid)) {
+            System.out.println("XAResourceImpl.commit - wrong Xid!");
+        }
+
+        currentXid = null;
+    }
+
+    public void end(Xid xid, int i) throws XAException {
+        System.out.println("XAResourceImpl.end(Xid="+xid+", b="+i+")");
+    }
+
+    public void forget(Xid xid) throws XAException {
+        System.out.println("XAResourceImpl.forget(Xid="+xid+")");
+        if(!xid.equals(currentXid)) {
+            System.out.println("XAResourceImpl.forget - wrong Xid!");
+        }
+        currentXid = null;
+    }
+
+    public int getTransactionTimeout() throws XAException {
+        System.out.println("XAResourceImpl.getTransactionTimeout() [returning "+txTimeout+"]");
+        return txTimeout;
+    }
+
+    public boolean isSameRM(XAResource xaResource) throws XAException {
+        System.out.println("XAResourceImpl.isSameRM(xaResource="+xaResource+")");
+        return false;
+    }
+
+    public int prepare(Xid xid) throws XAException {
+        System.out.println("XAResourceImpl.prepare(Xid="+xid+") returning "+prepareReturnValue);
+        return prepareReturnValue;
+    }
+
+    public Xid[] recover(int i) throws XAException {
+        System.out.println("XAResourceImpl.recover(i="+i+")");
+        return new Xid[0];
+    }
+
+    public void rollback(Xid xid) throws XAException {
+        System.out.println("XAResourceImpl.rollback(Xid="+xid+")");
+        if(!xid.equals(currentXid)) {
+            System.out.println("XAResourceImpl.rollback - wrong Xid!");
+        }
+        currentXid = null;
+    }
+
+    public boolean setTransactionTimeout(int i) throws XAException {
+        System.out.println("XAResourceImpl.setTransactionTimeout(i="+i+")");
+        txTimeout= i;
+        return true;
+    }
+
+    public void start(Xid xid, int i) throws XAException {
+        System.out.println("XAResourceImpl.start(Xid="+xid+", i="+i+")");
+        if(currentXid != null) {
+            System.out.println("XAResourceImpl.start - wrong Xid!");
+        }
+        currentXid = xid;
+    }
+
+    public String toString() {
+        return new String("XAResourceImple("+txTimeout+", "+currentXid+")");
+    }
+}




More information about the jboss-svn-commits mailing list