[jboss-svn-commits] JBL Code SVN: r31955 - in labs/jbosstm/trunk/txbridge: demo/dd and 5 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Fri Mar 5 06:17:51 EST 2010


Author: jhalliday
Date: 2010-03-05 06:17:50 -0500 (Fri, 05 Mar 2010)
New Revision: 31955

Added:
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/BridgeDurableParticipant.java
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/BridgeVolatileParticipant.java
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/InboundBridge.java
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/InboundBridgeManager.java
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/InboundBridgeRecoveryManager.java
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/JaxWSTxInboundBridgeHandler.java
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/BridgeSynchronization.java
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/BridgeXAResource.java
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/JaxWSTxOutboundBridgeHandler.java
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/OutboundBridge.java
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/OutboundBridgeManager.java
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/OutboundBridgeRecoveryManager.java
Removed:
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeDurableParticipant.java
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeRecoveryManager.java
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeSynchronization.java
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeVolatileParticipant.java
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeXAResource.java
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/InboundBridge.java
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/InboundBridgeManager.java
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/JaxWSTxInboundBridgeHandler.java
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/JaxWSTxOutboundBridgeHandler.java
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/OutboundBridge.java
   labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/OutboundBridgeManager.java
Modified:
   labs/jbosstm/trunk/txbridge/META-INF/jboss-beans.xml
   labs/jbosstm/trunk/txbridge/demo/dd/jaxws-handlers-client.xml
   labs/jbosstm/trunk/txbridge/demo/dd/jaxws-handlers-server.xml
   labs/jbosstm/trunk/txbridge/docs/TransactionBridgingGuide.odt
   labs/jbosstm/trunk/txbridge/docs/TransactionBridgingGuide.pdf
   labs/jbosstm/trunk/txbridge/tests/dd/jaxws-handlers-client.xml
   labs/jbosstm/trunk/txbridge/tests/dd/jaxws-handlers-server.xml
Log:
Refactor txbridge to divide inbound and outbound bridges. And initial structure for outbound bridge crash rec. JBTM-44


Modified: labs/jbosstm/trunk/txbridge/META-INF/jboss-beans.xml
===================================================================
--- labs/jbosstm/trunk/txbridge/META-INF/jboss-beans.xml	2010-03-05 05:45:20 UTC (rev 31954)
+++ labs/jbosstm/trunk/txbridge/META-INF/jboss-beans.xml	2010-03-05 11:17:50 UTC (rev 31955)
@@ -23,7 +23,7 @@
 
 <deployment xmlns="urn:jboss:bean-deployer:2.0">
 
-    <bean name="TxBridge" class="org.jboss.jbossts.txbridge.BridgeRecoveryManager">
+    <bean name="TxBridgeInboundRecoveryManager" class="org.jboss.jbossts.txbridge.inbound.InboundBridgeRecoveryManager">
 
         <demand state="PreInstall">jboss.xts:service=XTSService</demand>
 
@@ -33,5 +33,15 @@
 
     </bean>
 
+    <bean name="TxBridgeOutboundRecoveryManager" class="org.jboss.jbossts.txbridge.outbound.OutboundBridgeRecoveryManager">
+
+        <demand state="PreInstall">jboss.xts:service=XTSService</demand>
+
+        <depends>jboss.xts:service=XTSService</depends>
+
+        <depends>jboss:service=TransactionManager</depends>
+
+    </bean>
+
 </deployment>
 

Modified: labs/jbosstm/trunk/txbridge/demo/dd/jaxws-handlers-client.xml
===================================================================
--- labs/jbosstm/trunk/txbridge/demo/dd/jaxws-handlers-client.xml	2010-03-05 05:45:20 UTC (rev 31954)
+++ labs/jbosstm/trunk/txbridge/demo/dd/jaxws-handlers-client.xml	2010-03-05 11:17:50 UTC (rev 31955)
@@ -37,7 +37,7 @@
 
 		<handler>
 			<handler-name>TransactionBridgeHandler</handler-name>
-			<handler-class>org.jboss.jbossts.txbridge.JaxWSTxOutboundBridgeHandler</handler-class>
+			<handler-class>org.jboss.jbossts.txbridge.outbound.JaxWSTxOutboundBridgeHandler</handler-class>
 		</handler>
 
 		<handler>

Modified: labs/jbosstm/trunk/txbridge/demo/dd/jaxws-handlers-server.xml
===================================================================
--- labs/jbosstm/trunk/txbridge/demo/dd/jaxws-handlers-server.xml	2010-03-05 05:45:20 UTC (rev 31954)
+++ labs/jbosstm/trunk/txbridge/demo/dd/jaxws-handlers-server.xml	2010-03-05 11:17:50 UTC (rev 31955)
@@ -37,7 +37,7 @@
 
         <handler>
             <handler-name>TransactionBridgeHandler</handler-name>
-            <handler-class>org.jboss.jbossts.txbridge.JaxWSTxInboundBridgeHandler</handler-class>
+            <handler-class>org.jboss.jbossts.txbridge.inbound.JaxWSTxInboundBridgeHandler</handler-class>
         </handler>
 
 		<handler>

Modified: labs/jbosstm/trunk/txbridge/docs/TransactionBridgingGuide.odt
===================================================================
(Binary files differ)

Modified: labs/jbosstm/trunk/txbridge/docs/TransactionBridgingGuide.pdf
===================================================================
(Binary files differ)

Deleted: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeDurableParticipant.java
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeDurableParticipant.java	2010-03-05 05:45:20 UTC (rev 31954)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeDurableParticipant.java	2010-03-05 11:17:50 UTC (rev 31955)
@@ -1,282 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- *
- * (C) 2007, 2009 @author JBoss Inc
- */
-package org.jboss.jbossts.txbridge;
-
-import com.arjuna.wst.*;
-import com.arjuna.ats.arjuna.common.Uid;
-import com.arjuna.ats.internal.jta.transaction.arjunacore.jca.SubordinationManager;
-import org.apache.log4j.Logger;
-
-import javax.transaction.xa.Xid;
-import javax.transaction.xa.XAException;
-import javax.transaction.xa.XAResource;
-
-import javax.resource.spi.XATerminator;
-
-import java.io.Serializable;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-
-/**
- * Provides method call mapping between WS-AT Durable Participant interface
- * and an underlying JTA subtransaction coordinator.
- *
- * @author jonathan.halliday at redhat.com, 2007-04-30
- */
-public class BridgeDurableParticipant implements Durable2PCParticipant, Serializable
-{
-	private static final Logger log = Logger.getLogger(BridgeDurableParticipant.class);
-
-    /*
-     * Uniq String used to prefix ids at participant registration,
-     * so that the recovery module can identify relevant instances.
-     */
-    public static final String TYPE_IDENTIFIER = "BridgeDurableParticipant_";
-
-    /*
-     * Uniq (well, hopefully) formatId so we can distinguish our own Xids.
-     */
-    public static final int XARESOURCE_FORMAT_ID = 131080;
-
-	private transient volatile XATerminator xaTerminator;
-
-    private transient volatile String externalTxId;
-
-    private transient volatile boolean isAwaitingRecovery = false;
-
-    static final long serialVersionUID = -5739871936627778072L;
-
-    // Xid not guaranteed Serializable by spec, but our XidImple happens to be
-	private volatile Xid xid;
-
-    // Id needed for recovery of the subordinate tx. Uids are likewise Serializable.
-    private volatile Uid subordinateTransactionId;
-
-    /**
-     * Create a new WS-AT Durable Participant which wraps the subordinate XA tx terminator.
-     *
-     * @param externalTxId the WS-AT Tx identifier
-     * @param xid the Xid to use when driving the subordinate XA transaction.
-     */
-	BridgeDurableParticipant(String externalTxId, Xid xid)
-    {
-		log.trace("BridgeDurableParticipant(TxId="+externalTxId+", Xid="+xid+")");
-
-        this.xid = xid;
-        this.externalTxId = externalTxId;
-		xaTerminator = SubordinationManager.getXATerminator();
-	}
-
-    /**
-     * Serialization hook. Gathers and writes information needed for transaction recovery.
-     *
-     * @param out the strean to which the object state is serialized.
-     * @throws IOException if serialization fails.
-     */
-    private void writeObject(ObjectOutputStream out) throws IOException
-    {
-        log.trace("writeObject() for Xid="+xid);
-
-        // we need to preserve the Uid of the underlying SubordinateTx, as it's required
-        // to get a handle on it again during recovery, Using the xid wont work,
-        // although we do need to serialize that too for use after recovery.
-        try
-        {
-            subordinateTransactionId = SubordinationManager.getTransactionImporter().getImportedTransaction(xid).get_uid();
-        }
-        catch(XAException xaException)
-        {
-            log.error("Unable to get subordinate transaction id", xaException);
-            IOException ioException = new IOException("Unable to serialize");
-            ioException.initCause(xaException);
-            throw ioException;
-        }
-
-        //out.defaultWriteObject();
-        out.writeObject(xid);
-        out.writeObject(subordinateTransactionId);
-    }
-
-    /**
-     * Deserialization hook. Unpacks transaction recovery information and uses it to
-     * recover the subordinate transaction.
-     *
-     * @param in the stream from which to unpack the object state.
-     * @throws IOException if deserialzation and recovery fail.
-     * @throws ClassNotFoundException if deserialzation fails.
-     */
-    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
-    {
-        log.trace("readObject()");
-
-        //in.defaultReadObject();
-        xid = (Xid)in.readObject();
-        subordinateTransactionId = (Uid)in.readObject();
-
-        isAwaitingRecovery = true;
-
-        xaTerminator = SubordinationManager.getXATerminator();
-
-        try
-        {
-            SubordinationManager.getTransactionImporter().recoverTransaction(subordinateTransactionId);
-        }
-        catch(XAException xaException)
-        {
-            log.error("Unable to recover subordinate transaction id="+subordinateTransactionId, xaException);
-            IOException ioException = new IOException("unable to deserialize");
-            ioException.initCause(xaException);
-            throw ioException;
-        }
-    }
-
-    /**
-     * Perform any work necessary to allow it to either commit or rollback
-     * the work performed by the Web service under the scope of the
-     * transaction. The implementation is free to do whatever it needs to in
-     * order to fulfill the implicit contract between it and the coordinator.
-     *
-     * @return an indication of whether it can prepare or not.
-     * @see com.arjuna.wst.Vote
-     */
-	public Vote prepare() throws WrongStateException, SystemException
-	{
-		log.trace("prepare(Xid="+xid+")");
-
-		try
-        {
-			// XAResource.XA_OK, XAResource.XA_RDONLY or exception.  if RDONLY, don't call commit
-			int result = xaTerminator.prepare(xid);
-			if(result == XAResource.XA_OK)
-            {
-				log.debug("prepare on Xid="+xid+" returning Prepared");
-				return new Prepared();
-			}
-            else
-            {
-                cleanupRefs();
-                log.debug("prepare on Xid="+xid+" returning ReadOnly");
-				return new ReadOnly();
-			}
-
-		}
-        catch(XAException e)
-        {
-            cleanupRefs();
-            log.warn("prepare on Xid="+xid+" returning Aborted", e);
-			return new Aborted();
-		}
-    }
-
-    /**
-     * The participant should make permanent the work that it controls.
-	 *
-     * @throws WrongStateException
-     * @throws SystemException
-     */
-    public void commit() throws WrongStateException, SystemException
-    {
-		log.trace("commit(Xid="+xid+")");
-
-		try
-		{
-			xaTerminator.commit(xid, false);
-			log.debug("commit on Xid="+xid+" OK");
-		}
-		catch (XAException e)
-		{
-			log.error("commit on Xid="+xid+" failed", e);
-		}
-        finally
-        {
-            cleanupRefs();
-        }
-    }
-
-    /**
-     * The participant should undo the work that it controls. The participant
-     * will then return an indication of whether or not it succeeded..
-     *
-     * @throws WrongStateException
-     * @throws SystemException
-     */
-    public void rollback() throws WrongStateException, SystemException
-    {
-		log.trace("rollback(Xid="+xid+")");
-
-		try
-		{
-			xaTerminator.rollback(xid);
-			log.debug("rollback on Xid="+xid+" OK");
-		}
-		catch (XAException e)
-		{
-			log.error("rollback on Xid="+xid+" failed", e);
-		}
-        finally
-        {
-            cleanupRefs();
-        }
-    }
-
-    /**
-     * During recovery the participant can enquire as to the status of the
-     * transaction it was registered with. If that transaction is no longer
-     * available (has rolled back) then this operation will be invoked by the
-     * coordination service.
-     */
-	public void unknown() throws SystemException
-    {
-		log.trace("unknown(Xid="+xid+"): NOT IMPLEMENTED");
-    }
-
-    /**
-     * During recovery the participant can enquire as to the status of the
-     * transaction it was registered with. If an error occurs (e.g., the
-     * transaction service is unavailable) then this operation will be invoked.
-     */
-	public void error() throws SystemException
-    {
-		log.trace("error(Xid="+xid+"): NOT IMPLEMENTED");
-    }
-
-    public boolean isAwaitingRecovery() {
-        return isAwaitingRecovery;
-    }
-
-    public Xid getXid()
-    {
-        return xid;
-    }
-
-    private void cleanupRefs()
-    {
-        log.trace("cleanupRefs()");
-
-        InboundBridgeManager.removeMapping(externalTxId);
-        isAwaitingRecovery = false;
-    }
-}
-

