[jboss-svn-commits] JBL Code SVN: r12675 - in labs/jbosstm/workspace/maciej.machulak/code/demo/bridge: src and 8 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Mon Jun 18 21:45:02 EDT 2007


Author: maciej.machulak
Date: 2007-06-18 21:45:02 -0400 (Mon, 18 Jun 2007)
New Revision: 12675

Added:
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/JaxWSServerHeaderContextProcessor.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/BACompensatedBy.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/BAService.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/BAServiceType.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/BATransactionAttribute.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/BATransactionAttributeType.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/CompensationIdentifier.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/CompensationManagement.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/CompensationObject.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/BridgeParticipantAT.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/DummyParticipantAT.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/InboundBridge.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/JaxWSTransactionBridgeHandler.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/JaxWSTransactionSpecifierHandler.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/TxBridgeManager.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/BABridgeManager.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/CoordinatorCompletionParticipantBA.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/InboundBABridge.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/JaxWSBASpecifierHandler.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/JaxWSBusinessActivityHandler.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/ParticipantCompletionParticipantBA.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/data/
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/data/ClassInformation.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/data/CompensationObject.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/data/MethodInformation.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/data/ServiceDescription.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/BAProperties.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/BATaskIdentifierFactory.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/ClassBAVisitor.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/ClassInformationManager.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/CompensationManager.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/CompensationService.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/JBossServiceAccessFactory.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/SOAPProcessor.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/ServiceAccessFactory.java
   labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/SimpleBATaskIdentifierFactory.java
