[jboss-cvs] JBossAS SVN: r65848 - in trunk: ejb3/src/main/org/jboss/ejb3/embedded and 9 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Thu Oct 4 11:59:32 EDT 2007


Author: adrian at jboss.org
Date: 2007-10-04 11:59:32 -0400 (Thu, 04 Oct 2007)
New Revision: 65848

Added:
   trunk/ejb3/src/main/org/jboss/ejb3/embedded/XidFactoryMBean.java
   trunk/server/src/main/org/jboss/ejb/plugins/jms/DLQHandler.java
   trunk/server/src/main/org/jboss/ejb/plugins/jms/JMSContainerInvoker.java
   trunk/transaction/.classpath
   trunk/transaction/.project
Removed:
   trunk/iiop/src/main/org/jboss/tm/iiop/client/
   trunk/iiop/src/main/org/jboss/tm/iiop/wrapper/
   trunk/testsuite/src/main/org/jboss/test/txpropiiop/
   trunk/testsuite/src/resources/txpropiiop/
Modified:
   trunk/ejb3/.classpath
   trunk/server/.classpath
   trunk/server/.project
   trunk/testsuite/.classpath
   trunk/testsuite/.project
   trunk/testsuite/build.xml
   trunk/testsuite/imports/sections/cts.xml
   trunk/testsuite/imports/sections/tx.xml
   trunk/testsuite/imports/test-jars.xml
Log:
[JBAS-4516] - Complete the rollback of too early transaction project removal. The iiop changes have been left in place. txpropiiop tests have been removed

Modified: trunk/ejb3/.classpath
===================================================================
--- trunk/ejb3/.classpath	2007-10-04 15:46:25 UTC (rev 65847)
+++ trunk/ejb3/.classpath	2007-10-04 15:59:32 UTC (rev 65848)
@@ -12,6 +12,7 @@
 	<classpathentry kind="lib" path="/thirdparty/oswego-concurrent/lib/concurrent.jar"/>
 	<classpathentry kind="src" path="/naming"/>
 	<classpathentry kind="src" path="/aspects"/>
+	<classpathentry kind="src" path="/transaction"/>
 	<classpathentry kind="lib" path="/thirdparty/jgroups/lib/jgroups.jar"/>
 	<classpathentry kind="lib" path="/thirdparty/hibernate/lib/hibernate3.jar"/>
 	<classpathentry kind="lib" path="/thirdparty/hibernate-annotations/lib/hibernate-annotations.jar"/>

Copied: trunk/ejb3/src/main/org/jboss/ejb3/embedded/XidFactoryMBean.java (from rev 65810, trunk/ejb3/src/main/org/jboss/ejb3/embedded/XidFactoryMBean.java)
===================================================================
--- trunk/ejb3/src/main/org/jboss/ejb3/embedded/XidFactoryMBean.java	                        (rev 0)
+++ trunk/ejb3/src/main/org/jboss/ejb3/embedded/XidFactoryMBean.java	2007-10-04 15:59:32 UTC (rev 65848)
@@ -0,0 +1,167 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.ejb3.embedded;
+
+import javax.transaction.xa.Xid;
+import org.jboss.tm.*;
+
+/**
+ * Stupid wrapper because tons of services use the XidFactoryMBean interface.
+ *
+ * @author <a href="mailto:bill at jboss.org">Bill Burke</a>
+ * @version $Revision$
+ */
+public class XidFactoryMBean implements org.jboss.tm.XidFactoryMBean
+{
+   private XidFactoryBase base;
+
+   public XidFactoryMBean(XidFactoryBase base)
+   {
+      this.base = base;
+   }
+
+   public org.jboss.tm.XidFactoryMBean getInstance()
+   {
+      return this;
+   }
+
+   public String getName()
+   {
+      throw new RuntimeException("should not be called");
+   }
+
+   public int getState()
+   {
+      throw new RuntimeException("should not be called");
+   }
+
+   public String getStateString()
+   {
+      throw new RuntimeException("should not be called");
+   }
+
+   public void jbossInternalLifecycle(String method) throws Exception
+   {
+      throw new RuntimeException("should not be called");
+   }
+
+   public void create() throws Exception
+   {
+   }
+
+   public void start() throws Exception
+   {
+   }
+
+   public void stop()
+   {
+   }
+
+   public void destroy()
+   {
+   }
+
+   public String getBaseGlobalId()
+   {
+      return base.getBaseGlobalId();
+   }
+
+   public void setBaseGlobalId(String baseGlobalId)
+   {
+      base.setBaseGlobalId(baseGlobalId);
+   }
+
+   public long getGlobalIdNumber()
+   {
+      return base.getGlobalIdNumber();
+   }
+
+   public void setGlobalIdNumber(long globalIdNumber)
+   {
+      base.setGlobalIdNumber(globalIdNumber);
+   }
+
+   public String getBranchQualifier()
+   {
+      return base.getBranchQualifier();
+   }
+
+   public void setBranchQualifier(String branchQualifier)
+   {
+      base.setBranchQualifier(branchQualifier);
+   }
+
+   public boolean isPad()
+   {
+      return base.isPad();
+   }
+
+   public void setPad(boolean pad)
+   {
+      base.setPad(pad);
+   }
+
+   public XidImpl newXid()
+   {
+      return base.newXid();
+   }
+
+   public XidImpl newBranch(GlobalId globalId)
+   {
+      return base.newBranch(globalId);
+   }
+
+   public XidImpl newBranch(XidImpl xid, long branchIdNum)
+   {
+      return base.newBranch(xid, branchIdNum);
+   }
+
+   public XidImpl recreateXid(long localId)
+   {
+      return base.recreateXid(localId);
+   }
+
+   public XidImpl recreateXid(long localId, GlobalId globalId)
+   {
+      return base.recreateXid(localId, globalId);
+   }
+
+   public byte[] localIdToGlobalId(long localId)
+   {
+      return base.localIdToGlobalId(localId);
+   }
+
+   public long extractLocalIdFrom(byte[] globalId)
+   {
+      return base.extractLocalIdFrom(globalId);
+   }
+
+   public String getBaseBranchQualifier(byte[] branchQualifier)
+   {
+      return base.getBaseBranchQualifier(branchQualifier);
+   }
+
+   public String toString(Xid xid)
+   {
+      return base.toString(xid);
+   }
+}

Modified: trunk/server/.classpath
===================================================================
--- trunk/server/.classpath	2007-10-04 15:46:25 UTC (rev 65847)
+++ trunk/server/.classpath	2007-10-04 15:59:32 UTC (rev 65848)
@@ -25,6 +25,7 @@
 	<classpathentry kind="lib" path="/thirdparty/jboss/jbossxb/lib/jboss-xml-binding.jar"/>
 	<classpathentry kind="lib" path="/thirdparty/hibernate-entitymanager/lib/ejb3-persistence.jar"/>
 	<classpathentry combineaccessrules="false" kind="src" path="/system-jmx"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/transaction"/>
 	<classpathentry kind="lib" path="/thirdparty/jboss/microcontainer/lib/jboss-container.jar" sourcepath="/thirdparty/jboss/microcontainer/lib/jboss-container-sources.jar"/>
 	<classpathentry kind="lib" path="/thirdparty/jboss/microcontainer/lib/jboss-dependency.jar" sourcepath="/thirdparty/jboss/microcontainer/lib/jboss-dependency-sources.jar"/>
 	<classpathentry kind="lib" path="/thirdparty/jboss/jbossws/lib/jboss-jaxrpc.jar"/>

Modified: trunk/server/.project
===================================================================
--- trunk/server/.project	2007-10-04 15:46:25 UTC (rev 65847)
+++ trunk/server/.project	2007-10-04 15:59:32 UTC (rev 65848)
@@ -8,6 +8,7 @@
 		<project>jmx</project>
 		<project>naming</project>
 		<project>system</project>
+		<project>transaction</project>
 	</projects>
 	<buildSpec>
 		<buildCommand>