Deleted: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeRecoveryManager.java
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeRecoveryManager.java	2010-03-05 05:45:20 UTC (rev 31954)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeRecoveryManager.java	2010-03-05 11:17:50 UTC (rev 31955)
@@ -1,263 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- *
- * (C) 2009 @author Red Hat Middleware LLC
- */
-package org.jboss.jbossts.txbridge;
-
-import com.arjuna.ats.arjuna.recovery.RecoveryManager;
-import com.arjuna.ats.arjuna.recovery.RecoveryModule;
-import com.arjuna.ats.internal.jta.recovery.arjunacore.XARecoveryModule;
-import com.arjuna.ats.internal.jta.transaction.arjunacore.jca.SubordinationManager;
-import com.arjuna.ats.jta.recovery.XAResourceOrphanFilter;
-import org.apache.log4j.Logger;
-import org.jboss.jbossts.xts.recovery.participant.at.XTSATRecoveryModule;
-import org.jboss.jbossts.xts.recovery.participant.at.XTSATRecoveryManager;
-import com.arjuna.wst.Durable2PCParticipant;
-
-import javax.resource.spi.XATerminator;
-import javax.transaction.xa.XAException;
-import javax.transaction.xa.XAResource;
-import javax.transaction.xa.Xid;
-import java.io.ObjectInputStream;
-import java.util.*;
-
-/**
- * Integrates with JBossAS MC lifecycle and JBossTS recovery manager to provide recovery services.
- *
- * @author jonathan.halliday at redhat.com, 2009-02-10
- */
-public class BridgeRecoveryManager implements XTSATRecoveryModule, RecoveryModule, XAResourceOrphanFilter
-{
-    private static final Logger log = Logger.getLogger(BridgeRecoveryManager.class);
-
-    private final XTSATRecoveryManager xtsATRecoveryManager = XTSATRecoveryManager.getRecoveryManager();
-    private final RecoveryManager acRecoveryManager = RecoveryManager.manager();
-    private final XATerminator xaTerminator = SubordinationManager.getXATerminator();
-
-    private final List<BridgeDurableParticipant> participantsAwaitingRecovery =
-            Collections.synchronizedList(new LinkedList<BridgeDurableParticipant>());
-    private volatile boolean orphanedXAResourcesAreIdentifiable = false;
-
-    /**
-     * MC lifecycle callback, used to register the recovery module with the transaction manager.
-     */
-    public void start()
-    {
-        log.info("BridgeRecoveryManager starting");
-
-        xtsATRecoveryManager.registerRecoveryModule(this);
-        acRecoveryManager.addModule(this);
-
-        XARecoveryModule xaRecoveryModule = getXARecoveryModule();
-        xaRecoveryModule.addXAResourceOrphanFilter(this);
-    }
-
-    private XARecoveryModule getXARecoveryModule()
-    {
-        XARecoveryModule xaRecoveryModule = null;
-        for(RecoveryModule recoveryModule : ((Vector<RecoveryModule>)acRecoveryManager.getModules())) {
-            if(recoveryModule instanceof XARecoveryModule) {
-                xaRecoveryModule = (XARecoveryModule)recoveryModule;
-                break;
-            }
-        }
-
-        if(xaRecoveryModule == null) {
-            throw new IllegalStateException("no XARecoveryModule found");
-        }
-        return xaRecoveryModule;
-    }
-
-    /**
-     * MC lifecycle callback, used to unregister the recovery module from the transaction manager.
-     */
-    public void stop()
-    {
-        log.info("BridgeRecoveryManager stopping");
-
-        xtsATRecoveryManager.unregisterRecoveryModule(this);
-        acRecoveryManager.removeModule(this, false);
-        
-        XARecoveryModule xaRecoveryModule = getXARecoveryModule();
-        xaRecoveryModule.removeXAResourceOrphanFilter(this);
-    }
-
-    /**
-     * Called during recovery processing to allow an application to identify a participant id
-     * belonging to one of its participants and recreate the participant by deserializing
-     * it from the supplied object input stream. n.b. this is only appropriate in case the
-     * participant was originally saved using serialization.
-     *
-     * @param id the id used when the participant was created
-     * @param objectInputStream a stream from which the application should deserialize the participant
-     * if it recognises that the id belongs to the module's application
-     * @return the deserialized Participant object
-     * @throws Exception if an error occurs deserializing the durable participant
-     */
-    @Override
-    public Durable2PCParticipant deserialize(String id, ObjectInputStream objectInputStream) throws Exception
-    {
-        log.trace("deserialize(id="+id+")");
-
-        if(id.startsWith(BridgeDurableParticipant.TYPE_IDENTIFIER))
-        {
-            Object participant = objectInputStream.readObject();
-            BridgeDurableParticipant bridgeDurableParticipant = (BridgeDurableParticipant)participant;
-            participantsAwaitingRecovery.add(bridgeDurableParticipant);
-            return bridgeDurableParticipant;
-        }
-        else
-        {
-            return null;
-        }
-    }
-
-    /**
-     * Unused recovery callback. We use serialization instead, so this method will always throw an exception if called.
-     */
-    @Override
-    public Durable2PCParticipant recreate(String s, byte[] bytes) throws Exception
-    {
-        throw new Exception("recreation not supported - should use deserialization instead.");
-    }
-
-    /**
-     * Called by the RecoveryManager at start up, and then
-     * PERIODIC_RECOVERY_PERIOD seconds after the completion, for all RecoveryModules,
-     * of the second pass
-     */
-    @Override
-    public void periodicWorkFirstPass()
-    {
-        log.trace("periodicWorkFirstPass()");
-    }
-
-    /**
-     * Called by the RecoveryManager RECOVERY_BACKOFF_PERIOD seconds
-     * after the completion of the first pass
-     */
-    @Override
-    public void periodicWorkSecondPass()
-    {
-        log.trace("periodicWorkSecondPass()");
-
-        cleanupRecoveredParticipants();
-
-        // the XTS recovery module is registered and hence run before us. Therefore by the time we get here
-        // we know deserialize has been called for any BridgeDurableParticipant for which a log exists.
-        orphanedXAResourcesAreIdentifiable = true;
-
-
-        List<Xid> indoubtSubordinates = getIndoubtSubordinates();
-        for(Xid xid : indoubtSubordinates) {
-            if(checkXid(xid) == XAResourceOrphanFilter.Vote.ROLLBACK) {
-                log.trace("rolling back orphaned subordinate tx "+xid);
-                try {
-                    xaTerminator.rollback(xid);
-                } catch(XAException e) {
-                    log.error("problem rolling back orphaned subordinate tx "+xid, e);
-                }
-            }
-        }
-
-    }
-
-    /**
-     * Run a recovery scan to identify any in-doubt JTA subordinates.
-     *
-     * @return a possibly empty but non-null list of xids corresponding to outstanding
-     * JTA subordinate transactions owned by the txbridge.
-     */
-    private List<Xid> getIndoubtSubordinates()
-    {
-        log.trace("getIndoubtSubordinates()");
-
-        Xid[] allSubordinateXids = null;
-        try {
-            allSubordinateXids = xaTerminator.recover(XAResource.TMSTARTRSCAN);
-        } catch(XAException e) {
-            log.error("Problem whilst scanning for in-doubt subordinate transactions", e);
-        } finally {
-            try {
-                xaTerminator.recover(XAResource.TMENDRSCAN);
-            } catch(XAException e) {}
-        }
-
-        LinkedList<Xid> mySubordinateXids = new LinkedList<Xid>();
-
-        if(allSubordinateXids == null) {
-            return mySubordinateXids;
-        }
-
-        for(Xid xid : allSubordinateXids) {
-            if(xid.getFormatId() == BridgeDurableParticipant.XARESOURCE_FORMAT_ID) {
-                mySubordinateXids.add(xid);
-                log.trace("in-doubt subordinate, xid: "+xid);
-            }
-        }
-
-        return mySubordinateXids;
-    }
-
-    /**
-     * Release any BridgeDurableParticipant instances that have been driven
-     * through to completion by their parent XTS transaction.
-     */
-    private void cleanupRecoveredParticipants()
-    {
-        log.trace("cleanupRecoveredParticipants()");
-
-        synchronized(participantsAwaitingRecovery) {
-            Iterator<BridgeDurableParticipant> iter = participantsAwaitingRecovery.iterator();
-            while(iter.hasNext()) {
-                BridgeDurableParticipant participant = iter.next();
-                if(!participant.isAwaitingRecovery()) {
-                    iter.remove();
-                }
-            }
-        }
-    }
-
-    @Override
-    public Vote checkXid(Xid xid)
-    {
-        log.trace("checkXid("+xid+")");
-
-        if(xid.getFormatId() != BridgeDurableParticipant.XARESOURCE_FORMAT_ID) {
-            return Vote.ABSTAIN;
-        }
-
-        if(!orphanedXAResourcesAreIdentifiable) {
-            return Vote.LEAVE_ALONE;
-        }
-
-        synchronized(participantsAwaitingRecovery) {
-            for(BridgeDurableParticipant participant : participantsAwaitingRecovery) {
-                if(participant.getXid().equals(xid)) {
-                    return Vote.LEAVE_ALONE;
-                }
-            }
-        }
-
-        return Vote.ROLLBACK;
-    }
-}

Deleted: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeSynchronization.java
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeSynchronization.java	2010-03-05 05:45:20 UTC (rev 31954)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeSynchronization.java	2010-03-05 11:17:50 UTC (rev 31955)
@@ -1,90 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- *
- * (C) 2009 @author JBoss Inc
- */
-package org.jboss.jbossts.txbridge;
-
-import org.apache.log4j.Logger;
-import org.jboss.jbossts.xts.bridge.at.BridgeWrapper;
-
-import javax.transaction.Synchronization;
-import javax.transaction.Status;
-
-import com.arjuna.ats.jta.utils.JTAHelper;
-
-/**
- * Provides method call mapping between JTA parent coordinator and WS-AT subordinate transaction.
- *
- * @author jonathan.halliday at redhat.com, 2009-06-01
- */
-public class BridgeSynchronization implements Synchronization
-{
-    private static final Logger log = Logger.getLogger(BridgeSynchronization.class);
-
-    private final BridgeWrapper bridgeWrapper;
-
-    public BridgeSynchronization(BridgeWrapper bridgeWrapper)
-    {
-        log.trace("BridgeSynchronization(BridgeWrapper="+bridgeWrapper+")");
-
-        this.bridgeWrapper = bridgeWrapper;
-    }
-
-    /**
-     * The beforeCompletion method is called by the transaction manager prior to the start of the two-phase transaction commit process.
-     */
-    public void beforeCompletion()
-    {
-        log.trace("beforeCompletion()");
-
-        if(!bridgeWrapper.prepareVolatile())
-        {
-            // JTA does not explicitly provide for beforeCompletion signalling problems, but in
-            // our impl the engine will set the tx rollbackOnly if beforeCompletion throw an exception
-            // Note com.arjuna.ats.jta.TransactionManager.getTransaction().setRollbackOnly may also work.
-            throw new RuntimeException("BridgeWrapper.prepareVolatile() returned false");
-        }
-    }
-
-    /**
-     * This method is called by the transaction manager after the transaction is committed or rolled back.
-     *
-     * @param status the javax.transaction.Status representing the tx outcome.
-     */
-    public void afterCompletion(int status)
-    {
-        log.trace("afterCompletion(status="+status+"/"+ JTAHelper.stringForm(status)+")");
-
-        switch(status)
-        {
-            case Status.STATUS_COMMITTED:
-                bridgeWrapper.commitVolatile();
-                break;
-            case Status.STATUS_ROLLEDBACK:
-                bridgeWrapper.rollbackVolatile();
-                break;
-            default:
-                log.warn("unexpected Status "+status+", treating as ROLLEDBACK");
-                bridgeWrapper.rollbackVolatile();
-        }
-    }
-}

Deleted: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeVolatileParticipant.java
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeVolatileParticipant.java	2010-03-05 05:45:20 UTC (rev 31954)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeVolatileParticipant.java	2010-03-05 11:17:50 UTC (rev 31955)
@@ -1,182 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- *
- * (C) 2009 @author JBoss Inc
- */
-package org.jboss.jbossts.txbridge;
-
-import com.arjuna.wst.*;
-import com.arjuna.ats.internal.jta.resources.spi.XATerminatorExtensions;
-import com.arjuna.ats.internal.jta.transaction.arjunacore.jca.SubordinationManager;
-import com.arjuna.ats.jta.utils.JTAHelper;
-import org.apache.log4j.Logger;
-
-import javax.transaction.xa.Xid;
-import javax.transaction.Status;
-
-/**
- * Provides method call mapping between WS-AT Volatile Participant interface
- * and an underlying JTA subtransaction coordinator.
- *
- * @author jonathan.halliday at redhat.com, 2009-06-01
- */
-public class BridgeVolatileParticipant implements Volatile2PCParticipant
-{
-    private static final Logger log = Logger.getLogger(BridgeVolatileParticipant.class);
-
-    // no standard interface for driving Synchronization phases separately
-    // in JCA, so we have to use proprietary API.
-    private final XATerminatorExtensions xaTerminatorExtensions;
-
-    private final String externalTxId;
-
-    private final Xid xid;
-
-    /**
-     * Create a new WS-AT Volatile Participant which wraps the subordinate XA tx terminator.
-     *
-     * @param externalTxId the WS-AT Tx identifier
-     * @param xid the Xid to use when driving the subordinate XA transaction.
-     */
-    BridgeVolatileParticipant(String externalTxId, Xid xid)
-    {
-		log.trace("BridgeVolatileParticipant(TxId="+externalTxId+", Xid="+xid+")");
-
-        this.xid = xid;
-        this.externalTxId = externalTxId;
-        this.xaTerminatorExtensions = (XATerminatorExtensions)SubordinationManager.getXATerminator();
-    }
-
-    /**
-     * Perform beforeCompletion activities such as flushing cached state to stable store.
-     *
-     * @return an indication of whether it can prepare or not.
-     * @see com.arjuna.wst.Vote
-     */
-    public Vote prepare() throws WrongStateException, SystemException
-    {
-        log.trace("prepare(Xid="+xid+")");
-
-        // Usually a VolatileParticipant would return Aborted to stop the tx in error cases. However, that
-        // would mean rollback() would not be called on the instance returning Aborted, which would make it
-        // hard to invoke afterCompletion on the subordinate. So we cheat a bit by using setRollbackOnly instead.
-        // A slightly more efficient but less clear impl would be to have the same object implement both the Volatile
-        // and Durable Participants and keep count of the number of prepare/rollback invocations to know
-        // if being invoked as Volatile or Durable.
-
-
-        // TODO InboundBridgeManager.getInboundBridge() would be better,
-        // but needs XTS to provide tx context on thread in (selected) Participant calls.
-        InboundBridge inboundBridge = InboundBridgeManager.getInboundBridge(externalTxId);
-
-        try
-        {
-            // TODO: check for rollbackOnly before bothering to invoke?
-            // beforeCompletion should run in tx context.
-            inboundBridge.start();
-
-            if(!xaTerminatorExtensions.beforeCompletion(xid))
-            {
-				log.warn("prepare on Xid="+xid+" failed, setting RollbackOnly");
-                inboundBridge.setRollbackOnly();
-            }
-
-            return new Prepared();
-        }
-        catch(Exception e)
-        {
-            log.warn("prepare on Xid="+xid+" failed, setting RollbackOnly", e);
-            try
-            {
-                inboundBridge.setRollbackOnly();
-            }
-            catch(Exception e2)
-            {
-                log.warn("setRollbackOnly failed", e2);
-            }
-
-            return new Prepared();
-        }
-        finally
-        {
-            try
-            {
-                inboundBridge.stop();
-            }
-            catch(Exception e)
-            {
-                log.warn("stop failed for Xid="+xid, e);
-            }
-        }
-    }
-
-    /**
-     * Perform afterCompletion cleanup activities such as releasing resources.
-     *
-     * Caution: may not be invoked in crash recovery situations.
-     */
-    public void commit() throws WrongStateException, SystemException
-    {
-        log.trace("commit(Xid="+xid+")");
-
-        afterCompletion(Status.STATUS_COMMITTED);
-    }
-
-    /**
-     * Perform afterCompletion cleanup activities such as releasing resources.
-     *
-     * Caution: may not be invoked in crash recovery situations.
-     */
-    public void rollback() throws WrongStateException, SystemException
-    {
-        log.trace("rollback(Xid="+xid+")");
-
-        afterCompletion(Status.STATUS_ROLLEDBACK);
-    }
-
-    /**
-     * Invoke afterCompletion on the subordinate JTA tx.
-     *
-     * @param status a javax.transaction.Status value, normally STATUS_COMMITTED or STATUS_ROLLEDBACK
-     */
-    private void afterCompletion(int status)
-    {
-        log.trace("afterCompletion(Xid="+xid+", status="+status+"/"+JTAHelper.stringForm(status)+")");
-
-        // this is a null-op, the afterCompletion is done implicitly at the XAResource commit/rollback stage.
-    }
-
-    /**
-     * Deprecated, should never be called.
-     */
-    public void unknown() throws SystemException
-    {
-        log.trace("unknown(Xid="+xid+"): NOT IMPLEMENTED");
-    }
-
-    /**
-     * VolatileParticipants don't support recovery, so this should never be called.
-     */
-    public void error() throws SystemException
-    {
-        log.trace("unknown(Xid="+xid+"): NOT IMPLEMENTED");
-    }
-}