Log:


Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/JaxWSServerHeaderContextProcessor.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/JaxWSServerHeaderContextProcessor.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/JaxWSServerHeaderContextProcessor.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,273 @@
+package org.jboss.txbridge;
+
+import org.apache.log4j.Logger;
+
+import javax.xml.ws.handler.MessageContext;
+import javax.xml.ws.handler.soap.SOAPHandler;
+import javax.xml.ws.handler.soap.SOAPMessageContext;
+import javax.xml.namespace.QName;
+import javax.xml.soap.*;
+
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import com.arjuna.webservices.wscoor.CoordinationConstants;
+import com.arjuna.webservices.wscoor.CoordinationContextType;
+import com.arjuna.webservices.wsat.AtomicTransactionConstants;
+import com.arjuna.webservices.wsba.BusinessActivityConstants;
+import com.arjuna.mw.wst.common.CoordinationContextHelper;
+import com.arjuna.mw.wst.common.SOAPUtil;
+import com.arjuna.mw.wst.*;
+
+
+/**
+ * TODO: make this play nice alongside com.arjuna.mw.wst.service.JaxRPCHeaderContextProcessor
+ * - factor out common base class or suchlike
+ */
+public class JaxWSServerHeaderContextProcessor implements SOAPHandler
+{
+	private static Logger log = Logger.getLogger(JaxWSServerHeaderContextProcessor.class);
+
+	private String handlerName;
+
+	public String getHandlerName()
+	{
+	   return handlerName;
+	}
+
+	public void setHandlerName(String handlerName)
+	{
+	   this.handlerName = handlerName;
+	}
+
+	public boolean handleMessage(MessageContext msgContext)
+	{
+	   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);
+	}
+
+
+	public boolean handleFault(MessageContext messagecontext)
+	{
+		suspendTransaction() ;
+		return true;
+	}
+
+	public void close(MessageContext messageContext)
+	{
+	}
+
+	public String toString()
+	{
+	   return (handlerName != null ? handlerName : super.toString());
+	}
+
+
+
+   // The header blocks that can be processed by this Handler instance
+   private Set<QName> headers = new HashSet<QName>();
+
+   /** Gets the header blocks that can be processed by this Handler instance.
+    */
+   public Set<QName> getHeaders()
+   {
+	   log.info("getHeaders");
+
+	   Set<QName> headerSet = new HashSet<QName>();
+	   headerSet.add(new QName(CoordinationConstants.WSCOOR_NAMESPACE, CoordinationConstants.WSCOOR_ELEMENT_COORDINATION_CONTEXT));
+
+	  return headerSet;
+   }
+
+   /** Sets the header blocks that can be processed by this Handler instance.
+    */
+   public void setHeaders(Set<QName> headers)
+   {
+      this.headers = headers;
+   }
+
+
+
+   protected boolean handleInbound(MessageContext msgContext)
+   {
+      log.info("handleInbound");
+/*
+      try
+      {
+         SOAPMessage soapMessage = ((SOAPMessageContext)msgContext).getMessage();
+         SOAPHeader soapHeader = soapMessage.getSOAPHeader();
+         SOAPBody soapBody = soapMessage.getSOAPBody();
+
+         SOAPFactory soapFactory = SOAPFactory.newInstance();
+         Name headerName = soapFactory.createName("LogHandlerInbound", "ns1", "http://somens");
+         SOAPHeaderElement she = soapHeader.addHeaderElement(headerName);
+         she.setValue("true");
+
+         SOAPBodyElement soapBodyElement = (SOAPBodyElement)soapBody.getChildElements().next();
+         SOAPElement soapElement = (SOAPElement)soapBodyElement.getChildElements().next();
+         String value = soapElement.getValue();
+         soapElement.setValue(value + "|LogIn");
+      }
+      catch (SOAPException e)
+      {
+         throw  new WebServiceException(e);
+      }
+*/
+
+        final SOAPMessageContext soapMessageContext = (SOAPMessageContext)msgContext ;
+        final SOAPMessage soapMessage = soapMessageContext.getMessage() ;
+
+		if (soapMessage != null)
+        {
+            try
+            {
+                final SOAPEnvelope soapEnvelope = soapMessage.getSOAPPart().getEnvelope() ;
+                final SOAPHeader soapHeader = soapEnvelope.getHeader() ;
+                final SOAPHeaderElement soapHeaderElement = getHeaderElement(soapHeader, CoordinationConstants.WSCOOR_NAMESPACE, CoordinationConstants.WSCOOR_ELEMENT_COORDINATION_CONTEXT) ;
+
+                if (soapHeaderElement != null)
+                {
+                    final CoordinationContextType cc = CoordinationContextHelper.deserialise(soapEnvelope, soapHeaderElement) ;
+                    final String coordinationType = cc.getCoordinationType().getValue() ;
+                    if (AtomicTransactionConstants.WSAT_PROTOCOL.equals(coordinationType))
+                    {
+                        final TxContext txContext = new com.arjuna.mwlabs.wst.at.context.TxContextImple(cc) ;
+                        TransactionManagerFactory.transactionManager().resume(txContext) ;
+                        clearMustUnderstand(soapHeader, soapHeaderElement) ;
+                    }
+                    else if (BusinessActivityConstants.WSBA_PROTOCOL_ATOMIC_OUTCOME.equals(coordinationType))
+                    {
+                        final TxContext txContext = new com.arjuna.mwlabs.wst.ba.context.TxContextImple(cc);
+                        BusinessActivityManagerFactory.businessActivityManager().resume(txContext) ;
+                        clearMustUnderstand(soapHeader, soapHeaderElement) ;
+                    }
+                    else
+                    {
+						log.warn("handleInbound: unknown type="+coordinationType);
+                    }
+                }
+            }
+            catch (final Throwable th)
+            {
+				log.warn("handleInbound: ", th);
+            }
+        }
+        return true ;
+   }
+
+
+   protected boolean handleOutbound(MessageContext msgContext)
+   {
+	   log.info("handleOutbound");
+	   suspendTransaction() ;
+/*
+      try
+      {
+         SOAPMessage soapMessage = ((SOAPMessageContext)msgContext).getMessage();
+         SOAPHeader soapHeader = soapMessage.getSOAPHeader();
+         SOAPBody soapBody = soapMessage.getSOAPBody();
+
+         SOAPFactory soapFactory = SOAPFactory.newInstance();
+         Name headerName = soapFactory.createName("LogHandlerOutbound", "ns1", "http://somens");
+         SOAPHeaderElement she = soapHeader.addHeaderElement(headerName);
+         she.setValue("true");
+
+         SOAPBodyElement soapBodyElement = (SOAPBodyElement)soapBody.getChildElements().next();
+         SOAPElement soapElement = (SOAPElement)soapBodyElement.getChildElements().next();
+         String value = soapElement.getValue();
+         soapElement.setValue(value + "|LogOut");
+      }
+      catch (SOAPException e)
+      {
+         throw  new WebServiceException(e);
+      }
+*/
+      return true;
+   }
+
+	    private void suspendTransaction()
+    {
+        try
+        {
+            /*
+             * There should either be an Atomic Transaction *or* a Business Activity
+             * associated with the thread.
+             */
+            final TransactionManager transactionManager = TransactionManagerFactory.transactionManager() ;
+            final BusinessActivityManager businessActivityManager = BusinessActivityManagerFactory.businessActivityManager() ;
+
+            if (transactionManager != null)
+            {
+                transactionManager.suspend() ;
+            }
+
+            if (businessActivityManager != null)
+            {
+                businessActivityManager.suspend() ;
+            }
+        }
+        catch (final Throwable th)
+        {
+			log.warn("suspendTransaction", th);
+        }
+    }
+
+		private SOAPHeaderElement getHeaderElement(final SOAPHeader soapHeader, final String uri, final String name)
+        throws SOAPException
+		{
+        if (soapHeader != null)
+        {
+            final Iterator headerIter = SOAPUtil.getChildElements(soapHeader) ;
+            while(headerIter.hasNext())
+            {
+                final SOAPHeaderElement current = (SOAPHeaderElement)headerIter.next() ;
+                final Name currentName = current.getElementName() ;
+                if ((currentName != null) &&
+                    match(name, currentName.getLocalName()) &&
+                    match(uri, currentName.getURI()))
+                {
+                    return current ;
+                }
+            }
+        }
+        return null ;
+    }
+
+    /**
+     * Do the two references match?
+     * @param lhs The first reference.
+     * @param rhs The second reference.
+     * @return true if the references are both null or if they are equal.
+     */
+    private boolean match(final Object lhs, final Object rhs)
+    {
+        if (lhs == null)
+        {
+            return (rhs == null) ;
+        }
+        else
+        {
+            return lhs.equals(rhs) ;
+        }
+    }
+
+	    /**
+     * Clear the soap MustUnderstand.
+     * @param soapHeader The SOAP header.
+     * @param soapHeaderElement The SOAP header element.
+     */
+    private void clearMustUnderstand(final SOAPHeader soapHeader, final SOAPHeaderElement soapHeaderElement)
+    	throws SOAPException
+    {
+	final Name headerName = soapHeader.getElementName() ;
+
+	final SOAPFactory factory = SOAPFactory.newInstance() ;
+	final Name attributeName = factory.createName("mustUnderstand", headerName.getPrefix(), headerName.getURI()) ;
+
+	soapHeaderElement.removeAttribute(attributeName) ;
+    }
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/BACompensatedBy.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/BACompensatedBy.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/BACompensatedBy.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,16 @@
+package org.jboss.txbridge.annotations;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Author: Maciej Machulak
+ */
+ at Target(ElementType.METHOD)
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface BACompensatedBy 
+{
+    String value();
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/BAService.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/BAService.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/BAService.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,16 @@
+package org.jboss.txbridge.annotations;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Author: Maciej Machulak
+ */
+ at Target(ElementType.METHOD)
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface BAService
+{
+    BAServiceType value() default BAServiceType.MODIFY;
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/BAServiceType.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/BAServiceType.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/BAServiceType.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,14 @@
+package org.jboss.txbridge.annotations;
+
+/**
+ * Author: Maciej Machulak
+ */
+public enum BAServiceType {
+    READONLY,
+    MODIFY,
+    SELFCONTAINED
+}
+
+/*
+READ_ONLY, DELETE, SELF_CONTAINED, STATE_MANAGED
+ */

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/BATransactionAttribute.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/BATransactionAttribute.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/BATransactionAttribute.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,16 @@
+package org.jboss.txbridge.annotations;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+/**
+ * Author: Maciej Machulak
+ */
+ at Target(ElementType.METHOD)
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface BATransactionAttribute 
+{
+    BATransactionAttributeType value() default BATransactionAttributeType.PARTICIPANT_COMPLETION;
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/BATransactionAttributeType.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/BATransactionAttributeType.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/BATransactionAttributeType.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,10 @@
+package org.jboss.txbridge.annotations;
+
+/**
+ * Author: Maciej Machulak
+ */
+public enum BATransactionAttributeType
+{
+    PARTICIPANT_COMPLETION,
+    COORDINATOR_COMPLETION
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/CompensationIdentifier.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/CompensationIdentifier.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/CompensationIdentifier.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,15 @@
+package org.jboss.txbridge.annotations;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Author: Maciej Machulak
+ */
+ at Target(ElementType.FIELD)
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface CompensationIdentifier
+{
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/CompensationManagement.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/CompensationManagement.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/CompensationManagement.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,15 @@
+package org.jboss.txbridge.annotations;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Author: Maciej Machulak
+ */
+ at Target(ElementType.FIELD)
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface CompensationManagement
+{   
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/CompensationObject.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/CompensationObject.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/annotations/CompensationObject.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,16 @@
+package org.jboss.txbridge.annotations;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Author: Maciej Machulak
+ */
+ at Target(ElementType.FIELD)
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface CompensationObject
+{
+    String originalMethod() default "";
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/BridgeParticipantAT.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/BridgeParticipantAT.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/BridgeParticipantAT.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,154 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * (C) 2007,
+ * @author JBoss Inc.
+ */
+package org.jboss.txbridge.at;
+
+import com.arjuna.wst.*;
+import com.arjuna.ats.internal.jta.transaction.arjunacore.jca.XATerminatorImple;
+import org.apache.log4j.Logger;
+
+import javax.transaction.xa.Xid;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+
+/**
+ * Provides mapping between WS-AT Participant interface
+ * and an underlying JTA subtransaction coordinator.
+ *
+ * @author jonathan.halliday at redhat.com, 2007-04-30
+ */
+public class BridgeParticipantAT  implements Durable2PCParticipant
+{
+	private static Logger log = Logger.getLogger(BridgeParticipantAT.class);
+
+	private XATerminatorImple xaTerminator;
+	private Xid xid;
+
+	BridgeParticipantAT(XATerminatorImple xaTerminator, Xid xid)
+    {
+		log.info("BridgeParticipantAT(XATerminatorImple="+xaTerminator+", Xid="+xid+")");
+
+		this.xaTerminator = xaTerminator;
+		this.xid = xid;
+	}
+
+    /**
+	 *
+	 *
+     * 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.info("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.info("prepare on Xid="+xid+" returning Prepared");
+				return new Prepared();
+			} else {
+				log.info("prepare on Xid="+xid+" returning ReadOnly");
+				return new ReadOnly();
+			}
+
+		} catch(XAException e) {
+			log.info("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.info("commit(Xid="+xid+")");
+
+		try
+		{
+			xaTerminator.commit(xid, false);
+			log.info("commit on Xid="+xid+" OK");
+		}
+		catch (XAException e)
+		{
+			log.info("commit on Xid="+xid+" failed", e);
+		}
+    }
+
+    /**
+	 *
+	 *
+     * 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.info("rollback(Xid="+xid+")");
+
+		try
+		{
+			xaTerminator.rollback(xid);
+			log.info("rollback on Xid="+xid+" OK");
+		}
+		catch (XAException e)
+		{
+			log.info("rollback on Xid="+xid+" failed", e);
+		}
+    }
+
+    /**
+     * 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.info("unknown(Xid="+xid+"): NOT IMPLEMENTED");
+		// used for calbacks during crash recovery. This impl is not recoverable
+    }
+
+    /**
+     * 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.info("error(Xid="+xid+"): NOT IMPLEMENTED");
+        // used for calbacks during crash recovery. This impl is not recoverable
+    }
+}
+

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/DummyParticipantAT.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/DummyParticipantAT.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/DummyParticipantAT.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,42 @@
+package org.jboss.txbridge.at;
+
+import com.arjuna.wst.*;
+import org.apache.log4j.Logger;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class DummyParticipantAT implements Durable2PCParticipant {
+
+
+    public DummyParticipantAT() {
+        log.info("constructor");
+    }
+
+    private static Logger log = Logger.getLogger(DummyParticipantAT.class);
+
+    public Vote prepare() throws WrongStateException, SystemException {
+        log.info("prepare()");
+        return new Prepared();
+    }
+
+    public void commit() throws WrongStateException, SystemException {
+        log.info("commit()");
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public void rollback() throws WrongStateException, SystemException {
+        log.info("rollback()");
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public void unknown() throws SystemException {
+        log.info("unknown()");
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public void error() throws SystemException {
+        log.info("error()");
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/InboundBridge.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/InboundBridge.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/InboundBridge.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,110 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * (C) 2007,
+ * @author JBoss Inc.
+ */
+package org.jboss.txbridge.at;
+
+import com.arjuna.ats.internal.jta.transaction.arjunacore.subordinate.jca.TransactionImple;
+import com.arjuna.ats.internal.jta.transaction.arjunacore.jca.TxImporter;
+import com.arjuna.ats.jta.TransactionManager;
+
+import javax.transaction.xa.Xid;
+import javax.transaction.xa.XAException;
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+import javax.transaction.InvalidTransactionException;
+
+
+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 Logger log = Logger.getLogger(InboundBridge.class);
+
+	private Xid xid;
+
+	InboundBridge(Xid xid) throws XAException, SystemException {
+		log.info("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.info("start(Xid="+xid+")");
+
+		TransactionImple 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.info("stop("+xid+")");
+
+		TransactionImple tx = getTransaction();
+
+		TransactionManager.transactionManager().suspend();
+	}
+
+	/**
+	 * Get the JTA Transaction which corresponds to the Xid of the instance.
+	 *
+	 * @return
+	 * @throws XAException
+	 * @throws SystemException
+	 */
+	private TransactionImple getTransaction()
+			throws XAException, SystemException
+	{
+		// TODO: make jta/jts pluggable - diff TxImporters hence InboundBridges ?
+		TransactionImple tx = TxImporter.importTransaction(xid);
+
+		switch (tx.getStatus())
+		{
+			case Status.STATUS_ACTIVE:
+				break;
+			default:
+				throw new IllegalStateException("Transaction not in state ACTIVE");
+		}
+		return tx;
+	}
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/JaxWSTransactionBridgeHandler.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/JaxWSTransactionBridgeHandler.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/JaxWSTransactionBridgeHandler.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,261 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * (C) 2007,
+ * @author JBoss Inc.
+ */
+package org.jboss.txbridge.at;
+
+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 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 their 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.
+ * TODO: make this more flexible (ws-at policy and/or lazy init of JTA context.)
+ *
+ * TODO: provide a JAX-RPC version of this handler too?
+ *
+ * @author jonathan.halliday at redhat.com, 2007-04-30
+ */
+public class JaxWSTransactionBridgeHandler implements Handler
+{
+    private static Logger log = Logger.getLogger(JaxWSTransactionBridgeHandler.class);
+
+    /**
+     * Process a message. Determins if it's inbound or outbound and dispatches accordingly.
+     *
+     * @param msgContext
+     * @return
+     */
+    public boolean handleMessage(MessageContext msgContext)
+    {
+        log.debug("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
+     * @return
+     */
+    public boolean handleFault(MessageContext messageContext)
+    {
+        log.debug("handleFault()");
+        String transactionType = (String) messageContext.get("TransactionAttributeType");
+
+        if (transactionType == null)
+        {
+            log.info("transactionType is null");
+            return true;
+        }
+        else if ( transactionType.equals("MANDATORY"))
+        {
+            log.info("transactionType is mandatory");
+            suspendTransaction();
+        }
+        else if ( transactionType.equals("REQUIRED"))
+        {
+            log.info("transactionType is required");
+            suspendTransaction();
+        }
+        else if ( transactionType.equals("REQUIRES_NEW "))
+        {
+            log.info("transactionType is requires_new");
+            return true;
+        }
+        else if ( transactionType.equals("SUPPORTS"))
+        {
+            log.info("transactionType is supports");
+            suspendTransaction();
+        }
+        else if ( transactionType.equals("NOT_SUPPORTED"))
+        {
+            log.info("transactionType is not_supported");
+            return true;
+        }
+        return true;
+    }
+
+    public void close(MessageContext messageContext)
+    {
+        log.debug("close()");
+    }
+
+    /**
+     * Process inbound messages by mapping the WS transaction context
+     * to a JTA one and associating the latter to the current Thread.
+     *
+     * @param msgContext
+     * @return
+     */
+    protected boolean handleInbound(MessageContext msgContext)
+    {
+        log.debug("handleInbound()");
+        String transactionType = (String) msgContext.get("TransactionAttributeType");
+
+        // If there was no WS transaction
+        if (transactionType == null)
+        {
+            log.info("transactionType is null");
+            return true;
+        }
+
+        // If there is a WS transaction
+
+        // If the method must be executed within a transaction
+        if ( transactionType.equals("MANDATORY"))
+        {
+            log.info("transactionType is mandatory");
+            try
+            {
+                InboundBridge inboundBridge = org.jboss.txbridge.at.TxBridgeManager.getInboundBridge();
+                inboundBridge.start();
+            }
+            catch (Exception e)
+            {
+                log.error(e);
+                return false;
+            }
+        }
+        // If the method needs a transaction (either by client or its own)
+        else if ( transactionType.equals("REQUIRED"))
+        {
+            log.info("transactionType is required");
+            try
+            {
+                InboundBridge inboundBridge = org.jboss.txbridge.at.TxBridgeManager.getInboundBridge();
+                inboundBridge.start();
+            }
+            catch (Exception e)
+            {
+                log.error(e);
+                return false;
+            }
+        }
+        // If the method will start a new transaction anyway
+        else if ( transactionType.equals("REQUIRES_NEW "))
+        {
+            log.info("transactionType is requires_new");
+            return true;
+        }
+        // If the method does not care
+        else if ( transactionType.equals("SUPPORTS"))
+        {
+            log.info("transactionType is supports");
+            try
+            {
+                InboundBridge inboundBridge = org.jboss.txbridge.at.TxBridgeManager.getInboundBridge();
+                inboundBridge.start();
+            }
+            catch (Exception e)
+            {
+                log.error(e);
+                return false;
+            }
+
+        }
+        // If the method does not support a transaction
+        else if ( transactionType.equals("NOT_SUPPORTED"))
+        {
+            log.info("transactionType is not_supported");
+            try
+            {
+                org.jboss.txbridge.at.TxBridgeManager.startDummyTransaction();
+            }
+            catch (Exception e)
+            {
+                return false;
+            }
+            return true;
+        }
+        return true;
+    }
+
+    /**
+     * Tidy up the Transaction/Thread association before returning a message to the client.
+     *
+     * @param msgContext
+     * @return
+     */
+    protected boolean handleOutbound(MessageContext msgContext) {
+        log.debug("handleOutbound()");
+        String transactionType = (String) msgContext.get("TransactionAttributeType");
+
+        if (transactionType == null)
+        {
+            log.info("transactionType is null");
+            return true;
+        }
+        else if ( transactionType.equals("MANDATORY"))
+        {
+            suspendTransaction();
+        }
+        else if ( transactionType.equals("REQUIRED"))
+        {
+            log.info("transactionType is required");
+            suspendTransaction();
+        }
+        else if ( transactionType.equals("REQUIRES_NEW "))
+        {
+            log.info("transactionType is requires_new");
+            return true;
+        }
+        else if ( transactionType.equals("SUPPORTS"))
+        {
+            log.info("transactionType is supports");
+            suspendTransaction();
+        }
+        else if ( transactionType.equals("NOT_SUPPORTED"))
+        {
+            log.info("transactionType is not supported");
+            return true;
+        }
+        return true;
+    }
+
+    /**
+     * Break the association between the JTA transaction context and the calling Thread.
+     */
+    private void suspendTransaction() {
+        log.debug("suspendTransaction()");
+
+        try
+        {
+            InboundBridge inboundBridge = org.jboss.txbridge.at.TxBridgeManager.getInboundBridge();
+            inboundBridge.stop();
+        }
+        catch (Exception e)
+        {
+            log.error(e);
+        }
+    }
+}
\ No newline at end of file

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/JaxWSTransactionSpecifierHandler.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/JaxWSTransactionSpecifierHandler.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/JaxWSTransactionSpecifierHandler.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,149 @@
+package org.jboss.txbridge.at;
+
+import org.apache.log4j.Logger;
+import org.jboss.ws.core.soap.MessageContextAssociation;
+import org.jboss.ws.core.CommonMessageContext;
+import org.jboss.ws.metadata.umdm.EndpointMetaData;
+
+import javax.xml.ws.handler.Handler;
+import javax.xml.ws.handler.MessageContext;
+import javax.xml.ws.handler.soap.SOAPMessageContext;
+import javax.xml.soap.SOAPMessage;
+import javax.xml.soap.SOAPBodyElement;
+import javax.xml.soap.SOAPBody;
+import javax.xml.soap.SOAPException;
+import javax.jws.WebMethod;
+import javax.ejb.TransactionAttribute;
+import javax.ejb.TransactionAttributeType;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ArrayList;
+import java.lang.reflect.Method;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class JaxWSTransactionSpecifierHandler implements Handler
+{
+    private static Logger log = Logger.getLogger(JaxWSTransactionSpecifierHandler.class);
+    private static List<String> cacheList = new ArrayList<String>();
+    private static HashMap<String,String> methodMappings = new HashMap<String,String>();
+    private static TransactionAttributeType defaultAttribute = TransactionAttributeType.REQUIRED;
+
+    public JaxWSTransactionSpecifierHandler()
+    {
+    }
+
+    public boolean handleMessage(MessageContext msgContext)
+    {
+        log.debug("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);
+    }
+
+    private boolean handleInbound(MessageContext msgContext)
+    {
+
+        log.debug("handleInbound()");
+
+        try
+        {
+
+            CommonMessageContext commonMessageContext = MessageContextAssociation.peekMessageContext();
+            EndpointMetaData emd = commonMessageContext.getEndpointMetaData();
+            Class clazz = emd.getServiceEndpointInterface();
+            log.info("Class name: " + clazz.getName());
+
+            if (!cacheList.contains(clazz.getName()))
+            {
+                // Get all the methods from the class
+                Method[] methodList = clazz.getDeclaredMethods();
+                log.info("Number of methods: " + methodList.length);
+
+                // Loop through all methods
+                for (Method singleMethod : methodList)
+                {
+                    // Check what is the name of the method
+                    log.info("Single method: " + singleMethod.getName());
+                    String webMethodName = singleMethod.getName();
+
+                    // Check if there is a WebMethod annotation
+                    WebMethod webMethodAnnotation = singleMethod.getAnnotation(WebMethod.class);
+                    if (webMethodAnnotation != null)
+                    {
+                        log.info("WebMethod annotation: " + webMethodAnnotation.operationName());
+                        String name = webMethodAnnotation.operationName();
+                        if (name != null && !name.equals(""))
+                        {
+                            webMethodName = name;
+                        }
+                    }
+
+                    // Get the attribute of the transaction
+                    String transactionType = defaultAttribute.toString();
+                    TransactionAttribute txAttr = singleMethod.getAnnotation(TransactionAttribute.class);
+                    if (txAttr != null)
+                    {
+                        log.info("TransactionAttribute annotation: " + txAttr.value());
+                        // Check the type of the transaction attribute
+                        TransactionAttributeType txType = txAttr.value();
+
+                        if (txType != null)
+                        {
+                            transactionType = txType.toString();
+                        }
+
+                    }
+                    // Add the method definition to the methodMapping list
+                    log.info("Adding: (" + webMethodName + "," + transactionType + ")");
+                    methodMappings.put(webMethodName,transactionType);
+
+                }
+                cacheList.add(clazz.getName());
+            }
+
+            // Get the soap method name
+            SOAPMessage soapMessage = ((SOAPMessageContext)msgContext).getMessage();
+            SOAPBody soapBody = soapMessage.getSOAPBody();
+            SOAPBodyElement soapBodyElement = (SOAPBodyElement)soapBody.getChildElements().next();
+            String methodName = soapBodyElement.getElementName().getLocalName();
+
+            String transactionType = (String) methodMappings.get(methodName);
+            log.info("Mapping: (" + methodName + "," + transactionType + ")");
+
+            msgContext.put("TransactionAttributeType",transactionType);
+
+        }
+        catch (SOAPException soape)
+        {
+            soape.printStackTrace();
+        }
+        return true;
+    }
+
+    private boolean handleOutbound(MessageContext msgContext)
+    {
+        if (msgContext.containsKey("TransactionAttributeType"))
+        {
+            msgContext.remove("TransactionAttributeType");
+        }
+        return true;
+    }
+
+
+    public boolean handleFault(MessageContext messageContext)
+    {
+        log.debug("handleFault()");
+        return true;
+    }
+
+    public void close(MessageContext messageContext)
+    {
+        log.debug("close()");
+    }
+}
\ No newline at end of file

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/TxBridgeManager.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/TxBridgeManager.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/at/TxBridgeManager.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,127 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * (C) 2007,
+ * @author JBoss Inc.
+ */
+package org.jboss.txbridge.at;
+
+import com.arjuna.ats.internal.jta.transaction.arjunacore.jca.XATerminatorImple;
+import com.arjuna.ats.jta.xa.XidImple;
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.mw.wst.UserTransactionFactory;
+
+import com.arjuna.mw.wst.TransactionManagerFactory;
+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 transactions to JTA 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, 2007-04-30
+ */
+public class TxBridgeManager
+{
+	private static Logger log = Logger.getLogger(TxBridgeManager.class);
+
+	// TODO: make this play nice with the TransactionService in AS, particularly w.r.t recovery.
+	private static XATerminatorImple xaTerminatorImple = new XATerminatorImple();
+
+	private static ConcurrentMap<String, Xid> txIdMappings = new ConcurrentHashMap<String, Xid>();
+
+	private static ConcurrentMap<Xid, InboundBridge> inboundBridgeMappings = new ConcurrentHashMap<Xid, InboundBridge>();
+
+    private static String hello;
+    /**
+	 * Create 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
+	 * @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.info("getInboundBridge()");
+
+		String externalTxId = UserTransactionFactory.userTransaction().toString();
+
+		Xid xid = txIdMappings.get(externalTxId);
+		if(xid == null) {
+			xid = createMappings(externalTxId);
+		}
+
+		return inboundBridgeMappings.get(xid);
+	}
+
+	/**
+	 * Create the JTA transaction mapping and support objects for a given WS transaction context.
+	 *
+	 * @param externalTxId
+	 * @return
+	 * @throws WrongStateException
+	 * @throws UnknownTransactionException
+	 * @throws com.arjuna.wst.SystemException
+	 * @throws AlreadyRegisteredException
+	 */
+	private static synchronized Xid createMappings(String externalTxId)
+			throws XAException, WrongStateException, UnknownTransactionException,
+			com.arjuna.wst.SystemException, javax.transaction.SystemException, AlreadyRegisteredException {
+		log.info("createMappings(externalIxId="+externalTxId+")");
+
+		if(txIdMappings.containsKey(externalTxId)) {
+			return txIdMappings.get(externalTxId);
+		}
+
+		Xid xid = new XidImple(new Uid());
+		txIdMappings.put(externalTxId, xid);
+		inboundBridgeMappings.put(xid, new InboundBridge(xid));
+
+		// TODO: how do we tell if it's AT or BA?
+		// No implementation independent way, it requires parsind the otherwise opaque externalTxId.
+		// Probably better to have the caller (typically an handler) provide this info?
+
+        BridgeParticipantAT bridgeParticipantAT = new BridgeParticipantAT(xaTerminatorImple, xid);
+		TransactionManagerFactory.transactionManager().enlistForDurableTwoPhase(bridgeParticipantAT, new Uid().toString());
+
+		return xid;
+	}
+
+    public static synchronized void startDummyTransaction()
+            throws AlreadyRegisteredException, com.arjuna.wst.SystemException,
+            UnknownTransactionException, WrongStateException
+    {
+        DummyParticipantAT dummyParticipantAT = new DummyParticipantAT();
+        TransactionManagerFactory.transactionManager().enlistForDurableTwoPhase(dummyParticipantAT,new Uid().toString());
+    }
+}
\ No newline at end of file

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/BABridgeManager.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/BABridgeManager.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/BABridgeManager.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,157 @@
+package org.jboss.txbridge.ba;
+
+import org.apache.log4j.Logger;
+import org.jboss.txbridge.data.MethodInformation;
+import org.jboss.txbridge.helper.CompensationService;
+import com.arjuna.mw.wst.BusinessActivityManager;
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.wsc.AlreadyRegisteredException;
+import com.arjuna.wst.SystemException;
+import com.arjuna.wst.UnknownTransactionException;
+import com.arjuna.wst.WrongStateException;
+import com.arjuna.wst.BAParticipantManager;
+
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class BABridgeManager
+{
+    // Logger
+    private static Logger log = Logger.getLogger(BABridgeManager.class);
+
+    // Bridge manager
+    private volatile static BABridgeManager baBridgeManager;
+
+    // Business activity manager
+    BusinessActivityManager businessActivityManager;
+
+    // Compensation manager
+    CompensationService compensationService;
+
+    // Mappings: ba <-> participant
+    // ba <-> participant
+    private static ConcurrentMap<String,InboundBABridge> baBridges;
+
+
+    // Constructor
+    private BABridgeManager()
+    {
+        log.info("constructor()");
+
+        // Get business activity manager
+        businessActivityManager = BusinessActivityManager.getBusinessActivityManager();
+
+        // Initialise mappings
+        // - participants
+        baBridges = new ConcurrentHashMap<String,InboundBABridge>();
+
+
+    }
+
+    // Get instance of the bridge manager
+    public static BABridgeManager getSingletonInstance()
+    {
+        log.info("getSingletonInstance()");
+        if (baBridgeManager == null)
+        {
+            synchronized (BABridgeManager.class)
+            {
+                if (baBridgeManager == null)
+                {
+                    log.info("Creating new instance...");
+                    baBridgeManager = new BABridgeManager();
+                }
+            }
+        }
+        return baBridgeManager;
+    }
+
+    // Manage transaction for this method (service)
+    public synchronized void manageTransaction(MethodInformation methodInformation)
+    {
+        log.info("manageTransaction()");
+        String txId = null;
+        try
+        {
+            // Get the transaction identifier
+            txId = businessActivityManager.currentTransaction().toString();
+            log.info("Transaction identifier: " + txId);
+
+            // Start the participant
+            associateParticipantBA(txId,methodInformation);
+        }
+        catch (Exception se)
+        {
+            se.printStackTrace();
+        }
+
+    }
+
+    private synchronized void associateParticipantBA(String txId,MethodInformation methodInformation) throws AlreadyRegisteredException, SystemException, UnknownTransactionException, WrongStateException
+    {
+        log.info("associateParticipantBA()");
+
+        // Check if the transaction already has an associated bridge
+        // - if not than create one and pass him method's information
+        InboundBABridge baBridge = baBridges.get(txId);
+        if (baBridge == null)
+        {
+            // If not... create a new participant
+            baBridge = new InboundBABridge(txId);
+
+            // Remember the bridge
+            baBridges.put(txId,baBridge);
+
+        }
+        // - if yes then tell the bridge about another method
+        baBridge.start(methodInformation);
+
+    }
+
+    public synchronized void manageReturnObject(MethodInformation method, Object returnObject)
+    {
+        log.info("manageReturnObject()");
+        String txId = null;
+        try
+        {
+            txId = businessActivityManager.currentTransaction().toString();
+            InboundBABridge baBridge = baBridges.get(txId);
+            if (baBridge != null)
+            {
+                baBridge.addReturnObject(method.getOriginalMethod(),returnObject);
+            }
+        }
+        catch (SystemException e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    public synchronized void completeTransaction()
+    {
+        log.info("completeTransaction()");
+        String txId = null;
+        try
+        {
+            // Check the transaction identifier
+            txId = businessActivityManager.currentTransaction().toString();
+
+            // Get the participant manager
+            InboundBABridge baBridge = baBridges.get(txId);
+            if (baBridge != null)
+            {
+                baBridge.stop();
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+
+
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/CoordinatorCompletionParticipantBA.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/CoordinatorCompletionParticipantBA.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/CoordinatorCompletionParticipantBA.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,41 @@
+package org.jboss.txbridge.ba;
+
+import com.arjuna.wst.*;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class CoordinatorCompletionParticipantBA implements BusinessAgreementWithCoordinatorCompletionParticipant {
+
+    public void close() throws WrongStateException, SystemException
+    {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public void cancel() throws WrongStateException, SystemException
+    {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public void compensate() throws FaultedException, WrongStateException, SystemException
+    {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public String status() throws SystemException
+    {
+        return null;  //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public void unknown() throws SystemException {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public void error() throws SystemException {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+
+    public void complete() throws WrongStateException, SystemException {
+        //To change body of implemented methods use File | Settings | File Templates.
+    }
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/InboundBABridge.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/InboundBABridge.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/InboundBABridge.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,198 @@
+package org.jboss.txbridge.ba;
+
+import com.arjuna.wst.BAParticipantManager;
+import com.arjuna.wst.WrongStateException;
+import com.arjuna.wst.UnknownTransactionException;
+import com.arjuna.wst.SystemException;
+import com.arjuna.mw.wst.BusinessActivityManager;
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.wsc.AlreadyRegisteredException;
+
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.ArrayList;
+
+import org.jboss.txbridge.data.MethodInformation;
+import org.jboss.txbridge.annotations.BAServiceType;
+import org.jboss.txbridge.helper.CompensationService;
+import org.apache.log4j.Logger;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class InboundBABridge
+{
+    // Logger
+    Logger log = Logger.getLogger(InboundBABridge.class);
+
+    // Business activity manager
+    BusinessActivityManager businessActivityManager;
+
+    // Transaction identifier
+    private String txId;
+    
+    // Identifiers of methods
+    private Map<String,MethodInformation> methodList;
+
+    // List of the participants for this transaction
+    private Map<MethodInformation,ParticipantCompletionParticipantBA> participantList;
+
+    // List of all return objects
+    private Map<MethodInformation,Object> returnObjects;
+
+    // List of all compensation objects
+    private Map<MethodInformation,Object[]> compensationObjects;
+
+    // List of all temporary objects
+    private Map<String,Object> temporaryObjects;
+
+
+    // List of all participant managers
+    private Map<BAParticipantManager,String> participantManagerList;
+
+    public InboundBABridge(String txId)
+    {
+        this.txId = txId;
+        methodList = new HashMap<String,MethodInformation>();
+        participantList = new HashMap<MethodInformation,ParticipantCompletionParticipantBA>();
+        returnObjects = new HashMap<MethodInformation,Object>();
+        compensationObjects = new HashMap<MethodInformation,Object[]>();
+        participantManagerList = new HashMap<BAParticipantManager,String>();
+        temporaryObjects = new HashMap<String,Object>();
+        businessActivityManager = BusinessActivityManager.getBusinessActivityManager();
+
+        // Register itself with the compensation service
+        CompensationService cs = CompensationService.getSingletonInstance();
+        cs.registerBridge(txId,this);
+
+    }
+
+    public void start(MethodInformation methodInfo)
+    {
+        log.info("start()");
+        try
+        {
+            ParticipantCompletionParticipantBA participant = new ParticipantCompletionParticipantBA(txId,methodInfo);
+            BAParticipantManager participantManager = businessActivityManager.enlistForBusinessAgreementWithParticipantCompletion(participant,new Uid().toString());
+
+            methodList.put(methodInfo.getOriginalMethod(),methodInfo);
+            participantList.put(methodInfo,participant);
+            participantManagerList.put(participantManager,methodInfo.getServiceType());
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    public void stop()
+    {
+        log.info("stop()");
+        try
+        {
+            for ( BAParticipantManager pManager : participantManagerList.keySet())
+            {
+                log.info("Using participant manager.");
+                String serviceType = participantManagerList.get(pManager);
+                if (serviceType.equals("READONLY"))
+                {
+                    log.info("Service was 'read-only'. Exiting...");
+                    pManager.exit();
+                }
+                else if (serviceType.equals("MODIFY"))
+                {
+                    log.info("Service was 'modify'. Completing...");
+                    pManager.completed();
+                }
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    // Add new compensation object
+    public void addReturnObject(String methodName,Object object)
+    {
+        log.info("addReturnObject()");
+        MethodInformation methodInfo = methodList.get(methodName);
+        if (methodInfo != null)
+        {
+            returnObjects.put(methodInfo,object);
+        }
+    }
+
+    // Add new compensation object
+    public void addTemporaryObject(String methodName,String identifier, Object object)
+    {
+        log.info("addTemporaryObject()");
+        MethodInformation methodInfo = methodList.get(methodName);
+        if (methodInfo != null)
+        {
+            // Get the name of the compensation method
+            String compensationMethod = methodInfo.getCompensationMethod();
+            temporaryObjects.put(compensationMethod+identifier,object);
+        }
+    }
+
+    // Return a compensation object for a given transaction
+    public Object getTemporaryObject(String methodName,String identifier)
+    {
+        log.info("getTemporaryObject()");
+
+            return temporaryObjects.get(methodName+identifier);
+
+    }
+
+    // Return a compensation object for a given transaction
+    public Object getReturnObject(String methodName)
+    {
+        log.info("getReturnObject()");
+        MethodInformation methodInfo = methodList.get(methodName);
+        if (methodInfo != null)
+        {
+            return returnObjects.get(methodInfo);
+        }
+        return null;
+    }
+
+    public void addCompensationObject(String methodName, Object object)
+    {
+        log.info("addCompensationObject()");
+        MethodInformation methodInfo = methodList.get(methodName);
+        if ( methodInfo == null )
+        {
+            return;
+        }
+        Object[] objects = compensationObjects.get(methodInfo);
+        Integer paramListSize = 1;
+        if (objects != null)
+        {
+            paramListSize = objects.length;
+            Object[] tempObjects = new Object[paramListSize+1];
+            System.arraycopy(objects,0,tempObjects,0,objects.length);
+            tempObjects[paramListSize] = object;
+            compensationObjects.put(methodInfo,tempObjects);
+        }
+        else
+        {
+            objects = new Object[1];
+            objects[0] = object;
+            compensationObjects.put(methodInfo,objects);
+        }
+    }
+
+    public Object[] getCompensationObject(String methodName)
+    {
+        log.info("getCompensationObject()");
+        MethodInformation methodInfo = methodList.get(methodName);
+        if (methodInfo == null)
+        {
+            return null;
+        }
+        return compensationObjects.get(methodInfo);
+    }
+
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/JaxWSBASpecifierHandler.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/JaxWSBASpecifierHandler.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/JaxWSBASpecifierHandler.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,122 @@
+package org.jboss.txbridge.ba;
+
+import org.apache.log4j.Logger;
+
+import javax.xml.ws.handler.Handler;
+import javax.xml.ws.handler.MessageContext;
+
+
+import org.jboss.txbridge.data.ClassInformation;
+import org.jboss.txbridge.helper.*;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class JaxWSBASpecifierHandler implements Handler
+{
+    // Logger
+    private static Logger log = Logger.getLogger(JaxWSBASpecifierHandler.class);
+
+    // Service factory
+    private static ServiceAccessFactory serviceAccess = new JBossServiceAccessFactory();
+
+    public boolean handleMessage(MessageContext msgContext)
+    {
+        log.debug("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);
+    }
+
+    private boolean handleInbound(MessageContext msgContext)
+    {
+
+        log.debug("handleInbound()");
+
+        // Get reference to the service which is invoked
+        Class clazz = serviceAccess.getService();
+        String className = clazz.getName();
+        log.info("Class name: " + className);
+
+        // Get reference to the class manager
+        ClassInformationManager classInfoManager = ClassInformationManager.getSingletonInstance();
+
+        // Obtain information about the class
+        // - first check if the classInfoManager knows about this class
+        ClassInformation classInfo = classInfoManager.getClassInformation(className);
+        // - if not than process this class
+        if (classInfo == null)
+        {
+            // Process class and obtain info
+            classInfo = ClassBAVisitor.processClass(clazz);
+
+            // Remember info about the class
+            classInfoManager.storeClassInformation(classInfo);
+
+        }
+
+        // Inject task identifier
+      
+
+        // Check the web method's name
+        String methodName = SOAPProcessor.getMethodName(msgContext);
+
+        // Get the real name of the method
+        methodName = classInfo.getOriginalMethodName(methodName);
+
+        // Display for logging purposes
+        String transactionType =  classInfo.getTransactionAttribute(methodName);
+        log.info("Mapping: (" + methodName + "," + transactionType + ")");
+        String serviceType =  classInfo.getServiceType(methodName);
+        log.info("Mapping: (" + methodName + "," + serviceType + ")");
+        String compensationMethod = classInfo.getCompensationMethod(methodName);
+        log.info("Link: (" + methodName + "," + compensationMethod + ")");
+        Class returnType = classInfo.getReturnType(methodName);
+        log.info("Return type: (" + methodName + "," + returnType.getName() + ")");
+
+        // Set properties
+        msgContext.put(BAProperties.BAClass.toString(),className);
+        msgContext.put(BAProperties.BAMethod.toString(),methodName);
+
+        return true;
+    }
+
+    private boolean handleOutbound(MessageContext msgContext)
+    {
+        log.info("handleOutbound()");
+        // Remove properties
+        if (msgContext.containsKey(BAProperties.BAClass.toString()))
+        {
+            msgContext.remove(BAProperties.BAClass.toString());
+        }
+        if (msgContext.containsKey(BAProperties.BAMethod.toString()))
+        {
+            msgContext.remove(BAProperties.BAMethod.toString());
+        }
+        return true;
+    }
+
+    public boolean handleFault(MessageContext msgContext)
+    {
+        log.info("handleFault()");
+        // Remove properties
+        if (msgContext.containsKey(BAProperties.BAClass.toString()))
+        {
+            msgContext.remove(BAProperties.BAClass.toString());
+        }
+        if (msgContext.containsKey(BAProperties.BAMethod.toString()))
+        {
+            msgContext.remove(BAProperties.BAMethod.toString());
+        }
+        return true;
+    }
+
+    public void close(MessageContext messageContext)
+    {
+        log.info("close()");
+    }
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/JaxWSBusinessActivityHandler.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/JaxWSBusinessActivityHandler.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/JaxWSBusinessActivityHandler.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,180 @@
+package org.jboss.txbridge.ba;
+
+import org.apache.log4j.Logger;
+import org.jboss.txbridge.helper.*;
+import org.jboss.txbridge.data.ClassInformation;
+import org.jboss.txbridge.data.MethodInformation;
+
+import javax.xml.ws.handler.Handler;
+import javax.xml.ws.handler.MessageContext;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class JaxWSBusinessActivityHandler implements Handler
+{
+    // Logger
+    private static Logger log = Logger.getLogger(JaxWSBusinessActivityHandler.class);
+
+    // Service access factory
+    private static ServiceAccessFactory serviceAccess = new JBossServiceAccessFactory();
+
+    // Get access to the class information manager
+    private static ClassInformationManager classInfoManager = ClassInformationManager.getSingletonInstance();
+
+    public boolean handleMessage(MessageContext msgContext)
+    {
+        log.debug("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);
+    }
+
+    public boolean handleFault(MessageContext messageContext)
+    {
+        log.info("handleFault()");
+        return true;
+    }
+
+    public void close(MessageContext messageContext)
+    {
+        log.info("close()");
+    }
+
+    protected boolean handleInbound(MessageContext msgContext)
+    {
+        log.debug("handleInbound()");
+
+        // Get access to the class
+        Class clazz = serviceAccess.getService();
+
+        // Obtain class info
+        ClassInformation classInfo = classInfoManager.getClassInformation(clazz.getName());
+
+        // Get properties
+        String className = (String) msgContext.get(BAProperties.BAClass.toString());
+        log.info("className: " + className);
+        String webMethodName = (String) msgContext.get(BAProperties.BAMethod.toString());
+        log.info("webMethodName: " + webMethodName);
+
+        // Check if those are correct
+        // - check class
+        if (!className.equals(clazz.getName()))
+        {
+            return false;
+        }
+        // - check method
+        // TODO: IMPLEMENT
+
+        // Get original method name
+        String methodName = classInfo.getOriginalMethodName(webMethodName);
+        // Get method information
+        MethodInformation methodInfo = classInfo.getMethodInformation(methodName);
+
+        // Display for logging purposes
+        log.info("Business Activity...");
+        log.info("BAService: " + methodInfo.getServiceType());
+        log.info("BATransactionAttribute: " + methodInfo.getTransactionAttribute());
+        log.info("BACompensatedBy: " + methodInfo.getCompensationMethod());
+        log.info("Return Type: " + methodInfo.getReturnType().getName());
+
+        // Check the type of transaction
+        if (methodInfo.getTransactionAttribute() == null)
+        {
+
+        }
+        else if (methodInfo.getTransactionAttribute().equals("COORDINATOR_COMPLETION"))
+        {
+
+        }
+        else if (methodInfo.getTransactionAttribute().equals("PARTICIPANT_COMPLETION"))
+        {
+            // Get reference to the BABridgeManager
+            log.info("Getting reference to the BA Bridge Manager");
+            BABridgeManager babridgeManager = BABridgeManager.getSingletonInstance();
+
+            // Starting transaction management
+            log.info("Starting transaction managemenet");
+            babridgeManager.manageTransaction(methodInfo);
+
+        }
+
+        return true;
+    }
+
+    /**
+     * Tidy up the Transaction/Thread association before returning a message to the client.
+     *
+     * @param msgContext
+     * @return
+     */
+    protected boolean handleOutbound(MessageContext msgContext)
+    {
+
+        log.info("handleOutbound()");
+        try
+        {
+            // Get the soap method name
+            String className = (String) msgContext.get(BAProperties.BAClass.toString());
+            log.info("className: " + className);
+            String webMethodName = (String) msgContext.get(BAProperties.BAMethod.toString());
+            log.info("webMethodName: " + webMethodName);
+
+            // Get the methods information
+            ClassInformation classInfo = classInfoManager.getClassInformation(className);
+            String methodName = classInfo.getOriginalMethodName(webMethodName);
+            log.info("originalName: " + methodName);
+            MethodInformation methodInfo = classInfo.getMethodInformation(methodName);
+
+            // Check the type of transaction
+            if (methodInfo.getTransactionAttribute() == null)
+            {
+
+            }
+            else if (methodInfo.getTransactionAttribute().equals("COORDINATOR_COMPLETION"))
+            {
+
+            }
+            else if (methodInfo.getTransactionAttribute().equals("PARTICIPANT_COMPLETION"))
+            {
+                log.info("Getting reference to the bridge manager");
+                BABridgeManager babridgeManager = BABridgeManager.getSingletonInstance();
+
+                // Get the return object if necessary
+                log.info("checking return type...");
+                Class returnType = methodInfo.getReturnType();
+                log.info("return type: " + returnType.getName());
+                if (!methodInfo.getReturnType().getName().equals("void"))
+                {
+                    log.info("Getting return object");
+                    Object returnObject = SOAPProcessor.getReturnObject(msgContext);
+                    log.info("Return object: " + returnObject.toString());
+                    // Set compensation object
+
+                    log.info("Remembering return object");
+                    babridgeManager.manageReturnObject(methodInfo,returnObject);
+                }
+
+                babridgeManager.completeTransaction();
+            }
+
+
+
+        }
+        catch (Exception soape)
+        {
+            soape.printStackTrace();
+        }
+
+        return true;
+    }
+
+
+
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/ParticipantCompletionParticipantBA.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/ParticipantCompletionParticipantBA.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/ba/ParticipantCompletionParticipantBA.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,168 @@
+package org.jboss.txbridge.ba;
+
+import com.arjuna.wst.*;
+import com.arjuna.ats.internal.jta.transaction.arjunacore.jca.XATerminatorImple;
+import org.apache.log4j.Logger;
+import org.jboss.txbridge.data.MethodInformation;
+import org.jboss.txbridge.helper.CompensationService;
+import org.jboss.txbridge.annotations.CompensationIdentifier;
+
+import javax.transaction.xa.Xid;
+import java.lang.reflect.Method;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class ParticipantCompletionParticipantBA implements BusinessAgreementWithCoordinatorCompletionParticipant
+{
+    // Logger
+    private static Logger log = Logger.getLogger(ParticipantCompletionParticipantBA.class);
+
+    // Transaction identifier
+    String txId;
+
+    // Reference to the inbound bridge
+    InboundBABridge myBridge;
+
+    // Complete information about the original and compensation methods
+    private MethodInformation method;
+
+    // AT Transaction support
+    private XATerminatorImple xaTerminator;
+    private Xid xid;
+
+
+    public ParticipantCompletionParticipantBA(String txId,MethodInformation methodInformation)
+    {
+        log.info("constructor()");
+        method = methodInformation;
+        this.txId = txId;
+    }
+
+
+
+
+    public void complete() throws WrongStateException, SystemException
+    {
+        log.info("complete()");
+    }
+
+    public void close() throws WrongStateException, SystemException
+    {
+        log.info("close()");
+    }
+
+    public void cancel() throws WrongStateException, SystemException
+    {
+        log.info("cancel()");
+    }
+
+    public void compensate() throws FaultedException, WrongStateException, SystemException
+    {
+        log.info("compensate()");
+        try
+        {
+            // Obtain the return object
+            log.info("Getting the return object");
+            CompensationService compensationService = CompensationService.getSingletonInstance();
+            Object returnObject = compensationService.getReturnObject(txId,method.getOriginalMethod());
+            log.info("Return object that will be used: " + returnObject.toString());
+            Object[] parameterObjects = new Object[1];
+            Class[] parameterTypes = new Class[1];
+
+            parameterObjects[0] = returnObject;
+            parameterTypes[0] = returnObject.getClass();
+
+            // Obtain the compensation objects
+            log.info("Getting the compensation object");
+            Object[] compensationObjects = compensationService.getCompensationObject(txId,method.getOriginalMethod());
+            if ( compensationObjects == null )
+            {
+                log.info("No compensation objects will be used.");
+            }
+            else
+            {
+                log.info("Compensation objects found.");
+                for (Object singleObject : compensationObjects)
+                {
+                    log.info("Compensation object: " + singleObject);
+                }
+                log.info("Adding compensation objects as parameters.");
+                Object[] tempParameters = new Object[compensationObjects.length+1];
+                System.arraycopy(compensationObjects,0,tempParameters,0,compensationObjects.length);
+                tempParameters[compensationObjects.length] = returnObject;
+                parameterObjects = new Object[tempParameters.length];
+                parameterTypes = new Class[tempParameters.length];
+                System.arraycopy(tempParameters,0,parameterObjects,0,tempParameters.length);
+                int i = 0;
+                log.info("Adding parameter types.");
+                for (Object singleObject : parameterObjects)
+                {
+                    log.info("Link (" + singleObject + "," + singleObject.getClass()+")");
+                    parameterTypes[i++] = singleObject.getClass();
+                }
+
+            }
+
+            log.info("Parameter objects:");
+            for (Object parameter : parameterObjects)
+            {
+                log.info(parameter);
+            }
+            log.info("Parameter types:");
+            for (Class clazz : parameterTypes)
+            {
+                log.info(clazz);
+            }
+            log.info(parameterTypes);
+
+            // Get reference to the method
+            Class clazz = method.getCompensationClass();
+            log.info("Class: " + clazz.getName());
+            Method theMethod = clazz.getMethod(method.getCompensationMethod(),parameterTypes);
+            log.info("Method: " + theMethod.getName());
+            Constructor classConstructor = clazz.getConstructor();
+            log.info("Constructor: " + classConstructor.toString());
+            Object classObject = classConstructor.newInstance();
+
+            // Inject the transaction identifier
+            Field[] fields = clazz.getDeclaredFields();
+            for (Field singleField : fields)
+            {
+                CompensationIdentifier cid = singleField.getAnnotation(CompensationIdentifier.class);
+                if (cid != null)
+                {
+                    singleField.setAccessible(true);
+                    singleField.set(classObject,txId);
+                }
+            }
+
+            // Invoke the compensation method
+            theMethod.invoke(classObject,parameterObjects);
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    public String status() throws SystemException
+    {
+        log.info("status()");
+        return null;
+    }
+
+    public void unknown() throws SystemException
+    {
+        log.info("unknown()");
+    }
+
+    public void error() throws SystemException
+    {
+        log.info("error()");
+    }
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/data/ClassInformation.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/data/ClassInformation.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/data/ClassInformation.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,84 @@
+package org.jboss.txbridge.data;
+
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class ClassInformation
+{
+    // Class
+    private Class clazz;
+
+    // Mappings
+    // (web_method_name,real_method_name)
+    private ConcurrentMap<String,String> webMethodMappings;
+    // (real_method_name,method_information)
+    private ConcurrentMap<String,MethodInformation> methodMappings;
+
+    // Constructor
+    public ClassInformation(Class clazz, ConcurrentMap<String,String> webMethodMappings, ConcurrentMap<String, MethodInformation> methodMappings)
+    {
+        this.clazz = clazz;
+        this.webMethodMappings = webMethodMappings;
+        this.methodMappings = methodMappings;
+    }
+
+    // Get the class that is being described
+    public Class getTheClass()
+    {
+        return clazz;
+    }
+
+    // Get the name of a compensation method for a given method
+    public String getCompensationMethod(String originalMethod)
+    {
+        if (methodMappings.containsKey(originalMethod))
+        {
+            return methodMappings.get(originalMethod).getCompensationMethod();
+        }
+        return null;
+    }
+
+    // Get return type for a given method
+    public Class getReturnType(String originalMethod)
+    {
+        if (methodMappings.containsKey(originalMethod))
+        {
+            return methodMappings.get(originalMethod).getReturnType();
+        }
+        return null;
+    }
+
+    // Get transaction attribute for a given method
+    public String getTransactionAttribute(String originalMethod)
+    {
+        if (methodMappings.containsKey(originalMethod))
+        {
+            return methodMappings.get(originalMethod).getTransactionAttribute();
+        }
+        return null;
+    }
+
+    // Get the service type for the given method
+    public String getServiceType(String originalMethod)
+    {
+        if (methodMappings.containsKey(originalMethod))
+        {
+            return methodMappings.get(originalMethod).getServiceType();
+        }
+        return null;
+    }
+
+    // Get full method information
+    public MethodInformation getMethodInformation(String methodName)
+    {
+        return methodMappings.get(methodName);
+    }
+
+    // Get the original method's name
+    public String getOriginalMethodName(String webMethodName)
+    {
+        return webMethodMappings.get(webMethodName);
+    }
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/data/CompensationObject.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/data/CompensationObject.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/data/CompensationObject.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,8 @@
+package org.jboss.txbridge.data;
+
+/**
+ * Author: Maciej Machulak
+ */
+public interface CompensationObject
+{
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/data/MethodInformation.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/data/MethodInformation.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/data/MethodInformation.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,93 @@
+package org.jboss.txbridge.data;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class MethodInformation
+{
+    // Web method name
+    private String webMethodName;
+
+    // Original method
+    private Class originalClass;
+    private String originalMethod;
+    private Class returnType;
+
+    // Transaction attribute
+    private String transactionAttribute;
+
+    // Service type
+    private String serviceType;
+
+    // Compensation method
+    private Class compensationClass;
+    private String compensationMethod;
+    private Class[] parameterType;
+
+
+    public MethodInformation(String webMethodName, Class originalClass, String originalMethod, Class returnType, String transactionAttribute, String serviceType, Class compensationClass, String compensationMethod, Class[] parameterType)
+    {
+        this.webMethodName = webMethodName;
+        this.originalClass = originalClass;
+        this.originalMethod = originalMethod;
+        this.returnType = returnType;
+        this.transactionAttribute = transactionAttribute;
+        this.serviceType = serviceType;
+        this.compensationClass = compensationClass;
+        this.compensationMethod = compensationMethod;
+        this.parameterType = parameterType;
+    }
+
+    public Class getOriginalClass()
+    {
+        return originalClass;
+    }
+
+    public String getOriginalMethod()
+    {
+        return originalMethod;
+    }
+
+    public Class getReturnType()
+    {
+        return returnType;
+    }
+
+    public Class getCompensationClass()
+    {
+        return compensationClass;
+    }
+
+    public String getCompensationMethod()
+    {
+        return compensationMethod;
+    }
+
+    public Class[] getParameterType()
+    {
+        return parameterType;
+    }
+
+
+    public void setReturnType(Class returnType)
+    {
+        this.returnType = returnType;
+    }
+
+    public String getTransactionAttribute()
+    {
+        return transactionAttribute;
+    }
+
+
+    public String getServiceType()
+    {
+        return serviceType;
+    }
+
+
+    public String getWebMethodName()
+    {
+        return webMethodName;
+    }
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/data/ServiceDescription.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/data/ServiceDescription.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/data/ServiceDescription.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,45 @@
+package org.jboss.txbridge.data;
+
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class ServiceDescription 
+{
+    private String className;
+    private ConcurrentMap<String,String> compensationMappings = new ConcurrentHashMap<String,String>();
+    private ConcurrentMap<String,String> protocolMappings = new ConcurrentHashMap<String,String>();
+    private ConcurrentMap<String,String> serviceTypeMappings = new ConcurrentHashMap<String,String>();
+    private ConcurrentMap<String,Object> compensationObjects = new ConcurrentHashMap<String,Object>();
+
+
+    ServiceDescription(String className)
+    {
+        this.className = className;
+    }
+
+    String newCompensationMapping(String key, String value)
+    {
+        return compensationMappings.putIfAbsent(key, value);
+    }
+
+
+    String newProtocolMapping(String key, String value)
+    {
+        return protocolMappings.putIfAbsent(key, value);
+    }
+
+
+    String newServiceTypeMapping(String key, String value)
+    {
+        return serviceTypeMappings.putIfAbsent(key, value);
+    }
+
+
+    public Object newCompensationObject(String key, Object value)
+    {
+        return compensationObjects.putIfAbsent(key, value);
+    }
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/BAProperties.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/BAProperties.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/BAProperties.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,10 @@
+package org.jboss.txbridge.helper;
+
+/**
+ * Author: Maciej Machulak
+ */
+public enum BAProperties
+{
+    BAClass,
+    BAMethod
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/BATaskIdentifierFactory.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/BATaskIdentifierFactory.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/BATaskIdentifierFactory.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,15 @@
+package org.jboss.txbridge.helper;
+
+/**
+ * Author: Maciej Machulak
+ */
+public abstract class BATaskIdentifierFactory
+{
+    protected BATaskIdentifierFactory()
+    {
+        String BATaskIdentifier = getIdentifier();
+    }
+
+    public abstract String getIdentifier();
+
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/ClassBAVisitor.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/ClassBAVisitor.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/ClassBAVisitor.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,134 @@
+package org.jboss.txbridge.helper;
+
+import org.jboss.txbridge.annotations.*;
+import org.jboss.txbridge.data.ClassInformation;
+import org.jboss.txbridge.data.MethodInformation;
+import org.apache.log4j.Logger;
+
+import javax.jws.WebMethod;
+import javax.ejb.TransactionAttributeType;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.lang.reflect.Method;
+
+
+/**
+ * Author: Maciej Machulak
+ */
+public class ClassBAVisitor
+{
+    // Logger
+    private static Logger log = Logger.getLogger(ClassBAVisitor.class);
+
+    // Other
+    private static TransactionAttributeType defaultTxAttributeType = TransactionAttributeType.REQUIRED;
+    private static BAServiceType defaultBAServiceType = BAServiceType.MODIFY;
+
+    // Create information about a class
+    public static synchronized ClassInformation processClass(Class clazz)
+    {
+        log.info("processClass()");
+
+        // Create new mappings
+        ConcurrentMap<String, MethodInformation> methodMappings = new ConcurrentHashMap<String,MethodInformation>();
+        ConcurrentMap<String,String> methodNameMappings = new ConcurrentHashMap<String,String>();
+
+        // Get all the methods from the class
+        Method[] methodList = clazz.getDeclaredMethods();
+        log.info("Number of methods: " + methodList.length);
+
+        // Loop through all methods
+        for (Method singleMethod : methodList)
+        {
+            // Return class
+            Class<?> returnType = null;
+            Class<?>[] parameterTypes = null;
+
+            // Check what is the name of the method
+            log.info("Single method: " + singleMethod.getName());
+            String methodName = singleMethod.getName();
+            String webMethodName = methodName;
+
+            // Check if there is a WebMethod annotation
+            WebMethod webMethodAnnotation = singleMethod.getAnnotation(WebMethod.class);
+            if (webMethodAnnotation != null)
+            {
+                log.info("WebMethod annotation present!");
+
+                // Check if the operation name has been specified
+                String name = webMethodAnnotation.operationName();
+                if (name != null && !name.equals(""))
+                {
+                    log.info("WebMethod operationName: " + name);
+                    // If yes... change the name of the web method
+                    webMethodName = name;
+                }
+            }
+            // Remember (method,webMethod) association
+            methodNameMappings.put(methodName,webMethodName);
+
+            // Check if this method is a BA service
+            String serviceType = defaultBAServiceType.toString();
+            BAService baService = singleMethod.getAnnotation(BAService.class);
+            if (baService != null)
+            {
+                log.info("Method " + webMethodName + " is a BA service.");
+
+                // Get the type of the service
+                BAServiceType baServiceType = baService.value();
+                if (baServiceType != null)
+                {
+                    log.info("BAServiceType: " + baServiceType);
+                    serviceType = baServiceType.toString();
+                }
+
+            }
+
+            // Check the transaction attribute
+            String transactionType = defaultTxAttributeType.toString();
+            BATransactionAttribute txAttr = singleMethod.getAnnotation(BATransactionAttribute.class);
+            if (txAttr != null)
+            {
+
+                log.info("BATransactionAttribute annotation present!");
+                // If there was a transaction attribute check the type of the transaction attribute
+                BATransactionAttributeType txType = txAttr.value();
+
+                if (txType != null)
+                {
+                    log.info("BATransactionAttributeType: " + txType);
+                    transactionType = txType.toString();
+                }
+            }
+
+            // Check the compensation method
+            String compensationMethod = "";
+            BACompensatedBy baComp = singleMethod.getAnnotation(BACompensatedBy.class);
+            if (baComp != null)
+            {
+                log.info("BACompensatedBy annotation present!");
+                compensationMethod = baComp.value();
+            }
+
+            // Check the types of the parameters
+            for (Method theMethod : methodList)
+            {
+                if (theMethod.getName().equals(compensationMethod))
+                {
+                    parameterTypes = theMethod.getParameterTypes();
+                    break;
+                }
+            }
+
+            // Get the return type
+            returnType = singleMethod.getReturnType();
+
+            MethodInformation singleMethodInfo = new MethodInformation(webMethodName,clazz,methodName,returnType,transactionType,serviceType,clazz,compensationMethod,parameterTypes);
+            methodMappings.putIfAbsent(webMethodName,singleMethodInfo);
+        }
+
+        // Cache all obtained values
+        return new ClassInformation(clazz,methodNameMappings,methodMappings);
+    }
+
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/ClassInformationManager.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/ClassInformationManager.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/ClassInformationManager.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,83 @@
+package org.jboss.txbridge.helper;
+
+import org.jboss.txbridge.data.ClassInformation;
+import org.apache.log4j.Logger;
+
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class ClassInformationManager
+{
+    // Logger
+    private static Logger log = Logger.getLogger(ClassInformationManager.class);
+
+    // Mapping (class name , class information)
+    private ConcurrentMap<String, ClassInformation> classDescriptions;
+
+    // Class information manager instance
+    private volatile static ClassInformationManager cim = null;
+
+    // Constructor
+    private ClassInformationManager()
+    {
+        log.info("constructor()");
+        classDescriptions = new ConcurrentHashMap<String,ClassInformation>();
+    }
+
+    // Get instance of the class information manager
+    public static ClassInformationManager getSingletonInstance()
+    {
+        log.info("getSingletonInstance()");
+        if (cim == null)
+        {
+            synchronized(ClassInformationManager.class)
+            {
+                if (cim == null)
+                {
+                    log.info("Creating new instance");
+                    cim = new ClassInformationManager();
+                }
+            }
+        }
+        return cim;
+    }
+
+    // Store information about a class
+    public void storeClassInformation(ClassInformation classInformation)
+    {
+        log.info("storeClassInformation(ClassInformation)");
+        storeClassInformation(classInformation.getTheClass().getName(),classInformation);
+    }
+
+    // Store information about a class
+    public void storeClassInformation(String className,ClassInformation classInformation)
+    {
+        log.info("storeClassInformation(String,ClassInformation)");
+        classDescriptions.putIfAbsent(className,classInformation);
+    }
+
+    // Get information about a class of a given name
+    public ClassInformation getClassInformation(String className)
+    {
+        log.info("getClassInformation()");
+        log.info("No. of classes: " + classDescriptions.size());
+        ClassInformation classInfo = classDescriptions.get(className);
+        if (classInfo == null)
+        {
+            log.info("Returning null...");
+        }
+        return classInfo;
+    }
+
+    // Check if a class of a given name has its information object stored
+    public boolean knowsAbout(String className)
+    {
+        log.info("knowsAbout()");
+        return classDescriptions.containsKey(className);
+    }
+
+
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/CompensationManager.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/CompensationManager.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/CompensationManager.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,90 @@
+package org.jboss.txbridge.helper;
+
+import com.arjuna.mw.wst.BusinessActivityManager;
+import com.arjuna.mw.wst.TxContext;
+import com.arjuna.wst.SystemException;
+import org.apache.log4j.Logger;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class CompensationManager
+{
+    // Logger
+    Logger log = Logger.getLogger(CompensationManager.class);
+
+
+    BusinessActivityManager businessActivityManager;
+    CompensationService cs;
+
+    public CompensationManager()
+    {
+        // Get business activity manager
+        businessActivityManager = BusinessActivityManager.getBusinessActivityManager();
+
+        // Get compensation service
+        cs = CompensationService.getSingletonInstance();
+
+
+    }
+
+    public void store(String methodName, Object returnObject)
+    {
+        log.info("store()");
+        // Get transaction identifier
+        try
+        {
+            String txId = businessActivityManager.currentTransaction().toString();
+            cs.addCompensationObject(txId,methodName,returnObject);
+        }
+        catch (SystemException e)
+        {
+            e.printStackTrace();
+        }
+
+    }
+
+    public void storeTemporary(String methodName, String identifier, Object object)
+    {
+        log.info("storeTemporary()");
+        // Get transaction identifier
+        try
+        {
+            String txId = businessActivityManager.currentTransaction().toString();
+            cs.addTemporaryCompensationObject(txId,methodName,identifier,object);
+        }
+        catch (SystemException e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    public Object getTemporaryObject(String txId,String methodName,String identifier)
+    {
+        if (txId == null)
+        {
+            return null;
+        }
+        // Get transaction identifier
+        log.info("getTemporaryObject()");
+        return cs.getTemporaryCompensationObject(txId,methodName,identifier);
+
+    }
+
+    public Object retrieve(String methodName)
+    {
+        log.info("retrieve()");
+        // Get transaction identifier
+        try
+        {
+            businessActivityManager = BusinessActivityManager.getBusinessActivityManager();
+            String txId = businessActivityManager.currentTransaction().toString();
+            return cs.getCompensationObject(txId,methodName);
+        }
+        catch (SystemException e)
+        {
+            e.printStackTrace();
+        }
+        return null;
+    }
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/CompensationService.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/CompensationService.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/CompensationService.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,136 @@
+package org.jboss.txbridge.helper;
+
+import org.apache.log4j.Logger;
+import org.jboss.txbridge.ba.InboundBABridge;
+import org.jboss.txbridge.data.MethodInformation;
+
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class CompensationService
+{
+    // Logger
+    private static Logger log = Logger.getLogger(CompensationService.class);
+
+    // Compensation manager instance
+    private volatile static CompensationService compensationService = null;
+
+    // Mappings
+    // - transaction IDs and Inbound Bridges
+    private static ConcurrentMap<String,InboundBABridge> bridges;
+    // - transaction IDs and method information
+    private static ConcurrentMap<String, MethodInformation> txMethods;
+    // - unique ID and temporary objects
+    private static ConcurrentMap<String,Object> returnObjects;
+    // - transaction IDs and additional compensation objects
+    private static ConcurrentMap<String,Object[]> compensationObjects;
+
+    // Constructor
+    private CompensationService()
+    {
+        log.info("constructor()");
+        bridges = new ConcurrentHashMap<String,InboundBABridge>();
+        txMethods = new ConcurrentHashMap<String,MethodInformation>();
+        returnObjects = new ConcurrentHashMap<String,Object>();
+        compensationObjects = new ConcurrentHashMap<String,Object[]>();
+    }
+
+    public void registerBridge(String txId,InboundBABridge bridge)
+    {
+        bridges.put(txId,bridge);
+    }
+
+    // Return instance of the compensation manager
+    public static CompensationService getSingletonInstance()
+    {
+        log.info("getSingletonInstance()");
+        if (compensationService == null)
+        {
+            synchronized(CompensationService.class)
+            {
+                if (compensationService == null)
+                {
+                    log.info("Creating new instance");
+                    compensationService = new CompensationService();
+                }
+            }
+        }
+        return compensationService;
+    }
+
+    // Add new compensation object
+    public void addReturnObject(String txId, String methodName,Object object)
+    {
+        log.info("addReturnObject()");
+        InboundBABridge bridge = bridges.get(txId);
+        if (bridge != null)
+        {
+            log.info("Bridge found...");
+            bridge.addReturnObject(methodName,object);
+        }
+    }
+
+    // Add new compensation object
+    public void addTemporaryCompensationObject(String txId, String methodName,String identifier,Object object)
+    {
+        log.info("addTemporaryCompensationObject()");
+        InboundBABridge bridge = bridges.get(txId);
+        if (bridge != null)
+        {
+            log.info("Bridge found...");
+            bridge.addTemporaryObject(methodName,identifier,object);
+        }
+    }
+
+    // Return a compensation object for a given transaction
+    public Object getTemporaryCompensationObject(String txId,String methodName,String identifier)
+    {
+        log.info("getTemporaryCompensationObject()");
+        InboundBABridge bridge = bridges.get(txId);
+        if (bridge != null)
+        {
+            log.info("Bridge found...");
+            return bridge.getTemporaryObject(methodName,identifier);
+        }
+        return null;
+    }
+
+    // Return a compensation object for a given transaction
+    public Object getReturnObject(String txId,String methodName)
+    {
+        log.info("getReturnObject()");
+        InboundBABridge bridge = bridges.get(txId);
+        if (bridge != null)
+        {
+            log.info("Bridge found...");
+            return bridge.getReturnObject(methodName);
+        }
+        return null;
+    }
+
+    public void addCompensationObject(String txId, String methodName, Object object)
+    {
+        log.info("addCompensationObject()");
+        InboundBABridge bridge = bridges.get(txId);
+        if (bridge != null)
+        {
+            log.info("Bridge found...");
+            bridge.addCompensationObject(methodName,object);
+        }
+    }
+
+    public Object[] getCompensationObject(String txId, String methodName)
+    {
+        log.info("getCompensationObject()");
+        InboundBABridge bridge = bridges.get(txId);
+        if (bridge != null)
+        {
+            log.info("Bridge found...");
+            return bridge.getCompensationObject(methodName);
+        }
+        return null;
+    }
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/JBossServiceAccessFactory.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/JBossServiceAccessFactory.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/JBossServiceAccessFactory.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,26 @@
+package org.jboss.txbridge.helper;
+
+import org.jboss.ws.core.CommonMessageContext;
+import org.jboss.ws.core.soap.MessageContextAssociation;
+import org.jboss.ws.metadata.umdm.EndpointMetaData;
+import org.jboss.txbridge.helper.ServiceAccessFactory;
+import org.apache.log4j.Logger;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class JBossServiceAccessFactory extends ServiceAccessFactory
+{
+    // Logger
+    private static Logger log = Logger.getLogger(JBossServiceAccessFactory.class);
+
+    // Return a class that's method is being invoked in this context
+    public Class getService()
+    {
+        log.info("getService()");
+        CommonMessageContext commonMessageContext = MessageContextAssociation.peekMessageContext();
+        EndpointMetaData emd = commonMessageContext.getEndpointMetaData();
+        return emd.getServiceEndpointInterface();
+    }
+
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/SOAPProcessor.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/SOAPProcessor.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/SOAPProcessor.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,57 @@
+package org.jboss.txbridge.helper;
+
+import org.jboss.ws.core.soap.SOAPContentElement;
+import org.apache.log4j.Logger;
+
+import javax.xml.ws.handler.MessageContext;
+import javax.xml.ws.handler.soap.SOAPMessageContext;
+import javax.xml.soap.SOAPMessage;
+import javax.xml.soap.SOAPBody;
+import javax.xml.soap.SOAPBodyElement;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class SOAPProcessor
+{
+    // Logger
+    private static Logger log = Logger.getLogger(SOAPProcessor.class);
+
+    // Pull out a method's name from the SOAP message
+    public static synchronized String getMethodName(MessageContext msgContext)
+    {
+        log.info("getMethodName()");
+        try
+        {
+            SOAPMessage soapMessage = ((SOAPMessageContext)msgContext).getMessage();
+            SOAPBody soapBody = soapMessage.getSOAPBody();
+            SOAPBodyElement soapBodyElement = (SOAPBodyElement)soapBody.getChildElements().next();
+            return soapBodyElement.getElementName().getLocalName();
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    // Pull out the return object from a message
+    public static synchronized Object getReturnObject(MessageContext msgContext)
+    {
+        log.info("getReturnObject()");
+        try
+        {
+            SOAPMessage soapMessage = ((SOAPMessageContext)msgContext).getMessage();
+            SOAPBody soapBody = soapMessage.getSOAPBody();
+            SOAPBodyElement soapBodyElement = (SOAPBodyElement)soapBody.getChildElements().next();
+            SOAPContentElement parameterElement = (SOAPContentElement) soapBodyElement.getChildElements().next();
+            parameterElement.getObjectValue();
+            return parameterElement.getObjectValue();
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        return null;
+    }
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/ServiceAccessFactory.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/ServiceAccessFactory.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/ServiceAccessFactory.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,15 @@
+package org.jboss.txbridge.helper;
+
+/**
+ * Author: Maciej Machulak
+ */
+public abstract class ServiceAccessFactory 
+{
+
+    protected ServiceAccessFactory()
+    {
+        Class clazz = getService();
+    }
+
+    public abstract Class getService();
+}

Added: labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/SimpleBATaskIdentifierFactory.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/SimpleBATaskIdentifierFactory.java	                        (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/bridge/src/org/jboss/txbridge/helper/SimpleBATaskIdentifierFactory.java	2007-06-19 01:45:02 UTC (rev 12675)
@@ -0,0 +1,34 @@
+package org.jboss.txbridge.helper;
+
+import org.apache.log4j.Logger;
+import org.jboss.ws.core.CommonMessageContext;
+import org.jboss.ws.core.soap.MessageContextAssociation;
+import org.jboss.ws.metadata.umdm.EndpointMetaData;
+
+import java.util.Random;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class SimpleBATaskIdentifierFactory
+{
+    // Identifier uniqueness
+    private static int IDENTIFIER_PRECISION = 24;
+
+    // Logger
+    private static Logger log = Logger.getLogger(SimpleBATaskIdentifierFactory.class);
+
+    // Random generator
+    private static Random rg = new Random();
+
+    // Randomly generated bytes
+    byte[] taskIdentifier = new byte[IDENTIFIER_PRECISION];
+
+    // Return a class that's method is being invoked in this context
+    public String getIdentifier()
+    {
+        log.info("getIdentifier()");
+        rg.nextBytes(taskIdentifier);
+        return new String(taskIdentifier);
+    }
+}




More information about the jboss-svn-commits mailing list