Copied: trunk/server/src/main/org/jboss/ejb/plugins/jms/DLQHandler.java (from rev 65809, trunk/server/src/main/org/jboss/ejb/plugins/jms/DLQHandler.java)
===================================================================
--- trunk/server/src/main/org/jboss/ejb/plugins/jms/DLQHandler.java	                        (rev 0)
+++ trunk/server/src/main/org/jboss/ejb/plugins/jms/DLQHandler.java	2007-10-04 15:59:32 UTC (rev 65848)
@@ -0,0 +1,518 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.ejb.plugins.jms;
+
+import java.util.Hashtable;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Enumeration;
+import java.util.Iterator;
+
+import javax.naming.Context;
+import javax.jms.ExceptionListener;
+import javax.jms.Session;
+import javax.jms.QueueConnection;
+import javax.jms.QueueConnectionFactory;
+import javax.jms.QueueSession;
+import javax.jms.QueueSender;
+import javax.jms.Queue;
+import javax.jms.Message;
+import javax.jms.JMSException;
+import javax.jms.Destination;
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.Transaction;
+
+import org.w3c.dom.Element;
+
+import org.jboss.deployment.DeploymentException;
+import org.jboss.metadata.MetaData;
+import org.jboss.jms.jndi.JMSProviderAdapter;
+import org.jboss.system.ServiceMBeanSupport;
+
+/**
+ * Places redeliveded messages on a Dead Letter Queue.
+ *
+ *<p>
+ *The Dead Letter Queue handler is used to not set JBoss in an endles loop
+ * when a message is resent on and on due to transaction rollback for
+ * message receipt.
+ *
+ * <p>
+ * It sends message to a dead letter queue (configurable, defaults to
+ * queue/DLQ) when the message has been resent a configurable amount of times,
+ * defaults to 10.
+ *
+ * <p>
+ * The handler is configured through the element MDBConfig in
+ * container-invoker-conf.
+ *
+ * <p>
+ * The JMS property JBOSS_ORIG_DESTINATION in the resent message is set
+ * to the name of the original destination (Destination.toString())
+ * if it is present.
+ *
+ * <p>
+ * The JMS property JBOSS_ORIG_MESSAGEID in the resent message is set
+ * to the id of the original message.
+ *
+ * @author <a href="mailto:jason at planet57.com">Jason Dillon</a>
+ * @author Scott.Stark at jboss.org
+ * @author Adrian Brock
+ * @version <tt>$Revision$</tt>
+ */
+public class DLQHandler extends ServiceMBeanSupport implements ExceptionListener
+{
+   /** Standard property for delivery count */
+   public static final String PROPERTY_DELIVERY_COUNT = "JMSXDeliveryCount";
+
+   /** JMS property name holding original destination. */
+   public static final String JBOSS_ORIG_DESTINATION = "JBOSS_ORIG_DESTINATION";
+
+   /** JMS property name holding original JMS message id. */
+   public static final String JBOSS_ORIG_MESSAGEID = "JBOSS_ORIG_MESSAGEID";
+
+   /** Properties copied from org.jboss.mq.SpyMessage */
+   private static final String JMS_JBOSS_REDELIVERY_COUNT = "JMS_JBOSS_REDELIVERY_COUNT";
+   private static final String JMS_JBOSS_REDELIVERY_LIMIT = "JMS_JBOSS_REDELIVERY_LIMIT";
+
+   /**
+    * Destination to send dead letters to.
+    * 
+    * <p>
+    * Defaults to <em>queue/DLQ</em>, configurable through
+    * <tt>DestinationQueue</tt> element.
+    */
+   private String destinationJNDI = "queue/DLQ";
+
+   /**
+    * Maximum times a message is alowed to be resent.
+    *
+    * <p>Defaults to <em>10</em>, configurable through
+    * <tt>MaxTimesRedelivered</tt> element.
+    */
+   private int maxResent = 10;
+
+   /**
+    * Time to live for the message.
+    *
+    * <p>
+    * Defaults to <em>{@link Message#DEFAULT_TIME_TO_LIVE}</em>, 
+    * configurable through the <tt>TimeToLive</tt> element.
+    */
+   private long timeToLive = Message.DEFAULT_TIME_TO_LIVE;
+   
+   // May become configurable
+   
+   /** Delivery mode for message, Message.DEFAULT_DELIVERY_MODE. */
+   private int deliveryMode = Message.DEFAULT_DELIVERY_MODE;
+
+   /** Priority for the message, Message.DEFAULT_PRIORITY */
+   private int priority = Message.DEFAULT_PRIORITY;
+
+   /** The dlq user for the connection */
+   private String dlqUser;
+
+   /** The dlq password for the connection */
+   private String dlqPass;
+
+   // Private stuff
+   private QueueConnection connection;
+   private Queue dlq;
+   private JMSProviderAdapter providerAdapter;
+   private JMSContainerInvoker invoker;
+   private Hashtable resentBuffer = new Hashtable();
+
+   public DLQHandler(final JMSProviderAdapter providerAdapter, final JMSContainerInvoker invoker)
+   {
+      this.providerAdapter = providerAdapter;
+      this.invoker = invoker;
+   }
+   
+   public void onException(JMSException e)
+   {
+      if (invoker != null && invoker.exListener != null)
+         invoker.exListener.handleFailure(e);
+      else
+      {
+         log.warn("DLQHandler got JMS Failure but there is no link to JMSContainerInvoker's exception listener.", e);
+
+         // We shouldn't get here, but if we do, we should at least close the connection 
+         if (connection != null)
+         {
+            try
+            {
+               connection.close();
+            }
+            catch (Throwable ignored)
+            {
+               log.trace("Ignored error closing connection", ignored);
+            }
+            connection = null;
+         }
+      }
+   }
+   
+   protected void createService() throws Exception
+   {
+      Context ctx = providerAdapter.getInitialContext();
+
+      try
+      {
+         String factoryName = providerAdapter.getQueueFactoryRef();
+         QueueConnectionFactory factory = (QueueConnectionFactory)
+            ctx.lookup(factoryName);
+         log.debug("Using factory: " + factory);
+
+         if (dlqUser == null)
+            connection = factory.createQueueConnection();
+         else
+            connection = factory.createQueueConnection(dlqUser, dlqPass);
+         log.debug("Created connection: " + connection);
+
+         dlq = (Queue) ctx.lookup(destinationJNDI);
+         log.debug("Using Queue: " + dlq);
+      }
+      finally
+      {
+         ctx.close();
+      }
+   }
+   
+   protected void startService() throws Exception
+   {
+      connection.setExceptionListener(this);
+      connection.start();
+   }
+
+   protected void stopService() throws Exception
+   {
+      try
+      {
+         connection.setExceptionListener(null);
+         connection.stop();
+      }
+      catch (Throwable t)
+      {
+         log.trace("Ignored error stopping DLQ", t);
+      }
+   }
+
+   protected void destroyService() throws Exception
+   {
+      // Help the GC
+      if (connection != null)
+         connection.close();
+      connection = null;
+      dlq = null;
+      providerAdapter = null;
+   }
+   
+   /**
+    * Check if a message has been redelivered to many times.
+    *
+    * If message has been redelivered to many times, send it to the
+    * dead letter queue (default to queue/DLQ).
+    *
+    * @return true if message is handled (i.e resent), false if not.
+    */
+   public boolean handleRedeliveredMessage(final Message msg, final Transaction tx)
+   {
+      boolean handled = false;
+      int max = this.maxResent;
+      String id = null;
+      boolean fromMessage = true;
+      int count = 0;
+
+      try
+      {
+
+         if (msg.propertyExists(JMS_JBOSS_REDELIVERY_LIMIT))
+            max = msg.getIntProperty(JMS_JBOSS_REDELIVERY_LIMIT);
+
+         try
+         {
+            if (msg.propertyExists(PROPERTY_DELIVERY_COUNT))
+               count = msg.getIntProperty(PROPERTY_DELIVERY_COUNT);
+         }
+         catch (JMSException ignored)
+         {
+         }
+         if (count > 0)
+         {
+            // The delivery count is one too many
+            --count;
+         }
+         else if (msg.propertyExists(JMS_JBOSS_REDELIVERY_COUNT))
+            count = msg.getIntProperty(JMS_JBOSS_REDELIVERY_COUNT);
+         else
+         {
+            id = msg.getJMSMessageID();
+            if (id == null)
+            {
+               // if we can't get the id we are basically fucked
+               log.error("Message id is null, can't handle message");
+               return false;
+            }
+            count = incrementResentCount(id);
+            fromMessage = false;
+         }
+
+         if (count > max)
+         {
+            id = msg.getJMSMessageID();
+            log.warn("Message resent too many times; sending it to DLQ; message id=" + id);
+
+            sendMessage(msg);
+            deleteFromBuffer(id);
+
+            handled = true;
+         }
+         else if (fromMessage == false && tx != null)
+         {
+            // Register a synchronization to remove the buffer entry
+            // should the transaction commit
+            DLQSynchronization synch = new DLQSynchronization(id);
+            try
+            {
+               tx.registerSynchronization(synch);
+            }
+            catch (Exception e)
+            {
+               log.warn("Error registering DlQ Synchronization with transaction " + tx, e);
+            }
+         }
+      }
+      catch (JMSException e)
+      {
+         // If we can't send it ahead, we do not dare to just drop it...or?
+         log.error("Could not send message to Dead Letter Queue", e);
+      }
+
+      return handled;
+   }
+
+   /**
+    * Send message to the configured dead letter queue, defaults to queue/DLQ.
+    */
+   protected void sendMessage(Message msg) throws JMSException
+   {
+      boolean trace = log.isTraceEnabled();
+
+      QueueSession session = null;
+      QueueSender sender = null;
+
+      try
+      {
+         msg = makeWritable(msg, trace); // Don't know yet if we are gona clone or not
+         
+         // Set the properties
+         msg.setStringProperty(JBOSS_ORIG_MESSAGEID, msg.getJMSMessageID());
+         // Some providers (say Websphere MQ) don't set this to something we can use
+         Destination d = msg.getJMSDestination();
+         if (d != null)
+            msg.setStringProperty(JBOSS_ORIG_DESTINATION, d.toString());
+
+         session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
+         sender = session.createSender(dlq);
+         if (trace)
+         {
+            log.trace("Sending message to DLQ; destination=" +
+               dlq + ", session=" + session + ", sender=" + sender);
+         }
+
+         sender.send(msg, deliveryMode, priority, timeToLive);
+
+         if (trace)
+         {
+            log.trace("Message sent.");
+         }
+
+      }
+      finally
+      {
+         try
+         {
+            if (sender != null) sender.close();
+            if (session != null) session.close();
+         }
+         catch (Exception e)
+         {
+            log.warn("Failed to close sender or session; ignoring", e);
+         }
+      }
+   }
+
+   /**
+    * Increment the counter for the specific JMS message id.
+    *
+    * @return the new counter value.
+    */
+   protected int incrementResentCount(String id)
+   {
+      BufferEntry entry = null;
+      boolean trace = log.isTraceEnabled();
+      if (!resentBuffer.containsKey(id))
+      {
+         if (trace)
+            log.trace("Making new entry for id " + id);
+         entry = new BufferEntry();
+         entry.id = id;
+         entry.count = 1;
+         resentBuffer.put(id, entry);
+      }
+      else
+      {
+         entry = (BufferEntry) resentBuffer.get(id);
+         entry.count++;
+         if (trace)
+            log.trace("Incremented old entry for id " + id + " count " + entry.count);
+      }
+      return entry.count;
+   }
+
+   /**
+    * Delete the entry in the message counter buffer for specifyed JMS id.
+    */
+   protected void deleteFromBuffer(String id)
+   {
+      resentBuffer.remove(id);
+   }
+
+   /**
+    * Make the Message properties writable.
+    *
+    * @return the writable message.
+    */
+   protected Message makeWritable(Message msg, boolean trace) throws JMSException
+   {
+      HashMap tmp = new HashMap();
+
+      // Save properties
+      for (Enumeration en = msg.getPropertyNames(); en.hasMoreElements();)
+      {
+         String key = (String) en.nextElement();
+         tmp.put(key, msg.getObjectProperty(key));
+      }
+      
+      // Make them writable
+      msg.clearProperties();
+
+      Iterator i = tmp.entrySet().iterator();
+      while (i.hasNext())
+      {
+         Map.Entry me = (Map.Entry)i.next();
+         String key = (String) me.getKey();
+         try
+         {
+            msg.setObjectProperty(key, me.getValue());
+         }
+         catch (JMSException ignored)
+         {
+            if (trace)
+               log.trace("Could not copy message property " + key, ignored);
+         }
+      }
+
+      return msg;
+   }
+
+   /**
+    * Takes an MDBConfig Element
+    */
+   public void importXml(final Element element) throws DeploymentException
+   {
+      destinationJNDI = MetaData.getElementContent
+         (MetaData.getUniqueChild(element, "DestinationQueue"));
+
+      try
+      {
+         String mr = MetaData.getElementContent
+            (MetaData.getUniqueChild(element, "MaxTimesRedelivered"));
+         maxResent = Integer.parseInt(mr);
+      }
+      catch (Exception ignore)
+      {
+      }
+
+      try
+      {
+         String ttl = MetaData.getElementContent
+            (MetaData.getUniqueChild(element, "TimeToLive"));
+         timeToLive = Long.parseLong(ttl);
+
+         if (timeToLive < 0)
+         {
+            log.warn("Invalid TimeToLive: " + timeToLive + "; using default");
+            timeToLive = Message.DEFAULT_TIME_TO_LIVE;
+         }
+      }
+      catch (Exception ignore)
+      {
+      }
+
+      dlqUser = MetaData.getElementContent(MetaData.getOptionalChild(element, "DLQUser"));
+      dlqPass = MetaData.getElementContent(MetaData.getOptionalChild(element, "DLQPassword"));
+   }
+
+   public String toString()
+   {
+      return super.toString() +
+         "{ destinationJNDI=" + destinationJNDI +
+         ", maxResent=" + maxResent +
+         ", timeToLive=" + timeToLive +
+         " }";
+   }
+
+   private static class BufferEntry
+   {
+      int count;
+      String id;
+   }
+
+   /**
+    * Remove a redelivered message from the DLQ's buffer when it is acknowledged
+    */
+   protected class DLQSynchronization implements Synchronization
+   {
+      /** The message id */
+      String id;
+
+      public DLQSynchronization(String id)
+      {
+         this.id = id;
+      }
+
+      public void beforeCompletion()
+      {
+      }
+
+      /**
+       * Forget the message when the transaction commits
+       */
+      public void afterCompletion(int status)
+      {
+         if (status == Status.STATUS_COMMITTED)
+            deleteFromBuffer(id);
+      }
+   }
+}