Deleted: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeXAResource.java
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeXAResource.java	2010-03-05 05:45:20 UTC (rev 31954)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeXAResource.java	2010-03-05 11:17:50 UTC (rev 31955)
@@ -1,233 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- *
- * (C) 2009 @author Red Hat Middleware LLC
- */
-package org.jboss.jbossts.txbridge;
-
-import org.apache.log4j.Logger;
-import org.jboss.jbossts.xts.bridge.at.BridgeWrapper;
-
-import javax.transaction.xa.XAResource;
-import javax.transaction.xa.Xid;
-import javax.transaction.xa.XAException;
-
-import com.arjuna.ats.arjuna.common.Uid;
-import com.arjuna.ats.arjuna.coordinator.TwoPhaseOutcome;
-
-/**
- * Provides method call mapping between JTA parent coordinator and WS-AT subordinate transaction.
- *
- * @author jonathan.halliday at redhat.com, 2009-02-10
- */
-public class BridgeXAResource implements XAResource
-{
-    // Design note: Given the way JBossTS is designed, we could subclass AbstractRecord rather than
-    // implementing XAResource, but this design is more standards friendly and thus portable.
-
-    private static final Logger log = Logger.getLogger(BridgeXAResource.class);
-
-    private final transient BridgeWrapper bridgeWrapper;
-
-    private final transient Uid externalTxId;
-
-    /**
-     * Create a new XAResource which wraps the subordinate WS-AT transaction.
-     *
-     * @param externalTxId the parent JTA transaction identifier.
-     * @param bridgeWrapper the control for the subordinate WS-AT transaction.
-     */
-    public BridgeXAResource(Uid externalTxId, BridgeWrapper bridgeWrapper)
-    {
-        log.trace("BridgeXARresource(TxId="+externalTxId+", BridgeWrapper="+bridgeWrapper+")");
-
-        this.externalTxId = externalTxId;
-        this.bridgeWrapper = bridgeWrapper;
-    }
-
-    /**
-     * Ask the resource manager to prepare for a transaction commit of the transaction specified in xid.
-     *
-     * @param xid A global transaction identifier
-     * @return A value indicating the resource manager's vote on the outcome of the transaction
-     * @throws XAException
-     */
-    public int prepare(Xid xid) throws XAException
-    {
-        log.trace("prepare(Xid="+xid+")");
-
-        // TwoPhaseOutcome needs converting to XAResource rtn type.
-        int twoPhaseOutcome = bridgeWrapper.prepare();
-
-        log.trace("prepare TwoPhaseOutcome is "+twoPhaseOutcome+"/"+TwoPhaseOutcome.stringForm(twoPhaseOutcome));
-
-        switch(twoPhaseOutcome)
-        {
-            case TwoPhaseOutcome.PREPARE_OK:
-                log.trace("prepare returning XAResource.XA_OK");
-                return XAResource.XA_OK;
-            case TwoPhaseOutcome.PREPARE_READONLY:
-                OutboundBridgeManager.removeMapping(externalTxId);
-                log.trace("prepare returning XAResource.XA_RDONLY");
-                return XAResource.XA_RDONLY;
-            default:
-                // TODO more find-grained error type handling
-                log.trace("prepare TwoPhaseOutcome is "+twoPhaseOutcome+"/"+
-                        TwoPhaseOutcome.stringForm(twoPhaseOutcome)+", throwing XAException...");
-                XAException xaException = new XAException("unexpected oucome: "+TwoPhaseOutcome.stringForm(twoPhaseOutcome));
-                xaException.errorCode = XAException.XA_RBROLLBACK;
-                throw xaException;
-        }
-    }
-
-    /**
-     * Informs the resource manager to roll back work done on behalf of a transaction branch.
-     *
-     * @param xid A global transaction identifier
-     * @throws XAException
-     */
-    public void rollback(Xid xid) throws XAException
-    {
-        log.trace("rollback(Xid="+xid+")");
-
-        try
-        {
-            bridgeWrapper.rollback();
-        }
-        finally
-        {
-            OutboundBridgeManager.removeMapping(externalTxId);
-        }
-    }
-
-    /**
-     * Commits the global transaction specified by xid.
-     *
-     * @param xid A global transaction identifier
-     * @param onePhase
-     * @throws XAException
-     */
-    public void commit(Xid xid, boolean onePhase) throws XAException
-    {
-        log.trace("commit(Xid="+xid+", onePhase="+onePhase+")");
-
-        try
-        {
-            if(onePhase)
-            {
-                // no shortcuts, we have to do prepare anyhow
-                if(prepare(xid) == XAResource.XA_RDONLY)
-                {
-                    return;
-                }
-            }
-
-            bridgeWrapper.commit();
-        }
-        finally
-        {
-            OutboundBridgeManager.removeMapping(externalTxId);
-        }
-    }
-
-    /**
-     * Starts work on behalf of a transaction branch specified in xid.
-     *
-     * @param xid A global transaction identifier
-     * @param flags
-     * @throws XAException
-     */
-    public void start(Xid xid, int flags) throws XAException
-    {
-        log.trace("start(Xid="+xid+", flags="+flags+")");
-
-        // do nothing
-    }
-
-    /**
-     * Ends the work performed on behalf of a transaction branch.
-     *
-     * @param xid A global transaction identifier
-     * @param flags
-     * @throws XAException
-     */
-    public void end(Xid xid, int flags) throws XAException
-    {
-        log.trace("end(Xid="+xid+", flags="+flags+")");
-
-        // do nothing
-    }
-
-    public boolean isSameRM(XAResource xaResource) throws XAException
-    {
-        log.trace("isSameRM(XAResource="+xaResource+")");
-
-        return false;  // TODO
-    }
-
-    public void forget(Xid xid) throws XAException
-    {
-        log.trace("forget(Xid="+xid+")");
-
-        // TODO
-    }
-
-    /**
-     * Obtains a list of prepared transaction branches from a resource manager.
-     *
-     * @param flag
-     * @return
-     * @throws XAException
-     */
-    public Xid[] recover(int flag) throws XAException
-    {
-        log.trace("recover(flag="+flag+")");
-
-        return new Xid[0];  // TODO
-    }
-
-    /**
-     * Sets the current transaction timeout value for this XAResource instance.
-     *
-     * @param seconds - The transaction timeout value in seconds.
-     * @return true if the transaction timeout value is set successfully; otherwise false.
-     * @throws XAException
-     */
-    public boolean setTransactionTimeout(int seconds) throws XAException
-    {
-        log.trace("setTransactionTimeout(seconds="+seconds+")");
-
-        return false;  // TODO
-    }
-
-    /**
-     * Obtains the current transaction timeout value set for this XAResource instance.
-     *
-     * @return the transaction timeout value in seconds.
-     * @throws XAException
-     */
-    public int getTransactionTimeout() throws XAException
-    {
-        log.trace("getTransactionTimeout()");
-
-        return 0;  // TODO
-    }
-}

Deleted: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/InboundBridge.java
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/InboundBridge.java	2010-03-05 05:45:20 UTC (rev 31954)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/InboundBridge.java	2010-03-05 11:17:50 UTC (rev 31955)
@@ -1,132 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- *
- * (C) 2007, 2009 @author JBoss Inc
- */
-package org.jboss.jbossts.txbridge;
-
-import com.arjuna.ats.jta.TransactionManager;
-import com.arjuna.ats.internal.jta.transaction.arjunacore.jca.SubordinationManager;
-
-import javax.transaction.xa.Xid;
-import javax.transaction.xa.XAException;
-import javax.transaction.Status;
-import javax.transaction.SystemException;
-import javax.transaction.InvalidTransactionException;
-import javax.transaction.Transaction;
-
-import org.apache.log4j.Logger;
-
-/**
- * Manages Thread association of the interposed coordinator.
- * Typically called from handlers in the WS stack.
- *
- * @author jonathan.halliday at redhat.com, 2007-04-30
- */
-public class InboundBridge
-{
-	private static final Logger log = Logger.getLogger(InboundBridge.class);
-
-    /**
-     * Identifier for the subordinate transaction.
-     */
-	private final Xid xid;
-
-    /**
-     * Create a new InboundBridge to manage the given subordinate JTA transaction.
-     *
-     * @param xid the subordinate transaction id
-     * @throws XAException
-     * @throws SystemException
-     */
-	InboundBridge(Xid xid) throws XAException, SystemException
-    {
-		log.trace("InboundBridge(Xid="+xid+")");
-
-		this.xid = xid;
-
-		getTransaction(); // ensures transaction is initialized
-	}
-
-	/**
-	 * Associate the JTA transaction to the current Thread.
-	 * Typically used by a server side inbound handler.
-	 *
-	 * @throws XAException
-	 * @throws SystemException
-	 * @throws InvalidTransactionException
-	 */
-	public void start() throws XAException, SystemException, InvalidTransactionException
-    {
-		log.trace("start(Xid="+xid+")");
-
-		Transaction tx = getTransaction();
-
-		TransactionManager.transactionManager().resume(tx);
-	}
-
-	/**
-	 * Disassociate the JTA transaction from the current Thread.
-	 * Typically used by a server side outbound handler.
-	 *
-	 * @throws XAException
-	 * @throws SystemException
-	 * @throws InvalidTransactionException
-	 */
-	public void stop() throws XAException, SystemException, InvalidTransactionException
-    {
-		log.trace("stop("+xid+")");
-
-		TransactionManager.transactionManager().suspend();
-	}
-
-    public void setRollbackOnly() throws XAException, SystemException
-    {
-        log.trace("setRollbackOnly("+xid+")");
-
-        getTransaction().setRollbackOnly();
-    }
-
-	/**
-	 * Get the JTA Transaction which corresponds to the Xid of the instance.
-	 *
-	 * @return
-	 * @throws XAException
-	 * @throws SystemException
-	 */
-	private Transaction getTransaction()
-			throws XAException, SystemException
-	{
-		Transaction tx = SubordinationManager.getTransactionImporter().importTransaction(xid);
-
-		switch (tx.getStatus())
-		{
-            // TODO: other cases?
-
-			case Status.STATUS_ACTIVE:
-            case Status.STATUS_MARKED_ROLLBACK:
-				break;
-			default:
-				throw new IllegalStateException("Transaction not in state ACTIVE");
-		}
-		return tx;
-	}
-}

Deleted: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/InboundBridgeManager.java
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/InboundBridgeManager.java	2010-03-05 05:45:20 UTC (rev 31954)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/InboundBridgeManager.java	2010-03-05 11:17:50 UTC (rev 31955)
@@ -1,149 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- *
- * (C) 2007, 2009 @author JBoss Inc
- */
-package org.jboss.jbossts.txbridge;
-
-import com.arjuna.ats.jta.xa.XATxConverter;
-import com.arjuna.ats.arjuna.common.Uid;
-import com.arjuna.mw.wst11.UserTransactionFactory;
-
-import com.arjuna.mw.wst11.TransactionManagerFactory;
-import com.arjuna.mw.wst11.TransactionManager;
-import com.arjuna.wst.WrongStateException;
-import com.arjuna.wst.UnknownTransactionException;
-import com.arjuna.wsc.AlreadyRegisteredException;
-
-import javax.transaction.xa.Xid;
-import javax.transaction.xa.XAException;
-
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import org.apache.log4j.Logger;
-
-/**
- * Maintains the mapping data that relates WS-AT transactions to JTA subordinate transactions and related objects.
- *
- * The mappings are scoped to the singleton instance of this class and its lifetime.
- * This poses problems where you have more than one instance (classloading, clusters)
- * or where you need crash recovery. It short, it's rather limited.
- *
- * @author jonathan.halliday at redhat.com, 2007-04-30
- */
-public class InboundBridgeManager
-{
-	private static final Logger log = Logger.getLogger(InboundBridgeManager.class);
-
-    // maps WS-AT Tx Id to InboundBridge instance.
-	private static final ConcurrentMap<String, InboundBridge> inboundBridgeMappings = new ConcurrentHashMap<String, InboundBridge>();
-
-	/**
-	 * Return an InboundBridge instance that maps the current Thread's WS transaction context
-	 * to a JTA context. Control of the latter is provided by the returned instance.
-	 *
-	 * @return an InboundBridge corresponding to the calling Thread's current WS-AT transaction context.
-	 * @throws WrongStateException
-	 * @throws UnknownTransactionException
-	 * @throws com.arjuna.wst.SystemException
-	 * @throws AlreadyRegisteredException
-	 */
-	public static InboundBridge getInboundBridge()
-		throws XAException, WrongStateException, UnknownTransactionException,
-			com.arjuna.wst.SystemException, javax.transaction.SystemException, AlreadyRegisteredException
-	{
-		log.trace("getInboundBridge()");
-
-		String externalTxId = UserTransactionFactory.userTransaction().toString();
-
-        if(!inboundBridgeMappings.containsKey(externalTxId)) {
-            createMapping(externalTxId);
-        }
-
-		return inboundBridgeMappings.get(externalTxId);
-	}
-
-    /**
-     * Return an InboundBridge instance for the specified WS-AT transaction context.
-     *
-     * This method exists only to allow BridgeVolatileParticipant to get tx context and may go away
-     * once its no longer needed for that purpose. Therefore it should probably not be relied upon.
-     *
-     * @deprecated
-     * @param externalTxId The WS-AT tx identifier.
-     * @return
-     */
-    static InboundBridge getInboundBridge(String externalTxId)
-    {
-        return inboundBridgeMappings.get(externalTxId);
-    }
-
-    /**
-     * Remove the mapping for the given externalTxId. This should be called for gc when the tx is finished.
-     *
-     * @param externalTxId The WS-AT tx identifier.
-     */
-    public static synchronized void removeMapping(String externalTxId)
-    {
-        log.trace("removeMapping(externalTxId="+externalTxId+")");
-
-        if(externalTxId != null) {
-            inboundBridgeMappings.remove(externalTxId);
-        }
-    }
-
-	/**
-	 * Create the JTA transaction mapping and support objects for a given WS transaction context.
-	 *
-	 * @param externalTxId The WS-AT tx identifier.
-	 * @throws WrongStateException
-	 * @throws UnknownTransactionException
-	 * @throws com.arjuna.wst.SystemException
-	 * @throws AlreadyRegisteredException
-	 */
-	private static synchronized void createMapping(String externalTxId)
-			throws XAException, WrongStateException, UnknownTransactionException,
-			com.arjuna.wst.SystemException, javax.transaction.SystemException, AlreadyRegisteredException
-    {
-		log.trace("createMapping(externalTxId="+externalTxId+")");
-
-		if(inboundBridgeMappings.containsKey(externalTxId)) {
-			return;
-		}
-
-        TransactionManager transactionManager = TransactionManagerFactory.transactionManager();
-
-        // Xid for driving the subordinate,
-        // shared by the bridge (thread assoc) and Participant (termination via XATerminator)
-		Xid xid = XATxConverter.getXid(new Uid(), false, BridgeDurableParticipant.XARESOURCE_FORMAT_ID);
-
-		BridgeDurableParticipant bridgeDurableParticipant = new BridgeDurableParticipant(externalTxId, xid);
-        // construct the participantId in such as way as we can recognise it at recovery time:
-        String participantId = BridgeDurableParticipant.TYPE_IDENTIFIER+new Uid().toString();
-		transactionManager.enlistForDurableTwoPhase(bridgeDurableParticipant, participantId);
-
-        BridgeVolatileParticipant bridgeVolatileParticipant = new BridgeVolatileParticipant(externalTxId, xid);
-        transactionManager.enlistForVolatileTwoPhase(bridgeVolatileParticipant, new Uid().toString());
-
-        inboundBridgeMappings.put(externalTxId, new InboundBridge(xid));
-	}
-}
\ No newline at end of file

Deleted: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/JaxWSTxInboundBridgeHandler.java
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/JaxWSTxInboundBridgeHandler.java	2010-03-05 05:45:20 UTC (rev 31954)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/JaxWSTxInboundBridgeHandler.java	2010-03-05 11:17:50 UTC (rev 31955)
@@ -1,142 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- *
- * (C) 2007, 2009 @author JBoss Inc
- */
-package org.jboss.jbossts.txbridge;
-
-import javax.xml.ws.handler.Handler;
-import javax.xml.ws.handler.MessageContext;
-
-import org.apache.log4j.Logger;
-
-/**
- * A handler that sits in the server side JAX-WS processing pipeline between the XTS header
- * context processor and the web service. Takes the WS transaction context provided by the
- * former and maps it to a JTA transaction context for use by the latter. Handles Thread
- * association of the JTA context.
- *
- * Note: we assume that there is a web services transaction context present and
- * that the service needs a JTA context. The handler should not be registered on
- * methods unless both these conditions hold.
- *
- * @author jonathan.halliday at redhat.com, 2007-04-30
- */
-public class JaxWSTxInboundBridgeHandler implements Handler
-{
-	private static final Logger log = Logger.getLogger(JaxWSTxInboundBridgeHandler.class);
-
-	/**
-	 * Process a message. Determines if it is inbound or outbound and dispatches accordingly.
-	 *
-	 * @param msgContext the context to process
-	 * @return true on success, false on error
-	 */
-	public boolean handleMessage(MessageContext msgContext)
-	{
-		log.trace("handleMessage()");
-
-		Boolean outbound = (Boolean)msgContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
-		if (outbound == null)
-		   throw new IllegalStateException("Cannot obtain required property: " + MessageContext.MESSAGE_OUTBOUND_PROPERTY);
-
-		return outbound ? handleOutbound(msgContext) : handleInbound(msgContext);
-	}
-
-	/**
-	 * Tidy up the Transaction/Thread association before faults are thrown back to the client.
-	 *
-	 * @param messageContext unused
-	 * @return true on success, false on error
-	 */
-	public boolean handleFault(MessageContext messageContext)
-	{
-		log.trace("handleFault()");
-
-		return suspendTransaction();
-	}
-
-	public void close(MessageContext messageContext)
-	{
-		log.trace("close()");
-	}
-
-	/**
-	 * Process inbound messages by mapping the WS transaction context
-	 * to a JTA one and associating the latter to the current Thread.
-	 *
-	 * @param msgContext unused
-	 * @return true on success, false on error
-	 */
-	protected boolean handleInbound(MessageContext msgContext)
-	{
-		log.trace("handleInbound()");
-
-		try
-		{
-			InboundBridge inboundBridge = InboundBridgeManager.getInboundBridge();
-			inboundBridge.start();
-		}
-		catch (Exception e)
-		{
-			log.error(e);
-			return false;
-		}
-
-		return true;
-	}
-
-	/**
-	 * Tidy up the Transaction/Thread association before returning a message to the client.
-	 *
-	 * @param msgContext unused
-	 * @return true on success, false on error
-	 */
-	protected boolean handleOutbound(MessageContext msgContext)
-    {
-		log.trace("handleOutbound()");
-
-		return suspendTransaction();
-	}
-
-	/**
-	 * Break the association between the JTA transaction context and the calling Thread.
-     *
-     * @return true on success, false on error
-	 */
-	private boolean suspendTransaction()
-    {
-		log.trace("suspendTransaction()");
-
-		try
-		{
-			InboundBridge inboundBridge = InboundBridgeManager.getInboundBridge();
-			inboundBridge.stop();
-		}
-		catch (Exception e)
-		{
-			log.error(e);
-            return false;
-		}
-
-        return true;
-	}
-}
\ No newline at end of file

Deleted: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/JaxWSTxOutboundBridgeHandler.java
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/JaxWSTxOutboundBridgeHandler.java	2010-03-05 05:45:20 UTC (rev 31954)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/JaxWSTxOutboundBridgeHandler.java	2010-03-05 11:17:50 UTC (rev 31955)
@@ -1,142 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- *
- * (C) 2009 @author Red Hat Middleware LLC
- */
-package org.jboss.jbossts.txbridge;
-
-import org.apache.log4j.Logger;
-
-import javax.xml.ws.handler.Handler;
-import javax.xml.ws.handler.MessageContext;
-
-/**
- * A handler that sits in the client side JAX-WS processing pipeline between the application
- * and the XTS header context processor. Takes the JTA transaction context provided by the
- * former and maps it to a WS-AT transaction context for use by the latter. Handles Thread
- * association of the WS-AT context.
- *
- * Note: we assume that there is a JTA transaction context present and
- * that the service needs a WS-AT context. The handler should not be registered on
- * methods unless both these conditions hold.
- *
- * @author jonathan.halliday at redhat.com, 2009-02-10
- */
-public class JaxWSTxOutboundBridgeHandler implements Handler
-{
-	private static final Logger log = Logger.getLogger(JaxWSTxOutboundBridgeHandler.class);
-
-	/**
-	 * Process a message. Determines if it is inbound or outbound and dispatches accordingly.
-	 *
-	 * @param msgContext the context to process
-	 * @return true on success, false on error
-	 */
-	public boolean handleMessage(MessageContext msgContext)
-	{
-		log.trace("handleMessage()");
-
-		Boolean outbound = (Boolean)msgContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
-		if (outbound == null)
-		   throw new IllegalStateException("Cannot obtain required property: " + MessageContext.MESSAGE_OUTBOUND_PROPERTY);
-
-		return outbound ? handleOutbound(msgContext) : handleInbound(msgContext);
-	}
-
-	/**
-	 * Tidy up the Transaction/Thread association before faults are thrown back to the client.
-	 *
-	 * @param messageContext unused
-	 * @return true on success, false on error
-	 */
-	public boolean handleFault(MessageContext messageContext)
-	{
-		log.trace("handleFault()");
-
-		return suspendTransaction();
-	}
-
-	public void close(MessageContext messageContext)
-	{
-		log.trace("close()");
-	}
-
-	/**
-     * Tidy up the Transaction/Thread association before returning a message to the client.
-	 *
-	 * @param msgContext unused
-	 * @return true on success, false on error
-	 */
-	protected boolean handleInbound(MessageContext msgContext)
-	{
-		log.trace("handleInbound()");
-
-		return suspendTransaction();
-	}
-
-	/**
-     * Process outbound messages by mapping the JTA transaction context
-     * to a WS-AT one and associating the latter to the current Thread.
-	 *
-	 * @param msgContext unused
-	 * @return true on success, false on error
-	 */
-	protected boolean handleOutbound(MessageContext msgContext)
-    {
-		log.trace("handleOutbound()");
-
-		try
-		{
-			OutboundBridge outboundBridge = OutboundBridgeManager.getOutboundBridge();
-			outboundBridge.start();
-		}
-		catch (Exception e)
-		{
-			log.error(e);
-			return false;
-		}
-
-		return true;
-	}
-
-	/**
-	 * Break the association between the WS-AT transaction context and the calling Thread.
-     *
-     * @return true on success, false on error
-	 */
-	private boolean suspendTransaction()
-    {
-		log.trace("suspendTransaction()");
-
-		try
-		{
-			OutboundBridge outboundBridge = OutboundBridgeManager.getOutboundBridge();
-			outboundBridge.stop();
-		}
-		catch (Exception e)
-		{
-			log.error(e);
-            return false;
-		}
-
-        return true;
-	}
-}
\ No newline at end of file

Deleted: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/OutboundBridge.java
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/OutboundBridge.java	2010-03-05 05:45:20 UTC (rev 31954)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/OutboundBridge.java	2010-03-05 11:17:50 UTC (rev 31955)
@@ -1,88 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- *
- * (C) 2009 @author Red Hat Middleware LLC
- */
-package org.jboss.jbossts.txbridge;
-
-import org.apache.log4j.Logger;
-import org.jboss.jbossts.xts.bridge.at.BridgeWrapper;
-import com.arjuna.mw.wst11.TransactionManagerFactory;
-import com.arjuna.mw.wst.TxContext;
-import com.arjuna.wst.SystemException;
-import com.arjuna.wst.UnknownTransactionException;
-
-/**
- * Manages Thread association of the interposed coordinator.
- * Typically called from handlers in the WS stack.
- *
- * @author jonathan.halliday at redhat.com, 2009-02-10
- */
-public class OutboundBridge
-{
-    private static final Logger log = Logger.getLogger(OutboundBridge.class);
-
-    /**
-     * Management object for the subordinate transaction
-     */
-    private final BridgeWrapper bridgeWrapper;
-
-    /**
-     * Create a new OutboundBridge to manage the given subordinate WS-AT transaction.
-     *
-     * @param bridgeWrapper the subordinate transaction controller
-     */
-    public OutboundBridge(BridgeWrapper bridgeWrapper)
-    {
-        log.trace("OutboundBridge(BridgeWrapper="+bridgeWrapper+")");
-
-        this.bridgeWrapper = bridgeWrapper;
-    }
-
-    /**
-     * Associate the WS-AT transaction to the current Thread.
-     * Typically used by the client side outbound handler.
-     *
-     * @throws UnknownTransactionException
-     * @throws SystemException
-     */
-    public void start() throws UnknownTransactionException, SystemException
-    {
-		log.trace("start(BridgeWrapper="+bridgeWrapper+")");
-
-        TxContext txContext = bridgeWrapper.getContext();
-
-        TransactionManagerFactory.transactionManager().resume(txContext);
-	}
-
-    /**
-     * Disassociate the WS-AT transaction from the current Thread.
-     * Typically used by the client side inbound handler.
-     *
-     * @throws SystemException
-     */
-    public void stop() throws SystemException
-    {
-        log.trace("stop(BridgeWrapper="+bridgeWrapper+")");
-
-        TransactionManagerFactory.transactionManager().suspend();
-    }
-}

Deleted: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/OutboundBridgeManager.java
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/OutboundBridgeManager.java	2010-03-05 05:45:20 UTC (rev 31954)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/OutboundBridgeManager.java	2010-03-05 11:17:50 UTC (rev 31955)
@@ -1,136 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, Red Hat Middleware LLC, and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- *
- * (C) 2009 @author Red Hat Middleware LLC
- */
-package org.jboss.jbossts.txbridge;
-
-import com.arjuna.ats.jta.TransactionManager;
-import com.arjuna.ats.jta.transaction.Transaction;
-import com.arjuna.ats.arjuna.common.Uid;
-
-import javax.transaction.SystemException;
-import javax.transaction.RollbackException;
-import javax.transaction.Synchronization;
-import javax.transaction.xa.XAResource;
-
-import org.apache.log4j.Logger;
-import org.jboss.jbossts.xts.bridge.at.BridgeWrapper;
-
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * Maintains the mapping data that relates JTA transactions to WS-AT subordinate transactions and related objects.
- *
- * The mappings are scoped to the singleton instance of this class and its lifetime.
- * This poses problems where you have more than one instances (classloading, clusters)
- * or where you need crash recovery. It short, it's rather limited.
- *
- * @author jonathan.halliday at redhat.com, 2009-02-10
- */
-public class OutboundBridgeManager
-{
-    private static final Logger log = Logger.getLogger(OutboundBridgeManager.class);
-
-    // maps JTA Tx Id to OutboundBridge instance.
-    private static final ConcurrentMap<Uid, OutboundBridge> outboundBridgeMappings = new ConcurrentHashMap<Uid, OutboundBridge>();
-
-    /**
-     * Return an OutboundBridge instance that maps the current Thread's JTA transaction context
-     * to a WS-AT transaction context. Control of the latter is provided by the returned instance.
-     *
-     * @return as OutboundBridge corresponding to the calling Thread's current JTA transaction context.
-     */
-	public static OutboundBridge getOutboundBridge()
-	{
-		log.trace("getOutboundBridge()");
-
-        try
-        {
-            Transaction transaction = (Transaction)TransactionManager.transactionManager().getTransaction();
-
-            Uid externalTxId = transaction.get_uid();
-
-            if(!outboundBridgeMappings.containsKey(externalTxId)) {
-                createMapping(transaction, externalTxId);
-            }
-
-            return outboundBridgeMappings.get(externalTxId);
-
-        }
-        catch(SystemException e)
-        {
-            log.error("problem", e);
-        }
-
-        return null;
-	}
-
-    /**
-     * Remove the mapping for the given externalTxId. This should be called for gc when the tx is finished.
-     *
-     * @param externalTxId The JTA transaction identifier.
-     */
-    public static synchronized void removeMapping(Uid externalTxId)
-    {
-        log.trace("removeMapping(externalTxId="+externalTxId+")");
-
-        if(externalTxId != null) {
-            outboundBridgeMappings.remove(externalTxId);
-        }
-    }
-
-    /**
-     * Create a WS-AT transaction mapping and support objects for a given JTA transaction context.
-     *
-     * @param externalTxId The JTA transaction identifier.
-     * @throws SystemException
-     */
-    private static synchronized void createMapping(Transaction transaction, Uid externalTxId) throws SystemException
-    {
-        log.trace("createmapping(externalTxId="+externalTxId+")");
-
-        if(outboundBridgeMappings.containsKey(externalTxId)) {
-            return;
-        }
-
-        // TODO: allow params to be configurable, or at least pass timeout down.
-        BridgeWrapper bridgeWrapper = BridgeWrapper.create(0, false);
-
-        OutboundBridge outboundBridge = new OutboundBridge(bridgeWrapper);
-        XAResource xaResource = new BridgeXAResource(externalTxId, bridgeWrapper);
-        Synchronization synchronization = new BridgeSynchronization(bridgeWrapper);
-
-        try
-        {
-            transaction.enlistResource(xaResource);
-            transaction.registerSynchronization(synchronization);
-        }
-        catch(RollbackException e)
-        {
-            log.error("Unable to enlist BridgeXAResource or register BridgeSynchronization: ", e);
-            throw new SystemException(e.toString());
-        }
-
-        outboundBridgeMappings.put(externalTxId, outboundBridge);
-    }
-}
\ No newline at end of file