Copied: trunk/server/src/main/org/jboss/ejb/plugins/jms/JMSContainerInvoker.java (from rev 65809, trunk/server/src/main/org/jboss/ejb/plugins/jms/JMSContainerInvoker.java)
===================================================================
--- trunk/server/src/main/org/jboss/ejb/plugins/jms/JMSContainerInvoker.java	                        (rev 0)
+++ trunk/server/src/main/org/jboss/ejb/plugins/jms/JMSContainerInvoker.java	2007-10-04 15:59:32 UTC (rev 65848)
@@ -0,0 +1,1600 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.ejb.plugins.jms;
+
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.Principal;
+import java.security.PrivilegedAction;
+import java.util.Collection;
+
+import javax.ejb.EJBMetaData;
+import javax.jms.Connection;
+import javax.jms.ConnectionConsumer;
+import javax.jms.Destination;
+import javax.jms.ExceptionListener;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+import javax.jms.Queue;
+import javax.jms.QueueConnection;
+import javax.jms.ServerSessionPool;
+import javax.jms.Topic;
+import javax.jms.TopicConnection;
+import javax.management.MBeanServer;
+import javax.management.Notification;
+import javax.management.ObjectName;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.jboss.deployment.DeploymentException;
+import org.jboss.ejb.Container;
+import org.jboss.ejb.EJBProxyFactory;
+import org.jboss.invocation.Invocation;
+import org.jboss.invocation.InvocationType;
+import org.jboss.jms.ConnectionFactoryHelper;
+import org.jboss.jms.asf.ServerSessionPoolFactory;
+import org.jboss.jms.asf.StdServerSessionPool;
+import org.jboss.jms.jndi.JMSProviderAdapter;
+import org.jboss.logging.Logger;
+import org.jboss.metadata.ActivationConfigPropertyMetaData;
+import org.jboss.metadata.InvokerProxyBindingMetaData;
+import org.jboss.metadata.MessageDestinationMetaData;
+import org.jboss.metadata.MessageDrivenMetaData;
+import org.jboss.metadata.MetaData;
+import org.jboss.system.ServiceMBeanSupport;
+import org.w3c.dom.Element;
+
+/**
+ * EJBProxyFactory for JMS MessageDrivenBeans
+ * 
+ * @author <a href="mailto:peter.antman at tim.se">Peter Antman</a> .
+ * @author <a href="mailto:rickard.oberg at telkel.com">Rickard Oberg</a>
+ * @author <a href="mailto:sebastien.alborini at m4x.org">Sebastien Alborini</a>
+ * @author <a href="mailto:marc.fleury at telkel.com">Marc Fleury</a>
+ * @author <a href="mailto:jason at planet57.com">Jason Dillon</a>
+ * @author <a href="mailto:adrian at jboss.com">Adrian Brock</a>
+ * @version <tt>$Revision$</tt>
+ */
+public class JMSContainerInvoker extends ServiceMBeanSupport
+   implements EJBProxyFactory, JMSContainerInvokerMBean
+{
+   /** The logger */
+   private static final Logger log = Logger.getLogger(JMSContainerInvoker.class);
+   
+   /** Notification sent before connectioning */
+   private static final String CONNECTING_NOTIFICATION = "org.jboss.ejb.plugins.jms.CONNECTING";
+
+   /** Notification sent after connection */
+   private static final String CONNECTED_NOTIFICATION = "org.jboss.ejb.plugins.jms.CONNECTED";
+
+   /** Notification sent before disconnection */
+   private static final String DISCONNECTING_NOTIFICATION = "org.jboss.ejb.plugins.jms.DISCONNECTING";
+
+   /** Notification sent before disconnected */
+   private static final String DISCONNECTED_NOTIFICATION = "org.jboss.ejb.plugins.jms.DISCONNECTED";
+
+   /** Notification sent at connection failure */
+   private static final String FAILURE_NOTIFICATION = "org.jboss.ejb.plugins.jms.FAILURE";
+   
+   /** {@link MessageListener#onMessage} reference. */
+   protected static Method ON_MESSAGE;
+
+   /**
+    * Default destination type. Used when no message-driven-destination is given
+    * in ejb-jar, and a lookup of destinationJNDI from jboss.xml is not
+    * successfull. Default value: javax.jms.Topic.
+    */
+   protected final static String DEFAULT_DESTINATION_TYPE = "javax.jms.Topic";
+   
+   /**
+    * Initialize the ON_MESSAGE reference.
+    */
+   static
+   {
+      try
+      {
+         final Class type = MessageListener.class;
+         final Class arg = Message.class;
+         ON_MESSAGE = type.getMethod("onMessage", new Class[]{arg});
+      }
+      catch (Exception e)
+      {
+         throw new ExceptionInInitializerError(e);
+      }
+   }
+   
+   protected boolean optimize;
+
+   /** Maximum number provider is allowed to stuff into a session. */
+   protected int maxMessagesNr = 1;
+
+   /** Minimun pool size of server sessions. */
+   protected int minPoolSize = 1;
+
+   /** Keep alive server sessions. */
+   protected long keepAlive = 30 * 1000;
+
+   /** Maximun pool size of server sessions. */
+   protected int maxPoolSize = 15;
+
+   /** Time to wait before retrying to reconnect a lost connection. */
+   protected long reconnectInterval = 10000;
+
+   /** If Dead letter queue should be used or not. */
+   protected boolean useDLQ = false;
+
+   /**
+    * JNDI name of the provider adapter.
+    * 
+    * @see org.jboss.jms.jndi.JMSProviderAdapter
+    */
+   protected String providerAdapterJNDI;
+
+   /**
+    * JNDI name of the server session factory.
+    * 
+    * @see org.jboss.jms.asf.ServerSessionPoolFactory
+    */
+   protected String serverSessionPoolFactoryJNDI;
+
+   /** JMS acknowledge mode, used when session is not XA. */
+   protected int acknowledgeMode;
+
+   protected boolean isContainerManagedTx;
+   protected boolean isNotSupportedTx;
+
+   /** The container. */
+   protected Container container;
+
+   /** The JMS connection. */
+   protected Connection connection;
+
+   /** The JMS connection consumer. */
+   protected ConnectionConsumer connectionConsumer;
+
+   protected TransactionManager tm;
+   protected ServerSessionPool pool;
+   protected ExceptionListenerImpl exListener;
+
+   /** Dead letter queue handler. */
+   protected DLQHandler dlqHandler;
+
+   /** DLQConfig element from MDBConfig element from jboss.xml. */
+   protected Element dlqConfig;
+
+   protected InvokerProxyBindingMetaData invokerMetaData;
+   protected String invokerBinding;
+
+   protected boolean deliveryActive = true;
+
+   protected boolean createJBossMQDestination = false;
+
+   /**
+    * Set the invoker meta data so that the ProxyFactory can initialize
+    * properly
+    */
+   public void setInvokerMetaData(InvokerProxyBindingMetaData imd)
+   {
+      invokerMetaData = imd;
+   }
+
+   /**
+    * Set the invoker jndi binding
+    */
+   public void setInvokerBinding(String binding)
+   {
+      invokerBinding = binding;
+   }
+   
+   /**
+    * Set the container for which this is an invoker to.
+    * 
+    * @param container The container for which this is an invoker to.
+    */
+   public void setContainer(final Container container)
+   {
+      this.container = container;
+   }
+
+   public int getMinPoolSize()
+   {
+      return minPoolSize;
+   }
+
+   public void setMinPoolSize(int minPoolSize)
+   {
+      this.minPoolSize = minPoolSize;
+   }
+
+   public int getMaxPoolSize()
+   {
+      return maxPoolSize;
+   }
+
+   public void setMaxPoolSize(int maxPoolSize)
+   {
+      this.maxPoolSize = maxPoolSize;
+   }
+
+   public long getKeepAliveMillis()
+   {
+      return keepAlive;
+   }
+
+   public void setKeepAliveMillis(long keepAlive)
+   {
+      this.keepAlive = keepAlive;
+   }
+
+   public int getMaxMessages()
+   {
+      return maxMessagesNr;
+   }
+
+   public void setMaxMessages(int maxMessages)
+   {
+      this.maxMessagesNr = maxMessages;
+   }
+
+   public MessageDrivenMetaData getMetaData()
+   {
+      MessageDrivenMetaData config =
+         (MessageDrivenMetaData) container.getBeanMetaData();
+      return config;
+   }
+
+   public boolean getDeliveryActive()
+   {
+      return deliveryActive;
+   }
+
+   public boolean getCreateJBossMQDestination()
+   {
+      return createJBossMQDestination;
+   }
+
+   public void startDelivery()
+      throws Exception
+   {
+      if (getState() != STARTED)
+         throw new IllegalStateException("The MDB is not started");
+      if (deliveryActive)
+         return;
+      deliveryActive = true;
+      startService();
+   }
+
+   public void stopDelivery()
+      throws Exception
+   {
+      if (getState() != STARTED)
+         throw new IllegalStateException("The MDB is not started");
+      if (deliveryActive == false)
+         return;
+      deliveryActive = false;
+      stopService();
+   }
+
+   /**
+    * Sets the Optimized attribute of the JMSContainerInvoker object
+    * 
+    * @param optimize The new Optimized value
+    */
+   public void setOptimized(final boolean optimize)
+   {
+      this.optimize = optimize;
+   }
+
+   public boolean isIdentical(Container container, Invocation mi)
+   {
+      throw new Error("Not valid for MessageDriven beans");
+   }
+
+   public Object getEJBHome()
+   {
+      throw new Error("Not valid for MessageDriven beans");
+   }
+
+   public EJBMetaData getEJBMetaData()
+   {
+      throw new Error("Not valid for MessageDriven beans");
+   }
+
+   public Collection getEntityCollection(Collection ids)
+   {
+      throw new Error("Not valid for MessageDriven beans");
+   }
+
+   public Object getEntityEJBObject(Object id)
+   {
+      throw new Error("Not valid for MessageDriven beans");
+   }
+
+   public Object getStatefulSessionEJBObject(Object id)
+   {
+      throw new Error("Not valid for MessageDriven beans");
+   }
+
+   public Object getStatelessSessionEJBObject()
+   {
+      throw new Error("Not valid for MessageDriven beans");
+   }
+
+   public boolean isOptimized()
+   {
+      return optimize;
+   }
+
+   /**
+    * XmlLoadable implementation.
+    *
+    * @todo FIXME - we ought to move all config into MDBConfig, but I do not do that
+    * now due to backward compatibility.
+    * 
+    * @param element Description of Parameter
+    * @throws DeploymentException Description of Exception
+    */
+   public void importXml(final Element element) throws Exception
+   {
+      try
+      {
+         if ("false".equalsIgnoreCase(MetaData.getElementContent(MetaData.getUniqueChild(element, "CreateJBossMQDestination"))))
+         {
+            createJBossMQDestination = false;
+         }
+      }
+      catch (Exception ignore)
+      {
+      }
+      
+      try
+      {
+         String maxMessages = MetaData.getElementContent
+            (MetaData.getUniqueChild(element, "MaxMessages"));
+         maxMessagesNr = Integer.parseInt(maxMessages);
+      }
+      catch (Exception ignore)
+      {
+      }
+
+      try
+      {
+         String minSize = MetaData.getElementContent
+            (MetaData.getUniqueChild(element, "MinimumSize"));
+         minPoolSize = Integer.parseInt(minSize);
+      }
+      catch (Exception ignore)
+      {
+      }
+
+      try
+      {
+         String maxSize = MetaData.getElementContent
+            (MetaData.getUniqueChild(element, "MaximumSize"));
+         maxPoolSize = Integer.parseInt(maxSize);
+      }
+      catch (Exception ignore)
+      {
+      }
+
+      try
+      {
+         String keepAliveMillis = MetaData.getElementContent
+            (MetaData.getUniqueChild(element, "KeepAliveMillis"));
+         keepAlive = Integer.parseInt(keepAliveMillis);
+      }
+      catch (Exception ignore)
+      {
+      }
+
+      Element mdbConfig = MetaData.getUniqueChild(element, "MDBConfig");
+
+      try
+      {
+         String reconnect = MetaData.getElementContent
+            (MetaData.getUniqueChild(mdbConfig, "ReconnectIntervalSec"));
+         reconnectInterval = Long.parseLong(reconnect) * 1000;
+      }
+      catch (Exception ignore)
+      {
+      }
+
+      try
+      {
+         if ("false".equalsIgnoreCase(MetaData.getElementContent(MetaData.getUniqueChild(mdbConfig, "DeliveryActive"))))
+         {
+            deliveryActive = false;
+         }
+      }
+      catch (Exception ignore)
+      {
+      }
+         
+      // Get Dead letter queue config - and save it for later use
+      Element dlqEl = MetaData.getOptionalChild(mdbConfig, "DLQConfig");
+      if (dlqEl != null)
+      {
+         dlqConfig = (Element) dlqEl.cloneNode(true);
+         useDLQ = true;
+      }
+      else
+      {
+         useDLQ = false;
+      }
+
+      // If these are not found we will get a DeploymentException, I hope
+      providerAdapterJNDI = MetaData.getElementContent
+         (MetaData.getUniqueChild(element, "JMSProviderAdapterJNDI"));
+
+      serverSessionPoolFactoryJNDI = MetaData.getElementContent
+         (MetaData.getUniqueChild(element, "ServerSessionPoolFactoryJNDI"));
+
+      // Check java:/ prefix
+      if (!providerAdapterJNDI.startsWith("java:/"))
+      {
+         providerAdapterJNDI = "java:/" + providerAdapterJNDI;
+      }
+
+      if (!serverSessionPoolFactoryJNDI.startsWith("java:/"))
+      {
+         serverSessionPoolFactoryJNDI = "java:/" + serverSessionPoolFactoryJNDI;
+      }
+   }
+
+   /**
+    * Initialize the container invoker. Sets up a connection, a server session
+    * pool and a connection consumer for the configured destination.
+    *
+    * <p>Any JMSExceptions produced while initializing will be assumed to be caused
+    * due to JMS Provider failure.
+    * 
+    * @throws Exception Failed to initalize.
+    */
+   protected void createService() throws Exception
+   {
+      importXml(invokerMetaData.getProxyFactoryConfig());
+
+      exListener = new ExceptionListenerImpl(this);
+   }
+
+   /**
+    * Initialize the container invoker. Sets up a connection, a server session
+    * pool and a connection consumer for the configured destination.
+    * 
+    * @throws Exception Failed to initalize.
+    */
+   protected void innerStartDelivery() throws Exception
+   {
+      if (deliveryActive == false)
+      {
+         log.debug("Delivery is disabled");
+         return;
+      }
+      
+      sendNotification(CONNECTING_NOTIFICATION, null);
+
+      log.debug("Initializing");
+
+      // Get the JMS provider
+      JMSProviderAdapter adapter = getJMSProviderAdapter();
+      log.debug("Provider adapter: " + adapter);
+      
+      // Set up Dead Letter Queue handler  
+      if (useDLQ)
+      {
+         dlqHandler = new DLQHandler(adapter, this);
+         dlqHandler.importXml(dlqConfig);
+         dlqHandler.create();
+      }
+      
+      // Store TM reference locally - should we test for CMT Required
+      tm = container.getTransactionManager();
+      
+      // Get configuration information - from EJB-xml
+      MessageDrivenMetaData config = getMetaData();
+      
+      // Selector
+      String messageSelector = config.getMessageSelector();
+      String activationConfig = getActivationConfigProperty("messageSelector");
+      if (activationConfig != null)
+         messageSelector = activationConfig;
+      
+      // Queue or Topic - optional unfortunately
+      String destinationType = config.getDestinationType();
+      activationConfig = getActivationConfigProperty("destinationType");
+      if (activationConfig != null)
+         destinationType = activationConfig;
+      
+      // Is container managed?
+      isContainerManagedTx = config.isContainerManagedTx();
+      acknowledgeMode = config.getAcknowledgeMode();
+      activationConfig = getActivationConfigProperty("acknowledgeMode");
+      if (activationConfig != null)
+      {
+         if (activationConfig.equals("DUPS_OK_ACKNOWLEDGE"))
+            acknowledgeMode = MessageDrivenMetaData.DUPS_OK_ACKNOWLEDGE_MODE;
+         else
+            acknowledgeMode = MessageDrivenMetaData.AUTO_ACKNOWLEDGE_MODE;
+      }
+      
+      byte txType = config.getMethodTransactionType("onMessage",
+         new Class[]{Message.class},
+         InvocationType.LOCAL);
+      isNotSupportedTx = txType == MetaData.TX_NOT_SUPPORTED; 
+      
+      // Get configuration data from jboss.xml
+      String destinationJNDI = config.getDestinationJndiName();
+      activationConfig = getActivationConfigProperty("destination");
+      if (activationConfig != null)
+         destinationJNDI = activationConfig;
+      // Try any EJB21 destination link
+      if (destinationJNDI == null)
+      {
+         String link = config.getDestinationLink();
+         if (link != null)
+         {
+            link = link.trim();
+            if (link.length() > 0)
+            {
+               MessageDestinationMetaData destinationMetaData = container.getMessageDestination(link);
+               if (destinationMetaData == null)
+                  log.warn("Unresolved message-destination-link '" + link + "' no message-destination in ejb-jar.xml");
+               else
+               {
+                  String jndiName = destinationMetaData.getJNDIName();
+                  if (jndiName == null)
+                     log.warn("The message-destination '" + link + "' has no jndi-name in jboss.xml");
+                  else
+                     destinationJNDI = jndiName;
+               }
+            }
+         }
+      }
+      
+      String user = config.getUser();
+      String password = config.getPasswd();
+      
+      // Connect to the JNDI server and get a reference to root context
+      Context context = adapter.getInitialContext();
+      log.debug("context: " + context);
+      
+      // if we can't get the root context then exit with an exception
+      if (context == null)
+      {
+         throw new RuntimeException("Failed to get the root context");
+      }
+      
+      // Get the JNDI suffix of the destination
+      String jndiSuffix = parseJndiSuffix(destinationJNDI, config.getEjbName());
+      log.debug("jndiSuffix: " + jndiSuffix);
+      
+      // Unfortunately the destination is optional, so if we do not have one
+      // here we have to look it up if we have a destinationJNDI, else give it
+      // a default.
+      if (destinationType == null)
+      {
+         log.warn("No message-driven-destination given; using; guessing type");
+         destinationType = getDestinationType(context, destinationJNDI);
+      }
+
+      if ("javax.jms.Topic".equals(destinationType))
+      {
+         log.debug("Got destination type Topic for " + config.getEjbName());
+         
+         // create a topic connection
+         Object factory = context.lookup(adapter.getTopicFactoryRef());
+         TopicConnection tConnection = null;
+         try
+         {
+            tConnection = ConnectionFactoryHelper.createTopicConnection(factory, user, password);
+            connection = tConnection;
+         }
+         catch (ClassCastException e)
+         {
+            throw new DeploymentException("Expected a TopicConnection check your provider adaptor: "
+               + adapter.getTopicFactoryRef());
+         }
+
+         try
+         {
+            // Fix: ClientId must be set as the first method call after connection creation.
+            // Fix: ClientId is necessary for durable subscriptions.
+
+            String clientId = config.getClientId();
+            activationConfig = getActivationConfigProperty("clientID");
+            if (activationConfig != null)
+               clientId = activationConfig;
+
+            log.debug("Using client id: " + clientId);
+            if (clientId != null && clientId.length() > 0)
+               connection.setClientID(clientId);
+
+            // lookup or create the destination topic
+            Topic topic = null;
+            try
+            {
+               // First we try the specified topic
+               if (destinationJNDI != null)
+                  topic = (Topic) context.lookup(destinationJNDI);
+               else if (createJBossMQDestination == false)
+                  throw new DeploymentException("Unable to determine destination for '" + container.getBeanMetaData().getEjbName()
+                        + "' use destination-jndi-name in jboss.xml, an activation config property or a message-destination-link");
+            }
+            catch (NamingException e)
+            {
+               if (createJBossMQDestination == false)
+                  throw new DeploymentException("Could not find the topic destination-jndi-name=" + destinationJNDI, e);
+               log.warn("Could not find the topic destination-jndi-name=" + destinationJNDI, e);
+            }
+            catch (ClassCastException e)
+            {
+               throw new DeploymentException("Expected a Topic destination-jndi-name=" + destinationJNDI, e);
+            }
+
+            // FIXME: This is not portable, only works for JBossMQ
+            if (topic == null)
+               topic = (Topic) createDestination(Topic.class,
+                  context,
+                  "topic/" + jndiSuffix,
+                  jndiSuffix);
+            
+            // set up the server session pool
+            pool = createSessionPool(
+               topic,
+               tConnection,
+               minPoolSize,
+               maxPoolSize,
+               keepAlive,
+               true, // tx
+               acknowledgeMode,
+               new MessageListenerImpl(this));
+
+            int subscriptionDurablity = config.getSubscriptionDurability();
+            activationConfig = getActivationConfigProperty("subscriptionDurability");
+            if (activationConfig != null)
+            {
+               if (activationConfig.equals("Durable"))
+                  subscriptionDurablity = MessageDrivenMetaData.DURABLE_SUBSCRIPTION;
+               else
+                  subscriptionDurablity = MessageDrivenMetaData.NON_DURABLE_SUBSCRIPTION;
+            }
+            // To be no-durable or durable
+            if (subscriptionDurablity != MessageDrivenMetaData.DURABLE_SUBSCRIPTION)
+            {
+               // Create non durable
+               connectionConsumer =
+                  tConnection.createConnectionConsumer(topic,
+                     messageSelector,
+                     pool,
+                     maxMessagesNr);
+            }
+            else
+            {
+               // Durable subscription
+               String durableName = config.getSubscriptionId();
+               activationConfig = getActivationConfigProperty("subscriptionName");
+               if (activationConfig != null)
+                  durableName = activationConfig;
+
+               connectionConsumer =
+                  tConnection.createDurableConnectionConsumer(topic,
+                     durableName,
+                     messageSelector,
+                     pool,
+                     maxMessagesNr);
+            }
+            log.debug("Topic connectionConsumer set up");
+         }
+         catch (Throwable t)
+         {
+            try
+            {
+               tConnection.close();
+            }
+            catch (Throwable ignored)
+            {
+            }
+            DeploymentException.rethrowAsDeploymentException("Error during topic setup", t);
+         }
+      }
+      else if ("javax.jms.Queue".equals(destinationType))
+      {
+         log.debug("Got destination type Queue for " + config.getEjbName());
+         
+         // create a queue connection
+         Object qFactory = context.lookup(adapter.getQueueFactoryRef());
+         QueueConnection qConnection = null;
+         try
+         {
+            qConnection = ConnectionFactoryHelper.createQueueConnection(qFactory, user, password);
+            connection = qConnection;
+         }
+         catch (ClassCastException e)
+         {
+            throw new DeploymentException("Expected a QueueConnection check your provider adaptor: "
+               + adapter.getQueueFactoryRef());
+         }
+         
+         try
+         {
+            // Set the optional client id
+            String clientId = config.getClientId();
+            activationConfig = getActivationConfigProperty("clientID");
+            if (activationConfig != null)
+               clientId = activationConfig;
+            
+            log.debug("Using client id: " + clientId);
+            if (clientId != null && clientId.length() > 0)
+               connection.setClientID(clientId);
+            
+            // lookup or create the destination queue
+            Queue queue = null;
+            try
+            {
+               // First we try the specified queue
+               if (destinationJNDI != null)
+                  queue = (Queue) context.lookup(destinationJNDI);
+               else if (createJBossMQDestination == false)
+                  throw new DeploymentException("Unable to determine destination for '" + container.getBeanMetaData().getEjbName()
+                        + "' use destination-jndi-name in jboss.xml, an activation config property or a message-destination-link");
+            }
+            catch (NamingException e)
+            {
+               if (createJBossMQDestination == false)
+                  throw new DeploymentException("Could not find the queue destination-jndi-name=" + destinationJNDI, e);
+               log.warn("Could not find the queue destination-jndi-name=" + destinationJNDI);
+            }
+            catch (ClassCastException e)
+            {
+               throw new DeploymentException("Expected a Queue destination-jndi-name=" + destinationJNDI);
+            }
+
+            // FIXME: This is not portable, only works for JBossMQ
+            if (queue == null)
+               queue = (Queue) createDestination(Queue.class,
+                  context,
+                  "queue/" + jndiSuffix,
+                  jndiSuffix);
+            
+            // set up the server session pool
+            pool = createSessionPool(
+               queue,
+               qConnection,
+               minPoolSize,
+               maxPoolSize,
+               keepAlive,
+               true, // tx
+               acknowledgeMode,
+               new MessageListenerImpl(this));
+            log.debug("Server session pool: " + pool);
+            
+            // create the connection consumer
+            connectionConsumer =
+               qConnection.createConnectionConsumer(queue,
+                  messageSelector,
+                  pool,
+                  maxMessagesNr);
+            log.debug("Connection consumer: " + connectionConsumer);
+         }
+         catch (Throwable t)
+         {
+            try
+            {
+               qConnection.close();
+            }
+            catch (Throwable ignored)
+            {
+            }
+            DeploymentException.rethrowAsDeploymentException("Error during queue setup", t);
+         }
+      }
+      else
+         throw new DeploymentException("Unknown destination-type " + destinationType);
+
+      log.debug("Initialized with config " + toString());
+
+      context.close();
+      
+      if (dlqHandler != null)
+      {
+         dlqHandler.start();
+      }
+
+      if (connection != null)
+      {
+         connection.setExceptionListener(exListener);
+         connection.start();
+      }
+
+      sendNotification(CONNECTED_NOTIFICATION, null);
+   }
+
+   protected void startService() throws Exception
+   {
+      try
+      {
+         innerStartDelivery();
+      }
+      catch (final Throwable t)
+      {
+         // start a thread up to handle recovering the connection. so we can
+         // attach to the jms resources once they become available
+         exListener.handleFailure(t);
+         return;
+      }
+      finally
+      {
+         // Clear any security context established by the jms connection
+         SecurityActions.clear();
+      }
+   }
+
+   protected void stopService() throws Exception
+   {
+      // Silence the exception listener
+      if (exListener != null)
+      {
+         exListener.stop();
+      }
+
+      innerStopDelivery();
+   }
+
+   /**
+    * Stop done from inside, we should not stop the exceptionListener in inner
+    * stop.
+    */
+   protected void innerStopDelivery()
+   {
+      log.debug("innerStop");
+
+      sendNotification(DISCONNECTING_NOTIFICATION, null);
+      
+      try
+      {
+         if (connection != null)
+         {
+            connection.setExceptionListener(null);
+            log.debug("unset exception listener");
+         }
+      }
+      catch (Throwable t)
+      {
+         log.trace("Could not set ExceptionListener to null", t);
+      }
+      
+      // Stop the connection
+      try
+      {
+         if (connection != null)
+         {
+            connection.stop();
+            log.debug("connection stopped");
+         }
+      }
+      catch (Throwable t)
+      {
+         log.trace("Could not stop JMS connection", t);
+      }
+
+      try
+      {
+         if (dlqHandler != null)
+            dlqHandler.stop();
+      }
+      catch (Throwable t)
+      {
+         log.trace("Failed to stop the dlq handler", t);
+      }
+
+      // close the connection consumer
+      try
+      {
+         if (connectionConsumer != null)
+            connectionConsumer.close();
+      }
+      catch (Throwable t)
+      {
+         log.trace("Failed to close connection consumer", t);
+      }
+      connectionConsumer = null;
+      
+      // clear the server session pool (if it is clearable)
+      try
+      {
+         if (pool instanceof StdServerSessionPool)
+         {
+            StdServerSessionPool p = (StdServerSessionPool) pool;
+            p.clear();
+         }
+      }
+      catch (Throwable t)
+      {
+         log.trace("Failed to clear session pool", t);
+      }
+      
+      // close the connection
+      if (connection != null)
+      {
+         try
+         {
+            connection.close();
+         }
+         catch (Throwable t)
+         {
+            log.trace("Failed to close connection", t);
+         }
+      }
+      connection = null;
+
+      // Take down DLQ
+      try
+      {
+         if (dlqHandler != null)
+         {
+            dlqHandler.destroy();
+         }
+      }
+      catch (Throwable t)
+      {
+         log.trace("Failed to close the dlq handler", t);
+      }
+      dlqHandler = null;
+      
+      sendNotification(DISCONNECTED_NOTIFICATION, null);
+   }
+   
+   public Object invoke(Object id,
+      Method m,
+      Object[] args,
+      Transaction tx,
+      Principal identity,
+      Object credential)
+      throws Exception
+   {
+
+      Invocation invocation = new Invocation(id, m, args, tx, identity, credential);
+      invocation.setType(InvocationType.LOCAL);
+
+      // Set the right context classloader
+      ClassLoader oldCL = TCLAction.UTIL.getContextClassLoader();
+      TCLAction.UTIL.setContextClassLoader(container.getClassLoader());
+      container.pushENC();
+      try
+      {
+         return container.invoke(invocation);
+      }
+      finally
+      {
+         container.popENC();
+         TCLAction.UTIL.setContextClassLoader(oldCL);
+      }
+   }
+
+   /**
+    * Try to get a destination type by looking up the destination JNDI, or
+    * provide a default if there is not destinationJNDI or if it is not possible
+    * to lookup.
+    * 
+    * @param ctx The naming context to lookup destinations from.
+    * @param destinationJNDI The name to use when looking up destinations.
+    * @return The destination type, either derived from destinationJDNI or
+    *         DEFAULT_DESTINATION_TYPE
+    */
+   protected String getDestinationType(Context ctx, String destinationJNDI)
+   {
+      String destType = null;
+
+      if (destinationJNDI != null)
+      {
+         try
+         {
+            Destination dest = (Destination) ctx.lookup(destinationJNDI);
+            if (dest instanceof javax.jms.Topic)
+            {
+               destType = "javax.jms.Topic";
+            }
+            else if (dest instanceof javax.jms.Queue)
+            {
+               destType = "javax.jms.Queue";
+            }
+         }
+         catch (NamingException ex)
+         {
+            log.debug("Could not do heristic lookup of destination ", ex);
+         }
+
+      }
+      if (destType == null)
+      {
+         log.warn("Could not determine destination type, defaults to: " +
+            DEFAULT_DESTINATION_TYPE);
+
+         destType = DEFAULT_DESTINATION_TYPE;
+      }
+
+      return destType;
+   }
+
+   /**
+    * Return the JMSProviderAdapter that should be used.
+    * 
+    * @return The JMSProviderAdapter to use.
+    */
+   protected JMSProviderAdapter getJMSProviderAdapter() throws NamingException
+   {
+      Context context = new InitialContext();
+      try
+      {
+         log.debug("Looking up provider adapter: " + providerAdapterJNDI);
+         return (JMSProviderAdapter) context.lookup(providerAdapterJNDI);
+      }
+      finally
+      {
+         context.close();
+      }
+   }
+
+   /**
+    * Create and or lookup a JMS destination.
+    * 
+    * @param type Either javax.jms.Queue or javax.jms.Topic.
+    * @param ctx The naming context to lookup destinations from.
+    * @param jndiName The name to use when looking up destinations.
+    * @param jndiSuffix The name to use when creating destinations.
+    * @return The destination.
+    * @throws IllegalArgumentException Type is not Queue or Topic.
+    * @throws Exception Description of Exception
+    */
+   protected Destination createDestination(final Class type,
+      final Context ctx,
+      final String jndiName,
+      final String jndiSuffix)
+      throws Exception
+   {
+      try
+      {
+         // first try to look it up
+         return (Destination) ctx.lookup(jndiName);
+      }
+      catch (NamingException e)
+      {
+         // if the lookup failes, the try to create it
+         log.warn("destination not found: " + jndiName + " reason: " + e);
+         log.warn("creating a new temporary destination: " + jndiName);
+
+         //
+         // jason: we should do away with this...
+         //
+         // attempt to create the destination (note, this is very
+         // very, very unportable).
+         //
+         
+         MBeanServer server = org.jboss.mx.util.MBeanServerLocator.locateJBoss();
+
+         String methodName;
+         if (type == Topic.class)
+         {
+            methodName = "createTopic";
+         }
+         else if (type == Queue.class)
+         {
+            methodName = "createQueue";
+         }
+         else
+         {
+            // type was not a Topic or Queue, bad user
+            throw new IllegalArgumentException
+               ("Expected javax.jms.Queue or javax.jms.Topic: " + type);
+         }
+
+         // invoke the server to create the destination
+         server.invoke(new ObjectName("jboss.mq:service=DestinationManager"),
+            methodName,
+            new Object[]{jndiSuffix},
+            new String[]{"java.lang.String"});
+         
+         // try to look it up again
+         return (Destination) ctx.lookup(jndiName);
+      }
+   }
+
+   protected String getActivationConfigProperty(String property)
+   {
+      MessageDrivenMetaData mdmd = getMetaData();
+      ActivationConfigPropertyMetaData acpmd = mdmd.getActivationConfigProperty(property);
+      if (acpmd != null)
+         return acpmd.getValue();
+      else
+         return null;
+   }
+   
+   /**
+    * Create a server session pool for the given connection.
+    * 
+    * @param destination the destination
+    * @param connection The connection to use.
+    * @param minSession The minumum number of sessions
+    * @param maxSession The maximum number of sessions.
+    * @param keepAlive The time to keep sessions alive
+    * @param isTransacted True if the sessions are transacted.
+    * @param ack The session acknowledgement mode.
+    * @param listener The message listener.
+    * @return A server session pool.
+    * @throws JMSException
+    * @throws NamingException Description of Exception
+    */
+   protected ServerSessionPool createSessionPool(
+      final Destination destination,
+      final Connection connection,
+      final int minSession,
+      final int maxSession,
+      final long keepAlive,
+      final boolean isTransacted,
+      final int ack,
+      final MessageListener listener)
+      throws NamingException, JMSException
+   {
+      ServerSessionPool pool;
+      Context context = new InitialContext();
+
+      try
+      {
+         // first lookup the factory
+         log.debug("looking up session pool factory: " +
+            serverSessionPoolFactoryJNDI);
+         ServerSessionPoolFactory factory = (ServerSessionPoolFactory)
+            context.lookup(serverSessionPoolFactoryJNDI);
+         
+         // the create the pool
+         pool = factory.getServerSessionPool(destination, connection, minSession, maxSession, keepAlive, isTransacted, ack, !isContainerManagedTx || isNotSupportedTx, listener);
+      }
+      finally
+      {
+         context.close();
+      }
+
+      return pool;
+   }
+
+   /**
+    * Notify of an event
+    * 
+    * @param event the event
+    * @param userData any user data, e.g. the exception on a failure
+    */
+   protected void sendNotification(String event, Object userData)
+   {
+      Notification notif = new Notification(event, getServiceName(), getNextNotificationSequenceNumber());
+      notif.setUserData(userData);
+      sendNotification(notif);
+   }
+   
+   /**
+    * Parse the JNDI suffix from the given JNDI name.
+    * 
+    * @param jndiname The JNDI name used to lookup the destination.
+    * @param defautSuffix Description of Parameter
+    * @return The parsed suffix or the defaultSuffix
+    */
+   protected String parseJndiSuffix(final String jndiname,
+      final String defautSuffix)
+   {
+      // jndiSuffix is merely the name that the user has given the MDB.
+      // since the jndi name contains the message type I have to split
+      // at the "/" if there is no slash then I use the entire jndi name...
+      String jndiSuffix = "";
+
+      if (jndiname != null)
+      {
+         int indexOfSlash = jndiname.indexOf("/");
+         if (indexOfSlash != -1)
+         {
+            jndiSuffix = jndiname.substring(indexOfSlash + 1);
+         }
+         else
+         {
+            jndiSuffix = jndiname;
+         }
+      }
+      else
+      {
+         // if the jndi name from jboss.xml is null then lets use the ejbName
+         jndiSuffix = defautSuffix;
+      }
+
+      return jndiSuffix;
+   }
+
+   /**
+    * An implementation of MessageListener that passes messages on to the
+    * container invoker.
+    */
+   class MessageListenerImpl implements MessageListener
+   {
+      /** The container invoker. */
+      JMSContainerInvoker invoker;
+      
+      /**
+       * Construct a <tt>MessageListenerImpl</tt> .
+       * 
+       * @param invoker The container invoker. Must not be null.
+       */
+      MessageListenerImpl(final JMSContainerInvoker invoker)
+      {
+         this.invoker = invoker;
+      }
+
+      /**
+       * Process a message.
+       * 
+       * @param message The message to process.
+       */
+      public void onMessage(final Message message)
+      {
+         if (log.isTraceEnabled())
+         {
+            log.trace("processing message: " + message);
+         }
+
+         Object id;
+         try
+         {
+            id = message.getJMSMessageID();
+         }
+         catch (JMSException e)
+         {
+            // what ?
+            id = "JMSContainerInvoker";
+         }
+
+         // Invoke, shuld we catch any Exceptions??
+         try
+         {
+            Transaction tx = tm.getTransaction();
+
+            // DLQHandling
+            if (useDLQ && // Is Dead Letter Queue used at all
+               message.getJMSRedelivered() && // Was message resent
+               dlqHandler.handleRedeliveredMessage(message, tx)) //Did the DLQ handler take care of the message
+            {
+               // Message will be placed on Dead Letter Queue,
+               // if redelivered to many times
+               return;
+            }
+
+            invoker.invoke(id, // Object id - where used?
+               ON_MESSAGE, // Method to invoke
+               new Object[]{message}, // argument
+               tx, // Transaction
+               null, // Principal                           
+               null);                 // Cred
+
+         }
+         catch (Exception e)
+         {
+            log.error("Exception in JMSCI message listener", e);
+         }
+      }
+   }
+
+   /** ExceptionListener for failover handling. */
+   class ExceptionListenerImpl implements ExceptionListener
+   {
+      Object lock = new Object();
+      JMSContainerInvoker invoker;
+      Thread currentThread;
+      boolean notStopped = true;
+
+      /**
+       * Create a new ExceptionListenerImpl.
+       * 
+       * @param invoker the container invoker
+       */
+      ExceptionListenerImpl(final JMSContainerInvoker invoker)
+      {
+         this.invoker = invoker;
+      }
+
+      /**
+       * Called on jms connection failure events
+       * 
+       * @param ex the jms connection failure exception
+       */
+      public void onException(JMSException ex)
+      {
+         handleFailure(ex);
+      }
+
+      /**
+       * Handle a failure
+       * 
+       * @param t the failure
+       */
+      public void handleFailure(Throwable t)
+      {
+         MessageDrivenMetaData metaData = invoker.getMetaData();
+         log.warn("JMS provider failure detected for " + metaData.getEjbName(), t);
+         
+         // JBAS-3750 - Help debug integration with foreign JMS providers
+         if (t instanceof JMSException)
+         {
+            Exception le = ((JMSException)t).getLinkedException();
+            if (le != null)
+               log.debug("Linked exception: " + le + ", cause: " + le.getCause());
+         }
+         
+         // Run the reconnection in the background
+         String name = "JMSContainerInvoker("+metaData.getEjbName()+") Reconnect";
+         synchronized (lock)
+         {
+            if (currentThread != null)
+            {
+               log.debug("Already a reconnect thread: " + currentThread + " for " + metaData.getEjbName());
+               return;
+            }
+            Runnable runnable = new ExceptionListenerRunnable(t);
+            currentThread = new Thread(runnable, name);
+            try
+            {
+               currentThread.setDaemon(true);
+               currentThread.start();
+            }
+            catch (RuntimeException rethrow)
+            {
+               currentThread = null;
+               throw rethrow;
+            }
+            catch (Error rethrow)
+            {
+               currentThread = null;
+               throw rethrow;
+            }
+         }
+      }
+
+      class ExceptionListenerRunnable implements Runnable
+      {
+         Throwable failure;
+
+         /**
+          * Create a new ExceptionListenerRunnable.
+          * 
+          * @param failure the error
+          */
+         public ExceptionListenerRunnable(Throwable failure)
+         {
+            this.failure = failure;
+         }
+         
+         /**
+          * Try to reconnect to the jms provider until explicitly stopped.
+          */ 
+         public void run()
+         {
+            MessageDrivenMetaData metaData = invoker.getMetaData();
+            try
+            {
+               boolean tryIt = true;
+               while (tryIt && notStopped)
+               {
+                  try
+                  {
+                     invoker.innerStopDelivery();
+                  }
+                  catch (Throwable t)
+                  {
+                     log.error("Unhandled error stopping connection for " + metaData.getEjbName(), t);
+                  }
+
+                  sendNotification(FAILURE_NOTIFICATION, failure);
+                  
+                  try
+                  {
+                     log.info("Waiting for reconnect internal " + reconnectInterval + "ms for " + metaData.getEjbName());
+                     try
+                     {
+                        Thread.sleep(reconnectInterval);
+                     }
+                     catch (InterruptedException ie)
+                     {
+                        tryIt = false;
+                        return;
+                     }
+                     
+                     // Reboot container
+                     log.info("Trying to reconnect to JMS provider for " + metaData.getEjbName());
+                     invoker.innerStartDelivery();
+                     tryIt = false;
+
+                     log.info("Reconnected to JMS provider for " + metaData.getEjbName());
+                  }
+                  catch (Throwable t)
+                  {
+                     log.error("Reconnect failed: JMS provider failure detected for " + metaData.getEjbName(), t);
+                  }
+               }
+            }
+            finally
+            {
+               synchronized (lock)
+               {
+                  currentThread = null;
+               }
+            }
+         }
+      }
+
+      void stop()
+      {
+         synchronized (lock)
+         {
+            log.debug("Stop requested for recovery thread: " + currentThread);
+            notStopped = false;
+            if (currentThread != null)
+            {
+               currentThread.interrupt();
+               log.debug("Recovery thread interrupted: " + currentThread);
+            }
+         }
+      }
+   }
+
+   /**
+    * Return a string representation of the current config state.
+    */
+   public String toString()
+   {
+      MessageDrivenMetaData metaData = getMetaData();
+      String destinationJNDI = metaData.getDestinationJndiName();
+      return super.toString() +
+         "{ maxMessagesNr=" + maxMessagesNr +
+         ", maxPoolSize=" + maxPoolSize +
+         ", reconnectInterval=" + reconnectInterval +
+         ", providerAdapterJNDI=" + providerAdapterJNDI +
+         ", serverSessionPoolFactoryJNDI=" + serverSessionPoolFactoryJNDI +
+         ", acknowledgeMode=" + acknowledgeMode +
+         ", isContainerManagedTx=" + isContainerManagedTx +
+         ", isNotSupportedTx=" + isNotSupportedTx +
+         ", useDLQ=" + useDLQ +
+         ", dlqHandler=" + dlqHandler +
+         ", destinationJNDI=" + destinationJNDI + 
+         " }";
+   }
+
+   interface TCLAction
+   {
+      class UTIL
+      {
+         static TCLAction getTCLAction()
+         {
+            return System.getSecurityManager() == null ? NON_PRIVILEGED : PRIVILEGED;
+         }
+
+         static ClassLoader getContextClassLoader()
+         {
+            return getTCLAction().getContextClassLoader();
+         }
+
+         static ClassLoader getContextClassLoader(Thread thread)
+         {
+            return getTCLAction().getContextClassLoader(thread);
+         }
+
+         static void setContextClassLoader(ClassLoader cl)
+         {
+            getTCLAction().setContextClassLoader(cl);
+         }
+
+         static void setContextClassLoader(Thread thread, ClassLoader cl)
+         {
+            getTCLAction().setContextClassLoader(thread, cl);
+         }
+      }
+
+      TCLAction NON_PRIVILEGED = new TCLAction()
+      {
+         public ClassLoader getContextClassLoader()
+         {
+            return Thread.currentThread().getContextClassLoader();
+         }
+
+         public ClassLoader getContextClassLoader(Thread thread)
+         {
+            return thread.getContextClassLoader();
+         }
+
+         public void setContextClassLoader(ClassLoader cl)
+         {
+            Thread.currentThread().setContextClassLoader(cl);
+         }
+
+         public void setContextClassLoader(Thread thread, ClassLoader cl)
+         {
+            thread.setContextClassLoader(cl);
+         }
+      };
+
+      TCLAction PRIVILEGED = new TCLAction()
+      {
+         private final PrivilegedAction getTCLPrivilegedAction = new PrivilegedAction()
+         {
+            public Object run()
+            {
+               return Thread.currentThread().getContextClassLoader();
+            }
+         };
+
+         public ClassLoader getContextClassLoader()
+         {
+            return (ClassLoader) AccessController.doPrivileged(getTCLPrivilegedAction);
+         }
+
+         public ClassLoader getContextClassLoader(final Thread thread)
+         {
+            return (ClassLoader) AccessController.doPrivileged(new PrivilegedAction()
+            {
+               public Object run()
+               {
+                  return thread.getContextClassLoader();
+               }
+            });
+         }
+
+         public void setContextClassLoader(final ClassLoader cl)
+         {
+            AccessController.doPrivileged(new PrivilegedAction()
+            {
+               public Object run()
+               {
+                  Thread.currentThread().setContextClassLoader(cl);
+                  return null;
+               }
+            });
+         }
+
+         public void setContextClassLoader(final Thread thread, final ClassLoader cl)
+         {
+            AccessController.doPrivileged(new PrivilegedAction()
+            {
+               public Object run()
+               {
+                  thread.setContextClassLoader(cl);
+                  return null;
+               }
+            });
+         }
+      };
+
+      ClassLoader getContextClassLoader();
+
+      ClassLoader getContextClassLoader(Thread thread);
+
+      void setContextClassLoader(ClassLoader cl);
+
+      void setContextClassLoader(Thread thread, ClassLoader cl);
+   }
+}