Copied: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/BridgeDurableParticipant.java (from rev 31937, labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeDurableParticipant.java)
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/BridgeDurableParticipant.java	                        (rev 0)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/BridgeDurableParticipant.java	2010-03-05 11:17:50 UTC (rev 31955)
@@ -0,0 +1,283 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ *
+ * (C) 2007, 2009 @author JBoss Inc
+ */
+package org.jboss.jbossts.txbridge.inbound;
+
+import com.arjuna.wst.*;
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.ats.internal.jta.transaction.arjunacore.jca.SubordinationManager;
+import org.apache.log4j.Logger;
+
+import javax.transaction.xa.Xid;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+
+import javax.resource.spi.XATerminator;
+
+import java.io.Serializable;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+/**
+ * Provides method call mapping between WS-AT Durable Participant interface
+ * and an underlying JTA subtransaction coordinator.
+ *
+ * @author jonathan.halliday at redhat.com, 2007-04-30
+ */
+public class BridgeDurableParticipant implements Durable2PCParticipant, Serializable
+{
+	private static final Logger log = Logger.getLogger(BridgeDurableParticipant.class);
+
+    /*
+     * Uniq String used to prefix ids at participant registration,
+     * so that the recovery module can identify relevant instances.
+     */
+    public static final String TYPE_IDENTIFIER = "BridgeDurableParticipant_";
+
+    /*
+     * Uniq (well, hopefully) formatId so we can distinguish our own Xids.
+     */
+    public static final int XARESOURCE_FORMAT_ID = 131080;
+
+	private transient volatile XATerminator xaTerminator;
+
+    private transient volatile String externalTxId;
+
+    private transient volatile boolean isAwaitingRecovery = false;
+
+    static final long serialVersionUID = -5739871936627778072L;
+
+    // Xid not guaranteed Serializable by spec, but our XidImple happens to be
+	private volatile Xid xid;
+
+    // Id needed for recovery of the subordinate tx. Uids are likewise Serializable.
+    private volatile Uid subordinateTransactionId;
+
+    /**
+     * Create a new WS-AT Durable Participant which wraps the subordinate XA tx terminator.
+     *
+     * @param externalTxId the WS-AT Tx identifier
+     * @param xid the Xid to use when driving the subordinate XA transaction.
+     */
+	BridgeDurableParticipant(String externalTxId, Xid xid)
+    {
+		log.trace("BridgeDurableParticipant(TxId="+externalTxId+", Xid="+xid+")");
+
+        this.xid = xid;
+        this.externalTxId = externalTxId;
+		xaTerminator = SubordinationManager.getXATerminator();
+	}
+
+    /**
+     * Serialization hook. Gathers and writes information needed for transaction recovery.
+     *
+     * @param out the stream to which the object state is serialized.
+     * @throws IOException if serialization fails.
+     */
+    private void writeObject(ObjectOutputStream out) throws IOException
+    {
+        log.trace("writeObject() for Xid="+xid);
+
+        // we need to preserve the Uid of the underlying SubordinateTx, as it's required
+        // to get a handle on it again during recovery, Using the xid wont work,
+        // although we do need to serialize that too for use after recovery.
+        try
+        {
+            subordinateTransactionId = SubordinationManager.getTransactionImporter().getImportedTransaction(xid).get_uid();
+        }
+        catch(XAException xaException)
+        {
+            log.error("Unable to get subordinate transaction id", xaException);
+            IOException ioException = new IOException("Unable to serialize");
+            ioException.initCause(xaException);
+            throw ioException;
+        }
+
+        //out.defaultWriteObject();
+        out.writeObject(xid);
+        out.writeObject(subordinateTransactionId);
+    }
+
+    /**
+     * Deserialization hook. Unpacks transaction recovery information and uses it to
+     * recover the subordinate transaction.
+     *
+     * @param in the stream from which to unpack the object state.
+     * @throws IOException if deserialzation and recovery fail.
+     * @throws ClassNotFoundException if deserialzation fails.
+     */
+    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
+    {
+        log.trace("readObject()");
+
+        //in.defaultReadObject();
+        xid = (Xid)in.readObject();
+        subordinateTransactionId = (Uid)in.readObject();
+
+        // this readObject method executes only when a log is being read at recovery time:
+        isAwaitingRecovery = true;
+
+        xaTerminator = SubordinationManager.getXATerminator();
+
+        try
+        {
+            SubordinationManager.getTransactionImporter().recoverTransaction(subordinateTransactionId);
+        }
+        catch(XAException xaException)
+        {
+            log.error("Unable to recover subordinate transaction id="+subordinateTransactionId, xaException);
+            IOException ioException = new IOException("unable to deserialize");
+            ioException.initCause(xaException);
+            throw ioException;
+        }
+    }
+
+    /**
+     * Perform any work necessary to allow it to either commit or rollback
+     * the work performed by the Web service under the scope of the
+     * transaction. The implementation is free to do whatever it needs to in
+     * order to fulfill the implicit contract between it and the coordinator.
+     *
+     * @return an indication of whether it can prepare or not.
+     * @see com.arjuna.wst.Vote
+     */
+	public Vote prepare() throws WrongStateException, SystemException
+	{
+		log.trace("prepare(Xid="+xid+")");
+
+		try
+        {
+			// XAResource.XA_OK, XAResource.XA_RDONLY or exception.  if RDONLY, don't call commit
+			int result = xaTerminator.prepare(xid);
+			if(result == XAResource.XA_OK)
+            {
+				log.debug("prepare on Xid="+xid+" returning Prepared");
+				return new Prepared();
+			}
+            else
+            {
+                cleanupRefs();
+                log.debug("prepare on Xid="+xid+" returning ReadOnly");
+				return new ReadOnly();
+			}
+
+		}
+        catch(XAException e)
+        {
+            cleanupRefs();
+            log.warn("prepare on Xid="+xid+" returning Aborted", e);
+			return new Aborted();
+		}
+    }
+
+    /**
+     * The participant should make permanent the work that it controls.
+	 *
+     * @throws WrongStateException
+     * @throws SystemException
+     */
+    public void commit() throws WrongStateException, SystemException
+    {
+		log.trace("commit(Xid="+xid+")");
+
+		try
+		{
+			xaTerminator.commit(xid, false);
+			log.debug("commit on Xid="+xid+" OK");
+		}
+		catch (XAException e)
+		{
+			log.error("commit on Xid="+xid+" failed", e);
+		}
+        finally
+        {
+            cleanupRefs();
+        }
+    }
+
+    /**
+     * The participant should undo the work that it controls. The participant
+     * will then return an indication of whether or not it succeeded..
+     *
+     * @throws WrongStateException
+     * @throws SystemException
+     */
+    public void rollback() throws WrongStateException, SystemException
+    {
+		log.trace("rollback(Xid="+xid+")");
+
+		try
+		{
+			xaTerminator.rollback(xid);
+			log.debug("rollback on Xid="+xid+" OK");
+		}
+		catch (XAException e)
+		{
+			log.error("rollback on Xid="+xid+" failed", e);
+		}
+        finally
+        {
+            cleanupRefs();
+        }
+    }
+
+    /**
+     * During recovery the participant can enquire as to the status of the
+     * transaction it was registered with. If that transaction is no longer
+     * available (has rolled back) then this operation will be invoked by the
+     * coordination service.
+     */
+	public void unknown() throws SystemException
+    {
+		log.trace("unknown(Xid="+xid+"): NOT IMPLEMENTED");
+    }
+
+    /**
+     * During recovery the participant can enquire as to the status of the
+     * transaction it was registered with. If an error occurs (e.g., the
+     * transaction service is unavailable) then this operation will be invoked.
+     */
+	public void error() throws SystemException
+    {
+		log.trace("error(Xid="+xid+"): NOT IMPLEMENTED");
+    }
+
+    public boolean isAwaitingRecovery() {
+        return isAwaitingRecovery;
+    }
+
+    public Xid getXid()
+    {
+        return xid;
+    }
+
+    private void cleanupRefs()
+    {
+        log.trace("cleanupRefs()");
+
+        org.jboss.jbossts.txbridge.inbound.InboundBridgeManager.removeMapping(externalTxId);
+        isAwaitingRecovery = false;
+    }
+}
+

Copied: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/BridgeVolatileParticipant.java (from rev 31937, labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeVolatileParticipant.java)
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/BridgeVolatileParticipant.java	                        (rev 0)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/BridgeVolatileParticipant.java	2010-03-05 11:17:50 UTC (rev 31955)
@@ -0,0 +1,179 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ *
+ * (C) 2009 @author JBoss Inc
+ */
+package org.jboss.jbossts.txbridge.inbound;
+
+import com.arjuna.wst.*;
+import com.arjuna.ats.internal.jta.resources.spi.XATerminatorExtensions;
+import com.arjuna.ats.internal.jta.transaction.arjunacore.jca.SubordinationManager;
+import com.arjuna.ats.jta.utils.JTAHelper;
+import org.apache.log4j.Logger;
+
+import javax.transaction.xa.Xid;
+import javax.transaction.Status;
+
+/**
+ * Provides method call mapping between WS-AT Volatile Participant interface
+ * and an underlying JTA subtransaction coordinator.
+ *
+ * @author jonathan.halliday at redhat.com, 2009-06-01
+ */
+public class BridgeVolatileParticipant implements Volatile2PCParticipant
+{
+    private static final Logger log = Logger.getLogger(BridgeVolatileParticipant.class);
+
+    // no standard interface for driving Synchronization phases separately
+    // in JCA, so we have to use proprietary API.
+    private final XATerminatorExtensions xaTerminatorExtensions;
+
+    private final String externalTxId;
+
+    private final Xid xid;
+
+    /**
+     * Create a new WS-AT Volatile Participant which wraps the subordinate XA tx terminator.
+     *
+     * @param externalTxId the WS-AT Tx identifier
+     * @param xid the Xid to use when driving the subordinate XA transaction.
+     */
+    BridgeVolatileParticipant(String externalTxId, Xid xid)
+    {
+		log.trace("BridgeVolatileParticipant(TxId="+externalTxId+", Xid="+xid+")");
+
+        this.xid = xid;
+        this.externalTxId = externalTxId;
+        this.xaTerminatorExtensions = (XATerminatorExtensions)SubordinationManager.getXATerminator();
+    }
+
+    /**
+     * Perform beforeCompletion activities such as flushing cached state to stable store.
+     *
+     * @return an indication of whether it can prepare or not.
+     * @see com.arjuna.wst.Vote
+     */
+    public Vote prepare() throws WrongStateException, SystemException
+    {
+        log.trace("prepare(Xid="+xid+")");
+
+        // Usually a VolatileParticipant would return Aborted to stop the tx in error cases. However, that
+        // would mean rollback() would not be called on the instance returning Aborted, which would make it
+        // hard to invoke afterCompletion on the subordinate. So we cheat a bit by using setRollbackOnly instead.
+        // A slightly more efficient but less clear impl would be to have the same object implement both the Volatile
+        // and Durable Participants and keep count of the number of prepare/rollback invocations to know
+        // if being invoked as Volatile or Durable.
+
+        InboundBridge inboundBridge = InboundBridgeManager.getInboundBridge(externalTxId);
+
+        try
+        {
+            // TODO: check for rollbackOnly before bothering to invoke?
+            // beforeCompletion should run in tx context.
+            inboundBridge.start();
+
+            if(!xaTerminatorExtensions.beforeCompletion(xid))
+            {
+				log.warn("prepare on Xid="+xid+" failed, setting RollbackOnly");
+                inboundBridge.setRollbackOnly();
+            }
+
+            return new Prepared();
+        }
+        catch(Exception e)
+        {
+            log.warn("prepare on Xid="+xid+" failed, setting RollbackOnly", e);
+            try
+            {
+                inboundBridge.setRollbackOnly();
+            }
+            catch(Exception e2)
+            {
+                log.warn("setRollbackOnly failed", e2);
+            }
+
+            return new Prepared();
+        }
+        finally
+        {
+            try
+            {
+                inboundBridge.stop();
+            }
+            catch(Exception e)
+            {
+                log.warn("stop failed for Xid="+xid, e);
+            }
+        }
+    }
+
+    /**
+     * Perform afterCompletion cleanup activities such as releasing resources.
+     *
+     * Caution: may not be invoked in crash recovery situations.
+     */
+    public void commit() throws WrongStateException, SystemException
+    {
+        log.trace("commit(Xid="+xid+")");
+
+        afterCompletion(Status.STATUS_COMMITTED);
+    }
+
+    /**
+     * Perform afterCompletion cleanup activities such as releasing resources.
+     *
+     * Caution: may not be invoked in crash recovery situations.
+     */
+    public void rollback() throws WrongStateException, SystemException
+    {
+        log.trace("rollback(Xid="+xid+")");
+
+        afterCompletion(Status.STATUS_ROLLEDBACK);
+    }
+
+    /**
+     * Invoke afterCompletion on the subordinate JTA tx.
+     *
+     * @param status a javax.transaction.Status value, normally STATUS_COMMITTED or STATUS_ROLLEDBACK
+     */
+    private void afterCompletion(int status)
+    {
+        log.trace("afterCompletion(Xid="+xid+", status="+status+"/"+JTAHelper.stringForm(status)+")");
+
+        // this is a null-op, the afterCompletion is done implicitly at the XAResource commit/rollback stage.
+    }
+
+    /**
+     * Deprecated, should never be called.
+     */
+    public void unknown() throws SystemException
+    {
+        log.trace("unknown(Xid="+xid+"): NOT IMPLEMENTED");
+    }
+
+    /**
+     * VolatileParticipants don't support recovery, so this should never be called.
+     */
+    public void error() throws SystemException
+    {
+        log.trace("unknown(Xid="+xid+"): NOT IMPLEMENTED");
+    }
+}

Copied: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/InboundBridge.java (from rev 31937, labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/InboundBridge.java)
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/InboundBridge.java	                        (rev 0)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/InboundBridge.java	2010-03-05 11:17:50 UTC (rev 31955)
@@ -0,0 +1,132 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ *
+ * (C) 2007, 2009 @author JBoss Inc
+ */
+package org.jboss.jbossts.txbridge.inbound;
+
+import com.arjuna.ats.jta.TransactionManager;
+import com.arjuna.ats.internal.jta.transaction.arjunacore.jca.SubordinationManager;
+
+import javax.transaction.xa.Xid;
+import javax.transaction.xa.XAException;
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+import javax.transaction.InvalidTransactionException;
+import javax.transaction.Transaction;
+
+import org.apache.log4j.Logger;
+
+/**
+ * Manages Thread association of the interposed coordinator.
+ * Typically called from handlers in the WS stack.
+ *
+ * @author jonathan.halliday at redhat.com, 2007-04-30
+ */
+public class InboundBridge
+{
+	private static final Logger log = Logger.getLogger(InboundBridge.class);
+
+    /**
+     * Identifier for the subordinate transaction.
+     */
+	private final Xid xid;
+
+    /**
+     * Create a new InboundBridge to manage the given subordinate JTA transaction.
+     *
+     * @param xid the subordinate transaction id
+     * @throws XAException
+     * @throws SystemException
+     */
+	InboundBridge(Xid xid) throws XAException, SystemException
+    {
+		log.trace("InboundBridge(Xid="+xid+")");
+
+		this.xid = xid;
+
+		getTransaction(); // ensures transaction is initialized
+	}
+
+	/**
+	 * Associate the JTA transaction to the current Thread.
+	 * Typically used by a server side inbound handler.
+	 *
+	 * @throws XAException
+	 * @throws SystemException
+	 * @throws InvalidTransactionException
+	 */
+	public void start() throws XAException, SystemException, InvalidTransactionException
+    {
+		log.trace("start(Xid="+xid+")");
+
+		Transaction tx = getTransaction();
+
+		TransactionManager.transactionManager().resume(tx);
+	}
+
+	/**
+	 * Disassociate the JTA transaction from the current Thread.
+	 * Typically used by a server side outbound handler.
+	 *
+	 * @throws XAException
+	 * @throws SystemException
+	 * @throws InvalidTransactionException
+	 */
+	public void stop() throws XAException, SystemException, InvalidTransactionException
+    {
+		log.trace("stop("+xid+")");
+
+		TransactionManager.transactionManager().suspend();
+	}
+
+    public void setRollbackOnly() throws XAException, SystemException
+    {
+        log.trace("setRollbackOnly("+xid+")");
+
+        getTransaction().setRollbackOnly();
+    }
+
+	/**
+	 * Get the JTA Transaction which corresponds to the Xid of the instance.
+	 *
+	 * @return
+	 * @throws XAException
+	 * @throws SystemException
+	 */
+	private Transaction getTransaction()
+			throws XAException, SystemException
+	{
+		Transaction tx = SubordinationManager.getTransactionImporter().importTransaction(xid);
+
+		switch (tx.getStatus())
+		{
+            // TODO: other cases?
+
+			case Status.STATUS_ACTIVE:
+            case Status.STATUS_MARKED_ROLLBACK:
+				break;
+			default:
+				throw new IllegalStateException("Transaction not in state ACTIVE");
+		}
+		return tx;
+	}
+}

Copied: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/InboundBridgeManager.java (from rev 31937, labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/InboundBridgeManager.java)
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/InboundBridgeManager.java	                        (rev 0)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/InboundBridgeManager.java	2010-03-05 11:17:50 UTC (rev 31955)
@@ -0,0 +1,149 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ *
+ * (C) 2007, 2009 @author JBoss Inc
+ */
+package org.jboss.jbossts.txbridge.inbound;
+
+import com.arjuna.ats.jta.xa.XATxConverter;
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.mw.wst11.UserTransactionFactory;
+
+import com.arjuna.mw.wst11.TransactionManagerFactory;
+import com.arjuna.mw.wst11.TransactionManager;
+import com.arjuna.wst.WrongStateException;
+import com.arjuna.wst.UnknownTransactionException;
+import com.arjuna.wsc.AlreadyRegisteredException;
+
+import javax.transaction.xa.Xid;
+import javax.transaction.xa.XAException;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.log4j.Logger;
+
+/**
+ * Maintains the mapping data that relates WS-AT transactions to JTA subordinate transactions and related objects.
+ *
+ * The mappings are scoped to the singleton instance of this class and its lifetime.
+ * This poses problems where you have more than one instance (classloading, clusters)
+ * or where you need crash recovery. It short, it's rather limited.
+ *
+ * @author jonathan.halliday at redhat.com, 2007-04-30
+ */
+public class InboundBridgeManager
+{
+	private static final Logger log = Logger.getLogger(InboundBridgeManager.class);
+
+    // maps WS-AT Tx Id to InboundBridge instance.
+	private static final ConcurrentMap<String, InboundBridge> inboundBridgeMappings = new ConcurrentHashMap<String, org.jboss.jbossts.txbridge.inbound.InboundBridge>();
+
+	/**
+	 * Return an InboundBridge instance that maps the current Thread's WS transaction context
+	 * to a JTA context. Control of the latter is provided by the returned instance.
+	 *
+	 * @return an InboundBridge corresponding to the calling Thread's current WS-AT transaction context.
+	 * @throws WrongStateException
+	 * @throws UnknownTransactionException
+	 * @throws com.arjuna.wst.SystemException
+	 * @throws AlreadyRegisteredException
+	 */
+	public static InboundBridge getInboundBridge()
+		throws XAException, WrongStateException, UnknownTransactionException,
+			com.arjuna.wst.SystemException, javax.transaction.SystemException, AlreadyRegisteredException
+	{
+		log.trace("getInboundBridge()");
+
+		String externalTxId = UserTransactionFactory.userTransaction().toString();
+
+        if(!inboundBridgeMappings.containsKey(externalTxId)) {
+            createMapping(externalTxId);
+        }
+
+		return inboundBridgeMappings.get(externalTxId);
+	}
+
+    /**
+     * Return an InboundBridge instance for the specified WS-AT transaction context.
+     *
+     * This method exists only to allow BridgeVolatileParticipant to get tx context and may go away
+     * once its no longer needed for that purpose. Therefore it should probably not be relied upon.
+     *
+     * @deprecated
+     * @param externalTxId The WS-AT tx identifier.
+     * @return
+     */
+    static InboundBridge getInboundBridge(String externalTxId)
+    {
+        return inboundBridgeMappings.get(externalTxId);
+    }
+
+    /**
+     * Remove the mapping for the given externalTxId. This should be called for gc when the tx is finished.
+     *
+     * @param externalTxId The WS-AT tx identifier.
+     */
+    public static synchronized void removeMapping(String externalTxId)
+    {
+        log.trace("removeMapping(externalTxId="+externalTxId+")");
+
+        if(externalTxId != null) {
+            inboundBridgeMappings.remove(externalTxId);
+        }
+    }
+
+	/**
+	 * Create the JTA transaction mapping and support objects for a given WS transaction context.
+	 *
+	 * @param externalTxId The WS-AT tx identifier.
+	 * @throws WrongStateException
+	 * @throws UnknownTransactionException
+	 * @throws com.arjuna.wst.SystemException
+	 * @throws AlreadyRegisteredException
+	 */
+	private static synchronized void createMapping(String externalTxId)
+			throws XAException, WrongStateException, UnknownTransactionException,
+			com.arjuna.wst.SystemException, javax.transaction.SystemException, AlreadyRegisteredException
+    {
+		log.trace("createMapping(externalTxId="+externalTxId+")");
+
+		if(inboundBridgeMappings.containsKey(externalTxId)) {
+			return;
+		}
+
+        TransactionManager transactionManager = TransactionManagerFactory.transactionManager();
+
+        // Xid for driving the subordinate,
+        // shared by the bridge (thread assoc) and Participant (termination via XATerminator)
+		Xid xid = XATxConverter.getXid(new Uid(), false, BridgeDurableParticipant.XARESOURCE_FORMAT_ID);
+
+		BridgeDurableParticipant bridgeDurableParticipant = new BridgeDurableParticipant(externalTxId, xid);
+        // construct the participantId in such as way as we can recognise it at recovery time:
+        String participantId = org.jboss.jbossts.txbridge.inbound.BridgeDurableParticipant.TYPE_IDENTIFIER+new Uid().toString();
+		transactionManager.enlistForDurableTwoPhase(bridgeDurableParticipant, participantId);
+
+        BridgeVolatileParticipant bridgeVolatileParticipant = new BridgeVolatileParticipant(externalTxId, xid);
+        transactionManager.enlistForVolatileTwoPhase(bridgeVolatileParticipant, new Uid().toString());
+
+        inboundBridgeMappings.put(externalTxId, new InboundBridge(xid));
+	}
+}
\ No newline at end of file

Copied: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/InboundBridgeRecoveryManager.java (from rev 31937, labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeRecoveryManager.java)
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/InboundBridgeRecoveryManager.java	                        (rev 0)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/InboundBridgeRecoveryManager.java	2010-03-05 11:17:50 UTC (rev 31955)
@@ -0,0 +1,289 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ *
+ * (C) 2009 @author Red Hat Middleware LLC
+ */
+package org.jboss.jbossts.txbridge.inbound;
+
+import com.arjuna.ats.arjuna.recovery.RecoveryManager;
+import com.arjuna.ats.arjuna.recovery.RecoveryModule;
+import com.arjuna.ats.internal.jta.recovery.arjunacore.XARecoveryModule;
+import com.arjuna.ats.internal.jta.transaction.arjunacore.jca.SubordinationManager;
+import com.arjuna.ats.jta.recovery.XAResourceOrphanFilter;
+import org.apache.log4j.Logger;
+import org.jboss.jbossts.xts.recovery.participant.at.XTSATRecoveryModule;
+import org.jboss.jbossts.xts.recovery.participant.at.XTSATRecoveryManager;
+import com.arjuna.wst.Durable2PCParticipant;
+
+import javax.resource.spi.XATerminator;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+import java.io.ObjectInputStream;
+import java.util.*;
+
+/**
+ * Integrates with JBossAS MC lifecycle and JBossTS recovery manager to provide
+ * recovery services for inbound bridged transactions.
+ *
+ * @author jonathan.halliday at redhat.com, 2009-02-10
+ */
+public class InboundBridgeRecoveryManager implements XTSATRecoveryModule, RecoveryModule, XAResourceOrphanFilter
+{
+    private static final Logger log = Logger.getLogger(InboundBridgeRecoveryManager.class);
+
+    private final XTSATRecoveryManager xtsATRecoveryManager = XTSATRecoveryManager.getRecoveryManager();
+    private final RecoveryManager acRecoveryManager = RecoveryManager.manager();
+    private final XATerminator xaTerminator = SubordinationManager.getXATerminator();
+
+    private final List<BridgeDurableParticipant> participantsAwaitingRecovery =
+            Collections.synchronizedList(new LinkedList<BridgeDurableParticipant>());
+    private volatile boolean orphanedXAResourcesAreIdentifiable = false;
+
+    /**
+     * MC lifecycle callback, used to register components with the recovery manager.
+     */
+    public void start()
+    {
+        log.info("InboundBridgeRecoveryManager starting");
+
+        xtsATRecoveryManager.registerRecoveryModule(this);
+        acRecoveryManager.addModule(this);
+
+        XARecoveryModule xaRecoveryModule = getXARecoveryModule();
+        xaRecoveryModule.addXAResourceOrphanFilter(this);
+    }
+
+    /**
+     * MC lifecycle callback, used to unregister components from the recovery manager.
+     */
+    public void stop()
+    {
+        log.info("InboundBridgeRecoveryManager stopping");
+
+        xtsATRecoveryManager.unregisterRecoveryModule(this);
+        acRecoveryManager.removeModule(this, false);
+        
+        XARecoveryModule xaRecoveryModule = getXARecoveryModule();
+        xaRecoveryModule.removeXAResourceOrphanFilter(this);
+    }
+
+    /**
+     * Lookup the XARecoveryModule, required for (de-)registration of XAResourceOrphanFilter.
+     * @return the RecoveryManager's XARecoveryModule instance.
+     */
+    private XARecoveryModule getXARecoveryModule()
+    {
+        // at some stage we should probably consider extending atsintegration's
+        // RecoveryManagerService (and maybe the app server's tm integration spi) to
+        // expose orphan filters directly, as with e.g. [add|remove]XAResourceRecovery.
+
+        XARecoveryModule xaRecoveryModule = null;
+        for(RecoveryModule recoveryModule : ((Vector<RecoveryModule>)acRecoveryManager.getModules())) {
+            if(recoveryModule instanceof XARecoveryModule) {
+                xaRecoveryModule = (XARecoveryModule)recoveryModule;
+                break;
+            }
+        }
+
+        if(xaRecoveryModule == null) {
+            throw new IllegalStateException("no XARecoveryModule found");
+        }
+        return xaRecoveryModule;
+    }
+
+    /**
+     * Called during recovery processing to allow an application to identify a participant id
+     * belonging to one of its participants and recreate the participant by deserializing
+     * it from the supplied object input stream. n.b. this is only appropriate in case the
+     * participant was originally saved using serialization.
+     *
+     * @param id the id used when the participant was created
+     * @param objectInputStream a stream from which the application should deserialize the participant
+     * if it recognises that the id belongs to the module's application
+     * @return the deserialized Participant object
+     * @throws Exception if an error occurs deserializing the durable participant
+     */
+    @Override
+    public Durable2PCParticipant deserialize(String id, ObjectInputStream objectInputStream) throws Exception
+    {
+        log.trace("deserialize(id="+id+")");
+
+        // Inbound bridge transactions don't have an independent log - their state is inlined into the
+        // XTS Participant log and this callback is used to recover that state.
+        // We keep a handle on it for later use, as we have no other means of determining which Xids
+        // represent uncompleted transactions.
+        if(id.startsWith(BridgeDurableParticipant.TYPE_IDENTIFIER))
+        {
+            Object participant = objectInputStream.readObject();
+            BridgeDurableParticipant bridgeDurableParticipant = (BridgeDurableParticipant)participant;
+            participantsAwaitingRecovery.add(bridgeDurableParticipant);
+            return bridgeDurableParticipant;
+        }
+        else
+        {
+            return null; // it belongs to some other XTS app, ignore it.
+        }
+    }
+
+    /**
+     * Unused recovery callback. We use serialization instead, so this method will always throw an exception if called.
+     */
+    @Override
+    public Durable2PCParticipant recreate(String s, byte[] bytes) throws Exception
+    {
+        throw new Exception("recreation not supported - should use deserialization instead.");
+    }
+
+    /**
+     * Called by the RecoveryManager at start up, and then
+     * PERIODIC_RECOVERY_PERIOD seconds after the completion, for all RecoveryModules,
+     * of the second pass
+     */
+    @Override
+    public void periodicWorkFirstPass()
+    {
+        log.trace("periodicWorkFirstPass()");
+    }
+
+    /**
+     * Called by the RecoveryManager RECOVERY_BACKOFF_PERIOD seconds
+     * after the completion of the first pass
+     */
+    @Override
+    public void periodicWorkSecondPass()
+    {
+        log.trace("periodicWorkSecondPass()");
+
+        cleanupRecoveredParticipants();
+
+        // the XTS recovery module is registered and hence run before us. Therefore by the time we get here
+        // we know deserialize has been called for any BridgeDurableParticipant for which a log exists.
+        // thus if it's not in our participantsAwaitingRecovery list by now, it's presumed rollback.
+        orphanedXAResourcesAreIdentifiable = true;
+
+        // Inbound tx may have a JCA tx log but no corresponding XTS Participant (i.e. BridgeDurableParticipant) log.
+        // these can now be identified and rolled back.
+        List<Xid> indoubtSubordinates = getIndoubtSubordinates();
+        for(Xid xid : indoubtSubordinates) {
+            if(checkXid(xid) == XAResourceOrphanFilter.Vote.ROLLBACK) {
+                log.trace("rolling back orphaned subordinate tx "+xid);
+                try {
+                    xaTerminator.rollback(xid);
+                } catch(XAException e) {
+                    log.error("problem rolling back orphaned subordinate tx "+xid, e);
+                }
+            }
+        }
+
+    }
+
+    /**
+     * Run a recovery scan to identify any in-doubt JTA subordinates.
+     *
+     * @return a possibly empty but non-null list of xids corresponding to outstanding
+     * JTA subordinate transactions owned by the txbridge.
+     */
+    private List<Xid> getIndoubtSubordinates()
+    {
+        log.trace("getIndoubtSubordinates()");
+
+        Xid[] allSubordinateXids = null;
+        try {
+            allSubordinateXids = xaTerminator.recover(XAResource.TMSTARTRSCAN);
+        } catch(XAException e) {
+            log.error("Problem whilst scanning for in-doubt subordinate transactions", e);
+        } finally {
+            try {
+                xaTerminator.recover(XAResource.TMENDRSCAN);
+            } catch(XAException e) {}
+        }
+
+        LinkedList<Xid> mySubordinateXids = new LinkedList<Xid>();
+
+        if(allSubordinateXids == null) {
+            return mySubordinateXids;
+        }
+
+        for(Xid xid : allSubordinateXids) {
+            if(xid.getFormatId() == BridgeDurableParticipant.XARESOURCE_FORMAT_ID) {
+                mySubordinateXids.add(xid);
+                log.trace("in-doubt subordinate, xid: "+xid);
+            }
+        }
+
+        return mySubordinateXids;
+    }
+
+    /**
+     * Release any BridgeDurableParticipant instances that have been driven
+     * through to completion by their parent XTS transaction.
+     */
+    private void cleanupRecoveredParticipants()
+    {
+        log.trace("cleanupRecoveredParticipants()");
+
+        synchronized(participantsAwaitingRecovery) {
+            Iterator<org.jboss.jbossts.txbridge.inbound.BridgeDurableParticipant> iter = participantsAwaitingRecovery.iterator();
+            while(iter.hasNext()) {
+                BridgeDurableParticipant participant = iter.next();
+                if(!participant.isAwaitingRecovery()) {
+                    iter.remove();
+                }
+            }
+        }
+    }
+
+    /**
+     * Used to identify inbound bridged Xids in either the RM log (when called by XARecoveryModule) or
+     * the JCA subordinate tx log (when called internally from this class) which have or have not got a
+     * remaining transaction that may still drive them to completion.
+     * 
+     * @param xid The in-doubt xid.
+     * @return a Vote on the handling of the xid (to roll it back or not).
+     */
+    @Override
+    public Vote checkXid(Xid xid)
+    {
+        log.trace("checkXid("+xid+")");
+
+        if(xid.getFormatId() != BridgeDurableParticipant.XARESOURCE_FORMAT_ID) {
+            return Vote.ABSTAIN; // it's not one of ours, ignore it.
+        }
+
+        if(!orphanedXAResourcesAreIdentifiable) {
+            // recovery system not in stable state yet - we don't yet know if it's orphaned or not.
+            return Vote.LEAVE_ALONE;
+        }
+
+        // check if it's owned by a recovered tx that may still commit.
+        synchronized(participantsAwaitingRecovery) {
+            for(BridgeDurableParticipant participant : participantsAwaitingRecovery) {
+                if(participant.getXid().equals(xid)) {
+                    return Vote.LEAVE_ALONE;
+                }
+            }
+        }
+
+        // presumed abort:
+        return Vote.ROLLBACK;
+    }
+}