Modified: trunk/testsuite/.classpath
===================================================================
--- trunk/testsuite/.classpath	2007-10-04 15:46:25 UTC (rev 65847)
+++ trunk/testsuite/.classpath	2007-10-04 15:59:32 UTC (rev 65848)
@@ -12,6 +12,7 @@
 	<classpathentry kind="src" path="/messaging"/>
 	<classpathentry kind="src" path="/naming"/>
 	<classpathentry kind="src" path="/connector"/>
+	<classpathentry kind="src" path="/transaction"/>
 	<classpathentry kind="lib" path="/thirdparty/apache-log4j/lib/log4j.jar"/>
 	<classpathentry kind="lib" path="/thirdparty/apache-httpclient/lib/commons-httpclient.jar"/>
 	<classpathentry kind="lib" path="/thirdparty/oswego-concurrent/lib/concurrent.jar"/>

Modified: trunk/testsuite/.project
===================================================================
--- trunk/testsuite/.project	2007-10-04 15:46:25 UTC (rev 65847)
+++ trunk/testsuite/.project	2007-10-04 15:59:32 UTC (rev 65848)
@@ -21,6 +21,7 @@
 		<project>server</project>
 		<project>system</project>
 		<project>tools</project>
+		<project>transaction</project>
 		<project>varia</project>
 	</projects>
 	<buildSpec>