Copied: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/JaxWSTxInboundBridgeHandler.java (from rev 31937, labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/JaxWSTxInboundBridgeHandler.java)
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/JaxWSTxInboundBridgeHandler.java	                        (rev 0)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/inbound/JaxWSTxInboundBridgeHandler.java	2010-03-05 11:17:50 UTC (rev 31955)
@@ -0,0 +1,142 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ *
+ * (C) 2007, 2009 @author JBoss Inc
+ */
+package org.jboss.jbossts.txbridge.inbound;
+
+import javax.xml.ws.handler.Handler;
+import javax.xml.ws.handler.MessageContext;
+
+import org.apache.log4j.Logger;
+
+/**
+ * A handler that sits in the server side JAX-WS processing pipeline between the XTS header
+ * context processor and the web service. Takes the WS transaction context provided by the
+ * former and maps it to a JTA transaction context for use by the latter. Handles Thread
+ * association of the JTA context.
+ *
+ * Note: we assume that there is a web services transaction context present and
+ * that the service needs a JTA context. The handler should not be registered on
+ * methods unless both these conditions hold.
+ *
+ * @author jonathan.halliday at redhat.com, 2007-04-30
+ */
+public class JaxWSTxInboundBridgeHandler implements Handler
+{
+	private static final Logger log = Logger.getLogger(JaxWSTxInboundBridgeHandler.class);
+
+	/**
+	 * Process a message. Determines if it is inbound or outbound and dispatches accordingly.
+	 *
+	 * @param msgContext the context to process
+	 * @return true on success, false on error
+	 */
+	public boolean handleMessage(MessageContext msgContext)
+	{
+		log.trace("handleMessage()");
+
+		Boolean outbound = (Boolean)msgContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+		if (outbound == null)
+		   throw new IllegalStateException("Cannot obtain required property: " + MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+
+		return outbound ? handleOutbound(msgContext) : handleInbound(msgContext);
+	}
+
+	/**
+	 * Tidy up the Transaction/Thread association before faults are thrown back to the client.
+	 *
+	 * @param messageContext unused
+	 * @return true on success, false on error
+	 */
+	public boolean handleFault(MessageContext messageContext)
+	{
+		log.trace("handleFault()");
+
+		return suspendTransaction();
+	}
+
+	public void close(MessageContext messageContext)
+	{
+		log.trace("close()");
+	}
+
+	/**
+	 * Process inbound messages by mapping the WS transaction context
+	 * to a JTA one and associating the latter to the current Thread.
+	 *
+	 * @param msgContext unused
+	 * @return true on success, false on error
+	 */
+	protected boolean handleInbound(MessageContext msgContext)
+	{
+		log.trace("handleInbound()");
+
+		try
+		{
+			InboundBridge inboundBridge = org.jboss.jbossts.txbridge.inbound.InboundBridgeManager.getInboundBridge();
+			inboundBridge.start();
+		}
+		catch (Exception e)
+		{
+			log.error(e);
+			return false;
+		}
+
+		return true;
+	}
+
+	/**
+	 * Tidy up the Transaction/Thread association before returning a message to the client.
+	 *
+	 * @param msgContext unused
+	 * @return true on success, false on error
+	 */
+	protected boolean handleOutbound(MessageContext msgContext)
+    {
+		log.trace("handleOutbound()");
+
+		return suspendTransaction();
+	}
+
+	/**
+	 * Break the association between the JTA transaction context and the calling Thread.
+     *
+     * @return true on success, false on error
+	 */
+	private boolean suspendTransaction()
+    {
+		log.trace("suspendTransaction()");
+
+		try
+		{
+			org.jboss.jbossts.txbridge.inbound.InboundBridge inboundBridge = InboundBridgeManager.getInboundBridge();
+			inboundBridge.stop();
+		}
+		catch (Exception e)
+		{
+			log.error(e);
+            return false;
+		}
+
+        return true;
+	}
+}
\ No newline at end of file

Copied: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/BridgeSynchronization.java (from rev 31937, labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeSynchronization.java)
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/BridgeSynchronization.java	                        (rev 0)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/BridgeSynchronization.java	2010-03-05 11:17:50 UTC (rev 31955)
@@ -0,0 +1,90 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ *
+ * (C) 2009 @author JBoss Inc
+ */
+package org.jboss.jbossts.txbridge.outbound;
+
+import org.apache.log4j.Logger;
+import org.jboss.jbossts.xts.bridge.at.BridgeWrapper;
+
+import javax.transaction.Synchronization;
+import javax.transaction.Status;
+
+import com.arjuna.ats.jta.utils.JTAHelper;
+
+/**
+ * Provides method call mapping between JTA parent coordinator and WS-AT subordinate transaction.
+ *
+ * @author jonathan.halliday at redhat.com, 2009-06-01
+ */
+public class BridgeSynchronization implements Synchronization
+{
+    private static final Logger log = Logger.getLogger(BridgeSynchronization.class);
+
+    private final BridgeWrapper bridgeWrapper;
+
+    public BridgeSynchronization(BridgeWrapper bridgeWrapper)
+    {
+        log.trace("BridgeSynchronization(BridgeWrapper="+bridgeWrapper+")");
+
+        this.bridgeWrapper = bridgeWrapper;
+    }
+
+    /**
+     * The beforeCompletion method is called by the transaction manager prior to the start of the two-phase transaction commit process.
+     */
+    public void beforeCompletion()
+    {
+        log.trace("beforeCompletion()");
+
+        if(!bridgeWrapper.prepareVolatile())
+        {
+            // JTA does not explicitly provide for beforeCompletion signalling problems, but in
+            // our impl the engine will set the tx rollbackOnly if beforeCompletion throw an exception
+            // Note com.arjuna.ats.jta.TransactionManager.getTransaction().setRollbackOnly may also work.
+            throw new RuntimeException("BridgeWrapper.prepareVolatile() returned false");
+        }
+    }
+
+    /**
+     * This method is called by the transaction manager after the transaction is committed or rolled back.
+     *
+     * @param status the javax.transaction.Status representing the tx outcome.
+     */
+    public void afterCompletion(int status)
+    {
+        log.trace("afterCompletion(status="+status+"/"+ JTAHelper.stringForm(status)+")");
+
+        switch(status)
+        {
+            case Status.STATUS_COMMITTED:
+                bridgeWrapper.commitVolatile();
+                break;
+            case Status.STATUS_ROLLEDBACK:
+                bridgeWrapper.rollbackVolatile();
+                break;
+            default:
+                log.warn("unexpected Status "+status+", treating as ROLLEDBACK");
+                bridgeWrapper.rollbackVolatile();
+        }
+    }
+}

Copied: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/BridgeXAResource.java (from rev 31937, labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/BridgeXAResource.java)
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/BridgeXAResource.java	                        (rev 0)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/BridgeXAResource.java	2010-03-05 11:17:50 UTC (rev 31955)
@@ -0,0 +1,287 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ *
+ * (C) 2009 @author Red Hat Middleware LLC
+ */
+package org.jboss.jbossts.txbridge.outbound;
+
+import com.arjuna.wst.UnknownTransactionException;
+import org.apache.log4j.Logger;
+import org.jboss.jbossts.xts.bridge.at.BridgeWrapper;
+
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+import javax.transaction.xa.XAException;
+
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.ats.arjuna.coordinator.TwoPhaseOutcome;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+/**
+ * Provides method call mapping between JTA parent coordinator and WS-AT subordinate transaction.
+ *
+ * @author jonathan.halliday at redhat.com, 2009-02-10
+ */
+public class BridgeXAResource implements XAResource, Serializable
+{
+    // Design note: Given the way JBossTS is designed, we could subclass AbstractRecord rather than
+    // implementing XAResource, but this design is more standards friendly and thus portable.
+
+    private static final Logger log = Logger.getLogger(BridgeXAResource.class);
+
+    private transient volatile BridgeWrapper bridgeWrapper;
+
+    private volatile Uid externalTxId; // JTA i.e. parent id
+
+    private volatile String bridgeWrapperId; // XTS i.e. subordinate.
+
+    /**
+     * Create a new XAResource which wraps the subordinate WS-AT transaction.
+     *
+     * @param externalTxId the parent JTA transaction identifier.
+     * @param bridgeWrapper the control for the subordinate WS-AT transaction.
+     */
+    public BridgeXAResource(Uid externalTxId, BridgeWrapper bridgeWrapper)
+    {
+        log.trace("BridgeXARresource(TxId="+externalTxId+", BridgeWrapper="+bridgeWrapper+")");
+
+        this.externalTxId = externalTxId;
+        this.bridgeWrapper = bridgeWrapper;
+        bridgeWrapperId = bridgeWrapper.getIdentifier();
+    }
+
+    /**
+     * Serialization hook. Gathers and writes information needed for transaction recovery.
+     *
+     * @param out the stream to which the object state is serialized.
+     * @throws java.io.IOException if serialization fails.
+     */
+    private void writeObject(ObjectOutputStream out) throws IOException
+    {
+        log.trace("writeObject() for tx id="+externalTxId);
+
+        //out.defaultWriteObject();
+        out.writeObject(externalTxId);
+        out.writeObject(bridgeWrapperId);
+    }
+
+    /**
+     * Deserialization hook. Unpacks transaction recovery information and uses it to
+     * recover the subordinate transaction.
+     *
+     * @param in the stream from which to unpack the object state.
+     * @throws IOException if deserialzation and recovery fail.
+     * @throws ClassNotFoundException if deserialzation fails.
+     */
+    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
+    {
+        log.trace("readObject()");
+
+        //in.defaultReadObject();
+        externalTxId = (Uid)in.readObject();
+        bridgeWrapperId = (String)in.readObject();
+
+        try
+        {
+            bridgeWrapper = BridgeWrapper.recover(bridgeWrapperId);
+            // TODO: check for null!
+        }
+        catch(UnknownTransactionException unknownTransactionException)
+        {
+            log.error("Unable to recover subordinate transaction id="+bridgeWrapperId, unknownTransactionException);
+            IOException ioException = new IOException("unable to deserialize");
+            ioException.initCause(unknownTransactionException);
+            throw ioException;
+        }
+    }
+
+    /**
+     * Ask the resource manager to prepare for a transaction commit of the transaction specified in xid.
+     *
+     * @param xid A global transaction identifier
+     * @return A value indicating the resource manager's vote on the outcome of the transaction
+     * @throws XAException
+     */
+    public int prepare(Xid xid) throws XAException
+    {
+        log.trace("prepare(Xid="+xid+")");
+
+        // TwoPhaseOutcome needs converting to XAResource rtn type.
+        int twoPhaseOutcome = bridgeWrapper.prepare();
+
+        log.trace("prepare TwoPhaseOutcome is "+twoPhaseOutcome+"/"+TwoPhaseOutcome.stringForm(twoPhaseOutcome));
+
+        switch(twoPhaseOutcome)
+        {
+            case TwoPhaseOutcome.PREPARE_OK:
+                log.trace("prepare returning XAResource.XA_OK");
+                return XAResource.XA_OK;
+            case TwoPhaseOutcome.PREPARE_READONLY:
+                OutboundBridgeManager.removeMapping(externalTxId);
+                log.trace("prepare returning XAResource.XA_RDONLY");
+                return XAResource.XA_RDONLY;
+            default:
+                // TODO more find-grained error type handling
+                log.trace("prepare TwoPhaseOutcome is "+twoPhaseOutcome+"/"+
+                        TwoPhaseOutcome.stringForm(twoPhaseOutcome)+", throwing XAException...");
+                XAException xaException = new XAException("unexpected oucome: "+TwoPhaseOutcome.stringForm(twoPhaseOutcome));
+                xaException.errorCode = XAException.XA_RBROLLBACK;
+                throw xaException;
+        }
+    }
+
+    /**
+     * Informs the resource manager to roll back work done on behalf of a transaction branch.
+     *
+     * @param xid A global transaction identifier
+     * @throws XAException
+     */
+    public void rollback(Xid xid) throws XAException
+    {
+        log.trace("rollback(Xid="+xid+")");
+
+        try
+        {
+            bridgeWrapper.rollback();
+        }
+        finally
+        {
+            OutboundBridgeManager.removeMapping(externalTxId);
+        }
+    }
+
+    /**
+     * Commits the global transaction specified by xid.
+     *
+     * @param xid A global transaction identifier
+     * @param onePhase
+     * @throws XAException
+     */
+    public void commit(Xid xid, boolean onePhase) throws XAException
+    {
+        log.trace("commit(Xid="+xid+", onePhase="+onePhase+")");
+
+        try
+        {
+            if(onePhase)
+            {
+                // no shortcuts, we have to do prepare anyhow
+                if(prepare(xid) == XAResource.XA_RDONLY)
+                {
+                    return;
+                }
+            }
+
+            bridgeWrapper.commit();
+        }
+        finally
+        {
+            OutboundBridgeManager.removeMapping(externalTxId);
+        }
+    }
+
+    /**
+     * Starts work on behalf of a transaction branch specified in xid.
+     *
+     * @param xid A global transaction identifier
+     * @param flags
+     * @throws XAException
+     */
+    public void start(Xid xid, int flags) throws XAException
+    {
+        log.trace("start(Xid="+xid+", flags="+flags+")");
+
+        // do nothing
+    }
+
+    /**
+     * Ends the work performed on behalf of a transaction branch.
+     *
+     * @param xid A global transaction identifier
+     * @param flags
+     * @throws XAException
+     */
+    public void end(Xid xid, int flags) throws XAException
+    {
+        log.trace("end(Xid="+xid+", flags="+flags+")");
+
+        // do nothing
+    }
+
+    public boolean isSameRM(XAResource xaResource) throws XAException
+    {
+        log.trace("isSameRM(XAResource="+xaResource+")");
+
+        return false;  // TODO
+    }
+
+    public void forget(Xid xid) throws XAException
+    {
+        log.trace("forget(Xid="+xid+")");
+
+        // TODO
+    }
+
+    /**
+     * Obtains a list of prepared transaction branches from a resource manager.
+     *
+     * @param flag
+     * @return
+     * @throws XAException
+     */
+    public Xid[] recover(int flag) throws XAException
+    {
+        log.trace("recover(flag="+flag+")");
+
+        return new Xid[0];  // TODO
+    }
+
+    /**
+     * Sets the current transaction timeout value for this XAResource instance.
+     *
+     * @param seconds - The transaction timeout value in seconds.
+     * @return true if the transaction timeout value is set successfully; otherwise false.
+     * @throws XAException
+     */
+    public boolean setTransactionTimeout(int seconds) throws XAException
+    {
+        log.trace("setTransactionTimeout(seconds="+seconds+")");
+
+        return false;  // TODO
+    }
+
+    /**
+     * Obtains the current transaction timeout value set for this XAResource instance.
+     *
+     * @return the transaction timeout value in seconds.
+     * @throws XAException
+     */
+    public int getTransactionTimeout() throws XAException
+    {
+        log.trace("getTransactionTimeout()");
+
+        return 0;  // TODO
+    }
+}

Copied: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/JaxWSTxOutboundBridgeHandler.java (from rev 31937, labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/JaxWSTxOutboundBridgeHandler.java)
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/JaxWSTxOutboundBridgeHandler.java	                        (rev 0)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/JaxWSTxOutboundBridgeHandler.java	2010-03-05 11:17:50 UTC (rev 31955)
@@ -0,0 +1,142 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ *
+ * (C) 2009 @author Red Hat Middleware LLC
+ */
+package org.jboss.jbossts.txbridge.outbound;
+
+import org.apache.log4j.Logger;
+
+import javax.xml.ws.handler.Handler;
+import javax.xml.ws.handler.MessageContext;
+
+/**
+ * A handler that sits in the client side JAX-WS processing pipeline between the application
+ * and the XTS header context processor. Takes the JTA transaction context provided by the
+ * former and maps it to a WS-AT transaction context for use by the latter. Handles Thread
+ * association of the WS-AT context.
+ *
+ * Note: we assume that there is a JTA transaction context present and
+ * that the service needs a WS-AT context. The handler should not be registered on
+ * methods unless both these conditions hold.
+ *
+ * @author jonathan.halliday at redhat.com, 2009-02-10
+ */
+public class JaxWSTxOutboundBridgeHandler implements Handler
+{
+	private static final Logger log = Logger.getLogger(JaxWSTxOutboundBridgeHandler.class);
+
+	/**
+	 * Process a message. Determines if it is inbound or outbound and dispatches accordingly.
+	 *
+	 * @param msgContext the context to process
+	 * @return true on success, false on error
+	 */
+	public boolean handleMessage(MessageContext msgContext)
+	{
+		log.trace("handleMessage()");
+
+		Boolean outbound = (Boolean)msgContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+		if (outbound == null)
+		   throw new IllegalStateException("Cannot obtain required property: " + MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+
+		return outbound ? handleOutbound(msgContext) : handleInbound(msgContext);
+	}
+
+	/**
+	 * Tidy up the Transaction/Thread association before faults are thrown back to the client.
+	 *
+	 * @param messageContext unused
+	 * @return true on success, false on error
+	 */
+	public boolean handleFault(MessageContext messageContext)
+	{
+		log.trace("handleFault()");
+
+		return suspendTransaction();
+	}
+
+	public void close(MessageContext messageContext)
+	{
+		log.trace("close()");
+	}
+
+	/**
+     * Tidy up the Transaction/Thread association before returning a message to the client.
+	 *
+	 * @param msgContext unused
+	 * @return true on success, false on error
+	 */
+	protected boolean handleInbound(MessageContext msgContext)
+	{
+		log.trace("handleInbound()");
+
+		return suspendTransaction();
+	}
+
+	/**
+     * Process outbound messages by mapping the JTA transaction context
+     * to a WS-AT one and associating the latter to the current Thread.
+	 *
+	 * @param msgContext unused
+	 * @return true on success, false on error
+	 */
+	protected boolean handleOutbound(MessageContext msgContext)
+    {
+		log.trace("handleOutbound()");
+
+		try
+		{
+			OutboundBridge outboundBridge = OutboundBridgeManager.getOutboundBridge();
+			outboundBridge.start();
+		}
+		catch (Exception e)
+		{
+			log.error(e);
+			return false;
+		}
+
+		return true;
+	}
+
+	/**
+	 * Break the association between the WS-AT transaction context and the calling Thread.
+     *
+     * @return true on success, false on error
+	 */
+	private boolean suspendTransaction()
+    {
+		log.trace("suspendTransaction()");
+
+		try
+		{
+			OutboundBridge outboundBridge = OutboundBridgeManager.getOutboundBridge();
+			outboundBridge.stop();
+		}
+		catch (Exception e)
+		{
+			log.error(e);
+            return false;
+		}
+
+        return true;
+	}
+}
\ No newline at end of file

Copied: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/OutboundBridge.java (from rev 31937, labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/OutboundBridge.java)
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/OutboundBridge.java	                        (rev 0)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/OutboundBridge.java	2010-03-05 11:17:50 UTC (rev 31955)
@@ -0,0 +1,88 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ *
+ * (C) 2009 @author Red Hat Middleware LLC
+ */
+package org.jboss.jbossts.txbridge.outbound;
+
+import org.apache.log4j.Logger;
+import org.jboss.jbossts.xts.bridge.at.BridgeWrapper;
+import com.arjuna.mw.wst11.TransactionManagerFactory;
+import com.arjuna.mw.wst.TxContext;
+import com.arjuna.wst.SystemException;
+import com.arjuna.wst.UnknownTransactionException;
+
+/**
+ * Manages Thread association of the interposed coordinator.
+ * Typically called from handlers in the WS stack.
+ *
+ * @author jonathan.halliday at redhat.com, 2009-02-10
+ */
+public class OutboundBridge
+{
+    private static final Logger log = Logger.getLogger(OutboundBridge.class);
+
+    /**
+     * Management object for the subordinate transaction
+     */
+    private final BridgeWrapper bridgeWrapper;
+
+    /**
+     * Create a new OutboundBridge to manage the given subordinate WS-AT transaction.
+     *
+     * @param bridgeWrapper the subordinate transaction controller
+     */
+    public OutboundBridge(BridgeWrapper bridgeWrapper)
+    {
+        log.trace("OutboundBridge(BridgeWrapper="+bridgeWrapper+")");
+
+        this.bridgeWrapper = bridgeWrapper;
+    }
+
+    /**
+     * Associate the WS-AT transaction to the current Thread.
+     * Typically used by the client side outbound handler.
+     *
+     * @throws UnknownTransactionException
+     * @throws SystemException
+     */
+    public void start() throws UnknownTransactionException, SystemException
+    {
+		log.trace("start(BridgeWrapper="+bridgeWrapper+")");
+
+        TxContext txContext = bridgeWrapper.getContext();
+
+        TransactionManagerFactory.transactionManager().resume(txContext);
+	}
+
+    /**
+     * Disassociate the WS-AT transaction from the current Thread.
+     * Typically used by the client side inbound handler.
+     *
+     * @throws SystemException
+     */
+    public void stop() throws SystemException
+    {
+        log.trace("stop(BridgeWrapper="+bridgeWrapper+")");
+
+        TransactionManagerFactory.transactionManager().suspend();
+    }
+}

Copied: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/OutboundBridgeManager.java (from rev 31937, labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/OutboundBridgeManager.java)
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/OutboundBridgeManager.java	                        (rev 0)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/OutboundBridgeManager.java	2010-03-05 11:17:50 UTC (rev 31955)
@@ -0,0 +1,136 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ *
+ * (C) 2009 @author Red Hat Middleware LLC
+ */
+package org.jboss.jbossts.txbridge.outbound;
+
+import com.arjuna.ats.jta.TransactionManager;
+import com.arjuna.ats.jta.transaction.Transaction;
+import com.arjuna.ats.arjuna.common.Uid;
+
+import javax.transaction.SystemException;
+import javax.transaction.RollbackException;
+import javax.transaction.Synchronization;
+import javax.transaction.xa.XAResource;
+
+import org.apache.log4j.Logger;
+import org.jboss.jbossts.xts.bridge.at.BridgeWrapper;
+
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Maintains the mapping data that relates JTA transactions to WS-AT subordinate transactions and related objects.
+ *
+ * The mappings are scoped to the singleton instance of this class and its lifetime.
+ * This poses problems where you have more than one instance (classloading, clusters)
+ * or where you need crash recovery. It short, it's rather limited.
+ *
+ * @author jonathan.halliday at redhat.com, 2009-02-10
+ */
+public class OutboundBridgeManager
+{
+    private static final Logger log = Logger.getLogger(OutboundBridgeManager.class);
+
+    // maps JTA Tx Id to OutboundBridge instance.
+    private static final ConcurrentMap<Uid, org.jboss.jbossts.txbridge.outbound.OutboundBridge> outboundBridgeMappings = new ConcurrentHashMap<Uid, org.jboss.jbossts.txbridge.outbound.OutboundBridge>();
+
+    /**
+     * Return an OutboundBridge instance that maps the current Thread's JTA transaction context
+     * to a WS-AT transaction context. Control of the latter is provided by the returned instance.
+     *
+     * @return as OutboundBridge corresponding to the calling Thread's current JTA transaction context.
+     */
+	public static org.jboss.jbossts.txbridge.outbound.OutboundBridge getOutboundBridge()
+	{
+		log.trace("getOutboundBridge()");
+
+        try
+        {
+            Transaction transaction = (Transaction)TransactionManager.transactionManager().getTransaction();
+
+            Uid externalTxId = transaction.get_uid();
+
+            if(!outboundBridgeMappings.containsKey(externalTxId)) {
+                createMapping(transaction, externalTxId);
+            }
+
+            return outboundBridgeMappings.get(externalTxId);
+
+        }
+        catch(SystemException e)
+        {
+            log.error("problem", e);
+        }
+
+        return null;
+	}
+
+    /**
+     * Remove the mapping for the given externalTxId. This should be called for gc when the tx is finished.
+     *
+     * @param externalTxId The JTA transaction identifier.
+     */
+    public static synchronized void removeMapping(Uid externalTxId)
+    {
+        log.trace("removeMapping(externalTxId="+externalTxId+")");
+
+        if(externalTxId != null) {
+            outboundBridgeMappings.remove(externalTxId);
+        }
+    }
+
+    /**
+     * Create a WS-AT transaction mapping and support objects for a given JTA transaction context.
+     *
+     * @param externalTxId The JTA transaction identifier.
+     * @throws SystemException
+     */
+    private static synchronized void createMapping(Transaction transaction, Uid externalTxId) throws SystemException
+    {
+        log.trace("createmapping(externalTxId="+externalTxId+")");
+
+        if(outboundBridgeMappings.containsKey(externalTxId)) {
+            return;
+        }
+
+        // TODO: allow params to be configurable, or at least pass timeout down.
+        BridgeWrapper bridgeWrapper = BridgeWrapper.create(0, false);
+
+        org.jboss.jbossts.txbridge.outbound.OutboundBridge outboundBridge = new org.jboss.jbossts.txbridge.outbound.OutboundBridge(bridgeWrapper);
+        XAResource xaResource = new org.jboss.jbossts.txbridge.outbound.BridgeXAResource(externalTxId, bridgeWrapper);
+        Synchronization synchronization = new org.jboss.jbossts.txbridge.outbound.BridgeSynchronization(bridgeWrapper);
+
+        try
+        {
+            transaction.enlistResource(xaResource);
+            transaction.registerSynchronization(synchronization);
+        }
+        catch(RollbackException e)
+        {
+            log.error("Unable to enlist BridgeXAResource or register BridgeSynchronization: ", e);
+            throw new SystemException(e.toString());
+        }
+
+        outboundBridgeMappings.put(externalTxId, outboundBridge);
+    }
+}
\ No newline at end of file

Added: labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/OutboundBridgeRecoveryManager.java
===================================================================
--- labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/OutboundBridgeRecoveryManager.java	                        (rev 0)
+++ labs/jbosstm/trunk/txbridge/src/org/jboss/jbossts/txbridge/outbound/OutboundBridgeRecoveryManager.java	2010-03-05 11:17:50 UTC (rev 31955)
@@ -0,0 +1,81 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc. and/or its affiliates,
+ * 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) 2010,
+ * @author JBoss, by Red Hat.
+ */
+package org.jboss.jbossts.txbridge.outbound;
+
+import com.arjuna.ats.arjuna.recovery.RecoveryManager;
+import com.arjuna.ats.arjuna.recovery.RecoveryModule;
+import org.apache.log4j.Logger;
+
+/**
+ * Integrates with JBossAS MC lifecycle and JBossTS recovery manager to provide
+ * recovery services for outbound bridged transactions.
+ *
+ * @author jonathan.halliday at redhat.com, 2010-03-05
+ */
+public class OutboundBridgeRecoveryManager implements RecoveryModule
+{
+    private static final Logger log = Logger.getLogger(OutboundBridgeRecoveryManager.class);
+
+    private final RecoveryManager acRecoveryManager = RecoveryManager.manager();
+
+    /**
+     * MC lifecycle callback, used to register components with the recovery manager.
+     */
+    public void start()
+    {
+        log.info("OutboundBridgeRecoveryManager starting");
+
+        acRecoveryManager.addModule(this);
+    }
+
+    /**
+     * MC lifecycle callback, used to unregister components from the recovery manager.
+     */
+    public void stop()
+    {
+        log.info("OutboundBridgeRecoveryManager stopping");
+
+        acRecoveryManager.removeModule(this, false);
+    }
+
+    /**
+     * Called by the RecoveryManager at start up, and then
+     * PERIODIC_RECOVERY_PERIOD seconds after the completion, for all RecoveryModules,
+     * of the second pass
+     */
+    @Override
+    public void periodicWorkFirstPass()
+    {
+        log.trace("periodicWorkFirstPass()");
+    }
+
+    /**
+     * Called by the RecoveryManager RECOVERY_BACKOFF_PERIOD seconds
+     * after the completion of the first pass
+     */
+    @Override
+    public void periodicWorkSecondPass()
+    {
+        log.trace("periodicWorkSecondPass()");
+
+        // TODO BridgeWrapper recovery scan for orphans - pending JBTM-725 work.
+    }
+}

Modified: labs/jbosstm/trunk/txbridge/tests/dd/jaxws-handlers-client.xml
===================================================================
--- labs/jbosstm/trunk/txbridge/tests/dd/jaxws-handlers-client.xml	2010-03-05 05:45:20 UTC (rev 31954)
+++ labs/jbosstm/trunk/txbridge/tests/dd/jaxws-handlers-client.xml	2010-03-05 11:17:50 UTC (rev 31955)
@@ -37,7 +37,7 @@
 
 		<handler>
 			<handler-name>TransactionBridgeHandler</handler-name>
-			<handler-class>org.jboss.jbossts.txbridge.JaxWSTxOutboundBridgeHandler</handler-class>
+			<handler-class>org.jboss.jbossts.txbridge.outbound.JaxWSTxOutboundBridgeHandler</handler-class>
 		</handler>
 
 		<handler>

Modified: labs/jbosstm/trunk/txbridge/tests/dd/jaxws-handlers-server.xml
===================================================================
--- labs/jbosstm/trunk/txbridge/tests/dd/jaxws-handlers-server.xml	2010-03-05 05:45:20 UTC (rev 31954)
+++ labs/jbosstm/trunk/txbridge/tests/dd/jaxws-handlers-server.xml	2010-03-05 11:17:50 UTC (rev 31955)
@@ -37,7 +37,7 @@
 
         <handler>
             <handler-name>TransactionBridgeHandler</handler-name>
-            <handler-class>org.jboss.jbossts.txbridge.JaxWSTxInboundBridgeHandler</handler-class>
+            <handler-class>org.jboss.jbossts.txbridge.inbound.JaxWSTxInboundBridgeHandler</handler-class>
         </handler>
 
 		<handler>



More information about the jboss-svn-commits mailing list