Modified: trunk/testsuite/build.xml
===================================================================
--- trunk/testsuite/build.xml	2007-10-04 15:46:25 UTC (rev 65847)
+++ trunk/testsuite/build.xml	2007-10-04 15:59:32 UTC (rev 65848)
@@ -452,10 +452,8 @@
          failonerror="${javac.fail.onerror}">
          <src path="${source.java}"/>
          <src path="${build.gen-src}"/>
-         <exclude name="org/jboss/test/cts/test/StatefulSessionUnitTestCase.java"/>
-         <exclude name="org/jboss/test/securitymgr/test/StatefulSessionUnitTestCase.java"/>
-         <exclude name="org/jboss/test/messagedriven/beans/TestMessageDriven.java"/>
-         <exclude name="org/jboss/test/txpropiiop/**"/>
+         <exclude name="org/jboss/test/recover/oracle/**"/>
+         <exclude name="org/jboss/test/recover/derby/**"/>
          <exclude name="org/jboss/test/xml/JaxpXPathBaseTestCase*" if="HAVE_JDK_1.4"/>
          <exclude name="org/jboss/test/aop/**"/>
          <classpath refid="tests.compile.classpath"/>
@@ -756,6 +754,9 @@
    <patternset id="tomcat.webctx.includes">
       <include name="org/jboss/test/web/test/WebCtxLoaderTestCase.class"/>
    </patternset>
+  <patternset id="dtm.excludes">
+     <exclude name="org/jboss/test/dtm/**"/>
+  </patternset>
    <!-- ws-bpel integration tests -->
    <patternset id="jbpm-bpel.includes">
      <include name="org/jboss/test/bpel/**/*TestCase.class"/>
@@ -817,6 +818,7 @@
       <patternset refid="deployment-service.excludes"/>
       <patternset refid="compatibility.excludes"/>
       <patternset refid="binding-manager.excludes"/>
+      <patternset refid="dtm.excludes"/>
       <patternset refid="jbossmq.excludes"/>
    </patternset>
 

Modified: trunk/testsuite/imports/sections/cts.xml
===================================================================
--- trunk/testsuite/imports/sections/cts.xml	2007-10-04 15:46:25 UTC (rev 65847)
+++ trunk/testsuite/imports/sections/cts.xml	2007-10-04 15:59:32 UTC (rev 65848)
@@ -90,7 +90,6 @@
          <src path="${source.java}"/>
          <classpath refid="tests.classpath"/>
          <include name="org/jboss/test/cts/**"/>
-         <exclude name="org/jboss/test/cts/test/StatefulSessionUnitTestCase.java"/>
       </javac>
       <jar destfile="${build.lib}/cts-v1cmp.sar">
          <fileset dir="${build.classes}">
@@ -160,7 +159,6 @@
          <src path="${source.java}"/>
          <classpath refid="tests.classpath"/>
          <include name="org/jboss/test/cts/**"/>
-         <exclude name="org/jboss/test/cts/test/StatefulSessionUnitTestCase.java"/>
       </javac>
       <jar destfile="${build.lib}/cts-v2cmp.sar">
          <fileset dir="${build.classes}">

Modified: trunk/testsuite/imports/sections/tx.xml
===================================================================
--- trunk/testsuite/imports/sections/tx.xml	2007-10-04 15:46:25 UTC (rev 65847)
+++ trunk/testsuite/imports/sections/tx.xml	2007-10-04 15:59:32 UTC (rev 65848)
@@ -27,46 +27,6 @@
       </jar>
    </target>
 
-   <!-- tx propogation test -->
-   <target name="_jars-txpropiiop">
-      <mkdir dir="${build.lib}"/>
-
-      <rmic base="${build.classes}"
-         verify="true"
-         iiop="true"
-         debug="true"
-         >
-         <classpath refid="tests.compile.classpath"/>
-         <include name="org/jboss/test/txpropiiop/interfaces/a/SessionAHome.class"/>
-         <include name="org/jboss/test/txpropiiop/interfaces/a/SessionA.class"/>
-         <include name="org/jboss/test/txpropiiop/interfaces/b/SessionBHome.class"/>
-         <include name="org/jboss/test/txpropiiop/interfaces/b/SessionB.class"/>
-      </rmic>
-
-      <jar destfile="${build.lib}/txpropiiopA.jar">
-         <fileset dir="${build.classes}">
-            <include name="org/jboss/test/txpropiiop/ejb/a/**"/>
-            <include name="org/jboss/test/txpropiiop/interfaces/**"/>
-            <include name="org/jboss/test/util/Debug.class"/>
-         </fileset>
-         <fileset dir="${build.resources}/txpropiiop/a">
-            <include name="META-INF/*.xml"/>
-         </fileset>
-      </jar>
-
-      <jar destfile="${build.lib}/txpropiiopB.jar">
-         <fileset dir="${build.classes}">
-            <include name="org/jboss/test/txpropiiop/ejb/b/**"/>
-            <include name="org/jboss/test/txpropiiop/interfaces/**"/>
-            <include name="org/jboss/test/util/Debug.class"/>
-         </fileset>
-         <fileset dir="${build.resources}/txpropiiop/b">
-            <include name="META-INF/*.xml"/>
-         </fileset>
-      </jar>
-
-   </target>
-
    <!-- EJB Tx Timer Service test -->
    <target name="_jars-txtimer">
       <!-- build ejb-txtimer.jar -->

Modified: trunk/testsuite/imports/test-jars.xml
===================================================================
--- trunk/testsuite/imports/test-jars.xml	2007-10-04 15:46:25 UTC (rev 65847)
+++ trunk/testsuite/imports/test-jars.xml	2007-10-04 15:59:32 UTC (rev 65848)
@@ -152,7 +152,6 @@
         _jars-timer,
         _jars-tm,
         _jars-txiiop,
-        _jars-txpropiiop,
         _jars-txtimer,
         _jars-util,
         _jars-web,

Copied: trunk/transaction/.classpath (from rev 65813, trunk/transaction/.classpath)
===================================================================
--- trunk/transaction/.classpath	                        (rev 0)
+++ trunk/transaction/.classpath	2007-10-04 15:59:32 UTC (rev 65848)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry excluding="org/jboss/tm/recovery/test/**" kind="src" path="src/main"/>
+	<classpathentry kind="src" path="/j2se"/>
+	<classpathentry kind="lib" path="/thirdparty/jboss/remoting/lib/jboss-remoting.jar"/>
+	<classpathentry kind="lib" path="/thirdparty/jboss/common-core/lib/jboss-common-core.jar"/>
+	<classpathentry kind="lib" path="/thirdparty/jboss/common-logging-spi/lib/jboss-logging-spi.jar"/>
+	<classpathentry kind="lib" path="/thirdparty/jboss/common-logging-log4j/lib/jboss-logging-log4j.jar"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/system-jmx"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/system"/>
+	<classpathentry kind="lib" path="/thirdparty/oswego-concurrent/lib/concurrent.jar"/>
+	<classpathentry kind="lib" path="/thirdparty/jboss/jboss-javaee/lib/jboss-javaee.jar" sourcepath="/thirdparty/jboss/jboss-javaee/lib/jboss-javaee-sources.jar"/>
+	<classpathentry kind="lib" path="/thirdparty/jboss/integration/lib/jboss-integration.jar" sourcepath="/thirdparty/jboss/integration/lib/integration-sources.jar"/>
+	<classpathentry combineaccessrules="false" kind="src" path="/main"/>
+	<classpathentry kind="output" path="output/eclipse-classes"/>
+</classpath>

Copied: trunk/transaction/.project (from rev 65813, trunk/transaction/.project)
===================================================================
--- trunk/transaction/.project	                        (rev 0)
+++ trunk/transaction/.project	2007-10-04 15:59:32 UTC (rev 65848)
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>transaction</name>
+	<comment></comment>
+	<projects>
+		<project>common</project>
+		<project>j2ee</project>
+		<project>jmx</project>
+		<project>system</project>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>




More information about the jboss-cvs-commits mailing list