[Jboss-cvs] JBossAS SVN: r55343 - in branches/JBoss_4_0_3_SP1_CP: common/src/main/org/jboss/util/threadpool common/src/main/org/jboss/util/timeout messaging/src/main/org/jboss/mq messaging/src/main/org/jboss/mq/il/http messaging/src/main/org/jboss/mq/il/jvm messaging/src/main/org/jboss/mq/il/uil2 messaging/src/main/org/jboss/mq/il/uil2/msgs messaging/src/main/org/jboss/mq/pm messaging/src/main/org/jboss/mq/pm/jdbc2 messaging/src/main/org/jboss/mq/server messaging/src/main/org/jboss/mq/server/jmx server/src/main/org/jboss/jms server/src/main/org/jboss/jms/recovery testsuite/imports testsuite/src/main/org/jboss/test/jbossmq/test testsuite/src/resources/jbossmq varia/src/main/org/jboss/mq/il/http/servlet

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Sat Aug 5 11:50:28 EDT 2006


Author: ryan.campbell at jboss.com
Date: 2006-08-05 11:50:23 -0400 (Sat, 05 Aug 2006)
New Revision: 55343

Added:
   branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/timeout/HashedTimeoutPriorityQueueImpl.java
   branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/timeout/TimeoutExt.java
   branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/timeout/TimeoutPriorityQueue.java
   branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/timeout/TimeoutPriorityQueueImpl.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/Recoverable.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/RecoverMsg.java
   branches/JBoss_4_0_3_SP1_CP/server/src/main/org/jboss/jms/recovery/
   branches/JBoss_4_0_3_SP1_CP/server/src/main/org/jboss/jms/recovery/XAResourceWrapper.java
   branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/jbossmq/test/RecoveryDurableTopicReceiveUnitTestCase.java
   branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/jbossmq/test/RecoveryDurableTopicSendUnitTestCase.java
   branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/jbossmq/test/RecoveryQueueReceiveUnitTestCase.java
   branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/jbossmq/test/RecoveryQueueSendUnitTestCase.java
   branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/jbossmq/test/RecoveryTest.java
   branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/jbossmq/jbossmq-recovery-service.xml
Removed:
   branches/JBoss_4_0_3_SP1_CP/server/src/main/org/jboss/jms/recovery/XAResourceWrapper.java
Modified:
   branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/BasicTaskWrapper.java
   branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/BasicThreadPool.java
   branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/BasicThreadPoolMBean.java
   branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/BlockingMode.java
   branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/MinPooledExecutor.java
   branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/RunnableTaskWrapper.java
   branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/StartTimeoutException.java
   branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/Task.java
   branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/TaskStoppedException.java
   branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/TaskWrapper.java
   branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/ThreadPool.java
   branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/ThreadPoolFullException.java
   branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/ThreadPoolMBean.java
   branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/ThreadPoolStoppedException.java
   branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/timeout/Timeout.java
   branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/timeout/TimeoutFactory.java
   branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/timeout/TimeoutTarget.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/AcknowledgementRequest.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/Connection.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/JBossMQXid.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyConnection.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyJMSException.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyMessage.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyXAConnection.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyXAException.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyXAResource.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyXAResourceManager.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/http/HTTPServerIL.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/jvm/JVMServerIL.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/ServerSocketManagerHandler.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/SocketManager.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/SocketManagerHandler.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/UILClientIL.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/UILClientILService.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/UILServerIL.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/UILServerILFactory.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/UILServerILService.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/UILServerILServiceMBean.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/AcknowledgementRequestMsg.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/AddMsg.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/BaseMsg.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/BrowseMsg.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/CheckIDMsg.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/CheckUserMsg.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/CloseMsg.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/ConnectionTokenMsg.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/CreateDestMsg.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/DeleteSubscriptionMsg.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/DeleteTemporaryDestMsg.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/DynCircularBuffer.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/EnableConnectionMsg.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/GetIDMsg.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/MsgTypes.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/PingMsg.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/ReceiveMsg.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/ReceiveRequestMsg.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/SubscribeMsg.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/TemporaryDestMsg.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/TransactMsg.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/UnsubscribeMsg.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/pm/Tx.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/pm/TxManager.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/pm/jdbc2/PersistenceManager.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/pm/jdbc2/PersistenceManagerMBean.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/BasicQueue.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/BasicQueueParameters.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/JMSDestination.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/JMSDestinationManager.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/JMSQueue.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/JMSServerInterceptorSupport.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/JMSServerInvoker.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/JMSTopic.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/TracingInterceptor.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/jmx/DestinationManager.java
   branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/jmx/DestinationManagerMBean.java
   branches/JBoss_4_0_3_SP1_CP/testsuite/imports/test-jars.xml
   branches/JBoss_4_0_3_SP1_CP/varia/src/main/org/jboss/mq/il/http/servlet/HTTPServerILServlet.java
Log:
merge JBAS-3259: Support patch for JBossMQ XARecovery

Modified: branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/BasicTaskWrapper.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/BasicTaskWrapper.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/BasicTaskWrapper.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,10 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- *
- */
+* 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.util.threadpool;
 
 import org.jboss.logging.Logger;
@@ -413,4 +427,30 @@
    // Private -------------------------------------------------------
 
    // Inner classes -------------------------------------------------
+   
+   /**
+    * Get the state as a string
+    * 
+    * @return the state string
+    */
+   protected String getStateString()
+   {
+      switch (state)
+      {
+         case TASK_NOT_ACCEPTED:
+            return "NOT_ACCEPTED";
+         case TASK_REJECTED:
+            return "REJECTED";
+         case TASK_ACCEPTED:
+            return "ACCEPTED";
+         case TASK_STARTED:
+            return "STARTED";
+         case TASK_STOPPED:
+            return "STOPPED";
+         case TASK_COMPLETED:
+            return "COMPLETED";
+         default:
+            return "???";
+      }
+   }
 }

Modified: branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/BasicThreadPool.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/BasicThreadPool.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/BasicThreadPool.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,10 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- *
- */
+* 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.util.threadpool;
 
 import java.util.Collections;
@@ -59,7 +73,7 @@
    private BoundedLinkedQueue queue;
 
    /** The thread group */
-   private ThreadGroup threadGroup = JBOSS_THREAD_GROUP;
+   private ThreadGroup threadGroup;
 
    /** The last thread number */
    private SynchronizedInt lastThreadNumber = new SynchronizedInt(0);
@@ -78,7 +92,7 @@
    // Constructors --------------------------------------------------
 
    /**
-    * Create a new thread pool
+    * Constructs a new thread pool
     */
    public BasicThreadPool()
    {
@@ -86,13 +100,25 @@
    }
 
    /**
-    * Create a new thread pool with a default queue size of 1024, min/max pool
-    * sizes of 100 and a keep alive of 60 seconds.
+    * Constructs a new thread pool with a default queue size of 1024, max pool
+    * size of 100, min pool size of 100, and a keep alive of 60 seconds.
     *
     * @param name the pool name
     */
    public BasicThreadPool(String name)
    {
+      this(name, JBOSS_THREAD_GROUP);
+   }
+
+   /**
+    * Constructs a new thread pool with a default queue size of 1024, max pool
+    * size of 100, min pool size of 100, and a keep alive of 60 seconds.
+    *
+    * @param name the pool name
+    * @param threadGroup threadGroup
+    */
+   public BasicThreadPool(String name, ThreadGroup threadGroup)
+   {
       trace = log.isTraceEnabled();
       ThreadFactory factory = new ThreadPoolThreadFactory();
 
@@ -106,6 +132,7 @@
 
       poolNumber = lastPoolNumber.increment();
       setName(name);
+      this.threadGroup = threadGroup;
    }
 
    // Public --------------------------------------------------------
@@ -178,12 +205,18 @@
    {
       run(runnable, 0, 0);
    }
+
    public void run(Runnable runnable, long startTimeout, long completeTimeout)
    {
       RunnableTaskWrapper wrapper = new RunnableTaskWrapper(runnable, startTimeout, completeTimeout);
       runTaskWrapper(wrapper);      
    }
 
+   public ThreadGroup getThreadGroup()
+   {
+      return threadGroup;
+   }
+
    // ThreadPoolMBean implementation --------------------------------
 
    public String getName()

Modified: branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/BasicThreadPoolMBean.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/BasicThreadPoolMBean.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/BasicThreadPoolMBean.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,10 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- *
- */
+* 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.util.threadpool;
 
 /**

Modified: branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/BlockingMode.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/BlockingMode.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/BlockingMode.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,8 +1,23 @@
 /*
-* JBoss, the OpenSource J2EE webOS
+* 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.
 *
-* Distributable under LGPL license.
-* See terms of license at gnu.org.
+* 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.util.threadpool;
 

Modified: branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/MinPooledExecutor.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/MinPooledExecutor.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/MinPooledExecutor.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,8 +1,23 @@
 /*
-* JBoss, the OpenSource J2EE webOS
+* 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.
 *
-* Distributable under LGPL license.
-* See terms of license at gnu.org.
+* 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.util.threadpool;
 
@@ -48,7 +63,7 @@
    /**
     * Construct a new executor
     * 
-    * @param poolSize the minimum pool size
+    * @param poolSize the maximum pool size
     */
    public MinPooledExecutor(int poolSize)
    {
@@ -59,7 +74,7 @@
     * Construct a new executor
     * 
     * @param channel the queue for any requests
-    * @param poolSize the minimum pool size
+    * @param poolSize the maximum pool size
     */
    public MinPooledExecutor(Channel channel, int poolSize)
    {

Modified: branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/RunnableTaskWrapper.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/RunnableTaskWrapper.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/RunnableTaskWrapper.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,10 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- *
- */
+* 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.util.threadpool;
 
 import org.jboss.logging.Logger;

Modified: branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/StartTimeoutException.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/StartTimeoutException.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/StartTimeoutException.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,10 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- *
- */
+* 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.util.threadpool;
 
 /**

Modified: branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/Task.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/Task.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/Task.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,10 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- *
- */
+* 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.util.threadpool;
 
 /**

Modified: branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/TaskStoppedException.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/TaskStoppedException.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/TaskStoppedException.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,10 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- *
- */
+* 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.util.threadpool;
 
 /**

Modified: branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/TaskWrapper.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/TaskWrapper.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/TaskWrapper.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,10 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- *
- */
+* 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.util.threadpool;
 
 /**

Modified: branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/ThreadPool.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/ThreadPool.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/ThreadPool.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.util.threadpool;
 
 /**

Modified: branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/ThreadPoolFullException.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/ThreadPoolFullException.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/ThreadPoolFullException.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,10 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- *
- */
+* 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.util.threadpool;
 
 /**

Modified: branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/ThreadPoolMBean.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/ThreadPoolMBean.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/ThreadPoolMBean.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,10 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- *
- */
+* 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.util.threadpool;
 
 /**

Modified: branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/ThreadPoolStoppedException.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/ThreadPoolStoppedException.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/threadpool/ThreadPoolStoppedException.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,10 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- *
- */
+* 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.util.threadpool;
 
 /**

Copied: branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/timeout/HashedTimeoutPriorityQueueImpl.java (from rev 55341, branches/JBoss_4_0_3_SP1_JBAS3259/common/src/main/org/jboss/util/timeout/HashedTimeoutPriorityQueueImpl.java)

Modified: branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/timeout/Timeout.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/timeout/Timeout.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/timeout/Timeout.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,32 +1,46 @@
 /*
-* JBoss, the OpenSource J2EE webOS
-*
-* Distributable under LGPL license.
-* See terms of license at gnu.org.
-*/
+ * 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.util.timeout;
 
-
 /**
- *  The public interface of timeouts.
+ * The public interface of timeouts.
  *   
- *  @author <a href="osh at sparre.dk">Ole Husgaard</a>
- *  @version $Revision$
+ * @author <a href="osh at sparre.dk">Ole Husgaard</a>
+ * @version $Revision$
 */
-public interface Timeout {
+public interface Timeout
+{
    /**
-    *  Cancel this timeout.
+    * Cancel this timeout.
     *
-    *  It is guaranteed that on return from this method this timer is
-    *  no longer active. This means that either it has been cancelled and
-    *  the timeout will not happen, or (in case of late cancel) the
-    *  timeout has happened and the timeout callback function has returned.
+    * It is guaranteed that on return from this method this timer is
+    * no longer active. This means that either it has been cancelled and
+    * the timeout will not happen, or (in case of late cancel) the
+    * timeout has happened and the timeout callback function has returned.
     *
-    *  On return from this method this instance should no longer be
-    *  used. The reason for this is that an implementation may reuse
-    *  cancelled timeouts, and at return the instance may already be
-    *  in use for another timeout.
+    * On return from this method this instance should no longer be
+    * used. The reason for this is that an implementation may reuse
+    * cancelled timeouts, and at return the instance may already be
+    * in use for another timeout.
     */
-   public void cancel();
-}
-
+   public boolean cancel();
+}
\ No newline at end of file

Copied: branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/timeout/TimeoutExt.java (from rev 55341, branches/JBoss_4_0_3_SP1_JBAS3259/common/src/main/org/jboss/util/timeout/TimeoutExt.java)

Modified: branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/timeout/TimeoutFactory.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/timeout/TimeoutFactory.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/timeout/TimeoutFactory.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,530 +1,222 @@
 /*
- * JBoss, the OpenSource J2EE webOS
+ * 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.
  *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
+ * 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.util.timeout;
 
+import org.jboss.util.NestedRuntimeException;
 import org.jboss.util.ThrowableHandler;
 import org.jboss.util.threadpool.BasicThreadPool;
-import org.jboss.util.threadpool.ThreadPool;
 import org.jboss.util.threadpool.BlockingMode;
-import org.jboss.logging.Logger;
+import org.jboss.util.threadpool.ThreadPool;
 
+import EDU.oswego.cs.dl.util.concurrent.SynchronizedBoolean;
+
 /**
- *  The timeout factory.
+ * The timeout factory.
  *
- *  This is written with performance in mind. In case of <code>n</code>
- *  active timeouts, creating, cancelling and firing timeouts all operate
- *  in time <code>O(log(n))</code>.
- *
- *  If a timeout is cancelled, the timeout is not discarded. Instead the
- *  timeout is saved to be reused for another timeout. This means that if
- *  no timeouts are fired, this class will eventually operate without
- *  allocating anything on the heap.
- *
- *  @author <a href="osh at sparre.dk">Ole Husgaard</a>
- *  @version $Revision$
+ * @author <a href="osh at sparre.dk">Ole Husgaard</a>
+ * @author <a href="dimitris at jboss.org">Dimitris Andreadis</a>
+ * @author <a href="genman at maison-otaku.net">Elias Ross</a>  
+ * @author <a href="adrian at jboss.com">Adrian Brock</a>
+ * @version $Revision$
  */
 public class TimeoutFactory
 {
+   /** The priority queue property */
+   private static final String priorityQueueProperty = TimeoutPriorityQueue.class.getName();
 
-   private static Logger log = Logger.getLogger(BasicThreadPool.class);
-
-   //  Code commented out with the mark "INV:" are runtime checks
-   //  of invariants that are not needed for a production system.
-   //  For problem solving, you can remove these comments.
-   //  Multithreading notes:
-   //
-   //  While a TimeoutImpl is enqueued, its index field contains the index
-   //  of the instance in the queue; that is, for 1 <= n <= size,
-   //  q[n].index = n.
-   //  Modifications of an enqueued TimeoutImpl instance may only happen
-   //  in code synchronized on the TimeoutFactory instance that has it
-   //  enqueued.
-   //  Modifications on the priority queue may only happen while running in
-   //  code synchronized on the TimeoutFactory instance that holds the queue.
-   //  When a TimeoutImpl instance is no longer enqueued, its index field
-   //  changes to one of the negative constants declared in the TimeoutImpl
-   //  class.
-   //  When a TimeoutImpl is not in use, its index field is TimeoutImpl.DONE
-   //  and it is on the freeList.
-   //
-   //  Cancellation may race with the timeout.
-   //  To avoid problems with this, the TimeoutImpl index field is set to
-   //  TimeoutImpl.TIMEOUT when the TimeoutImpl is taken out of the queue.
-   //  Finally the index field is set to TimeoutImpl.DONE, and
-   //  the TimeoutImpl instance is discarded.
-
-   /** The threadpool used to invoke timeouts */
-   private BasicThreadPool threadPool = new BasicThreadPool("Timeouts");
+   /** The priority queue default */
+   private static final String priorityQueueName = TimeoutPriorityQueueImpl.class.getName();
+   
+   /** Our singleton instance */
+   private static TimeoutFactory singleton;
+   
+   /** Number of TimeoutFactories created */
+   private static int timeoutFactoriesCount = 0;
+   
+   /** The priority queue class */
+   private static Class priorityQueueClass;
+   
+   /** The default threadpool used to execute timeouts */
+   private static BasicThreadPool DEFAULT_TP = new BasicThreadPool("Timeouts");
+   static
    {
-      threadPool.setBlockingMode(BlockingMode.RUN);
-   }
+      DEFAULT_TP.setBlockingMode(BlockingMode.RUN);
 
-   /**
-    *  Our private Timeout implementation.
-    */
-   private class TimeoutImpl implements Timeout
-   {
-      static final int DONE = -1; // done, may be finalized or reused
-
-      static final int TIMEOUT = -2; // target being called
-
-      int index; // index in queue, or one of constants above.
-
-      long time; // time to fire
-
-      TimeoutTarget target; // target to fire at
-
-      TimeoutImpl nextFree; // next on free list
-
-      public void cancel()
+      String priorityQueueClassName = priorityQueueName;
+      ClassLoader cl = TimeoutFactory.class.getClassLoader();
+      try
       {
-         TimeoutFactory.this.dropTimeout(this);
+         priorityQueueClassName = System.getProperty(priorityQueueProperty, priorityQueueName);
+         cl = Thread.currentThread().getContextClassLoader();
       }
-   }
-
-   /**
-    *  A worker thread that fires the timeout.
-    */
-   private static class TimeoutWorker implements Runnable
-   {
-      private TimeoutImpl work;
-
-      /**
-       *  Create a new instance.
-       *
-       *  @param work The timeout that should be fired.
-       */
-      TimeoutWorker(TimeoutImpl work)
+      catch (Exception ignored)
       {
-         this.work = work;
       }
-
-      /**
-       *  Override to fire the timeout.
-       */
-      public void run()
+      
+      try
       {
-         try
-         {
-            work.target.timedOut(work);
-         }
-         catch (Throwable t)
-         {
-            ThrowableHandler.add(ThrowableHandler.Type.ERROR, t);
-         }
-         synchronized (work)
-         {
-            work.index = TimeoutImpl.DONE;
-         }
+         priorityQueueClass = cl.loadClass(priorityQueueClassName);
       }
+      catch (Exception e)
+      {
+         throw new NestedRuntimeException(e.toString(), e);
+      }
    }
 
-   /** Linked list of free TimeoutImpl instances. */
-   private TimeoutImpl freeList;
+   /** Used for graceful exiting */
+   private SynchronizedBoolean cancelled = new SynchronizedBoolean(false);
+   
+   /** The daemon thread that dequeues timeouts tasks and issues
+       them for execution to the thread pool */ 
+   private Thread workerThread;
+   
+   /** Per TimeoutFactory thread pool used to execute timeouts */
+   private ThreadPool threadPool;
+   
+   /** The priority queue */
+   private TimeoutPriorityQueue queue;
 
-   /** The size of the timeout queue. */
-   private int size;
-
-   /**
-    *  Our priority queue.
-    *
-    *  This is a balanced binary tree. If nonempty, the root is at index 1,
-    *  and all nodes are at indices 1..size. Nodes with index greater than
-    *  size are null. Index 0 is never used.
-    *  Children of the node at index <code>j</code> are at <code>j*2</code>
-    *  and <code>j*2+1</code>. The children of a node always fire the timeout
-    *  no earlier than the node.
-    *
-    *
-    *  Or, more formally:
-    *
-    *  Only indices <code>1</code>..<code>size</code> of this array are used.
-    *  All other indices contain the null reference.
-    *  This array represent a balanced binary tree.
-    *
-    *  If <code>size</code> is <code>0</code> the tree is empty, otherwise
-    *  the root of the tree is at index <code>1</code>.
-    *
-    *  Given an arbitrary node at index <code>n</code> that is not the root
-    *  node, the parent node of <code>n</code> is at index <code>n/2</code>.
-    *
-    *  Given an arbitrary node at index <code>n</code>; if
-    *  <code>2*n <= size</code> the node at <code>n</code> has its left child
-    *  at index <code>2*n</code>, otherwise the node at <code>n</code> has
-    *  no left child.
-    *
-    *  Given an arbitrary node at index <code>n</code>; if
-    *  <code>2*n+1 <= size</code> the node at <code>n</code> has its right child
-    *  at index <code>2*n+1</code>, otherwise the node at <code>n</code> has
-    *  no right child.
-    *
-    *  The priority function is called T. Given a node <code>n</code>,
-    *  <code>T(n)</code> denotes the absolute time (in milliseconds since
-    *  the epoch) that the timeout for node <code>n</code> should happen.
-    *  Smaller values of <code>T</code> means higher priority.
-    *
-    *  The tree satisfies the following invariant:
-    *  <i>
-    *  For any node <code>n</code> in the tree:
-    *  If node <code>n</code> has a left child <code>l</code>,
-    *  <code>T(n) <= T(l)</code>.
-    *  If node <code>n</code> has a right child <code>r</code>,
-    *  <code>T(n) <= T(r)</code>.
-    *  </i>
-    *
-    *
-    *  The invariant may be temporarily broken while executing synchronized
-    *  on <code>this</code> instance, but is always reestablished before
-    *  leaving the synchronized code.
-    *
-    *  The node at index <code>1</code> is always the first node to timeout,
-    *  as can be deduced from the invariant.
-    *
-    *  For the following algorithm pseudocode, the operation
-    *  <code>swap(n,m)</code> denotes the exchange of the nodes at indices
-    *  <code>n</code> and <code>m</code> in the tree.
-    *
-    *  Insertion of a new node happend as follows:
-    *  <pre>
-    *    IF size = q.length THEN
-    *      "expand q array to be larger";
-    *    ENDIF
-    *    size <- size + 1;
-    *    q[size] <- "new node";
-    *    n <- size;
-    *    WHILE n > 1 AND T(n/2) > T(n) DO
-    *      swap(n/2, n);
-    *      n <- n/2;
-    *    ENDWHILE
-    *  </pre>
-    *  Proof that this insertion algorithm respects the invariant is left to
-    *  the interested reader.
-    *
-    *  The removal algorithm is a bit more complicated. To remove the node
-    *  at index <code>n</code>:
-    *  <pre>
-    *    swap(n, size);
-    *    size <- size - 1;
-    *    IF n > 1 AND T(n/2) > T(n) THEN
-    *      WHILE n > 1 AND T(n/2) > T(n) DO
-    *        swap(n/2, n);
-    *        n <- n/2;
-    *      ENDWHILE
-    *    ELSE
-    *      WHILE 2*n <= size DO
-    *        IF 2*n+1 <= size THEN
-    *          // Both children present
-    *          IF T(2*n) <= T(2*n+1) THEN
-    *            IF T(n) <= T(2*n) THEN
-    *              EXIT;
-    *            ENDIF
-    *            swap(n, 2*n);
-    *            n <- 2*n;
-    *          ELSE
-    *            IF T(n) <= T(2*n+1) THEN
-    *              EXIT;
-    *            ENDIF
-    *            swap(n, 2*n+1);
-    *            n <- 2*n+1;
-    *          ENDIF
-    *        ELSE
-    *          // Only left child, right child not present.
-    *          IF T(n) <= T(2*n) THEN
-    *            EXIT;
-    *          ENDIF
-    *          swap(n, 2*n);
-    *          n <- 2*n;
-    *        ENDIF
-    *      ENDWHILE
-    *    ENDIF
-    *  </pre>
-    *  Proof that this removal algorithm respects the invariant is left to
-    *  the interested reader. Really, I am not going to prove it here.
-    *
-    *  If you are interested, you can find this data structure and its
-    *  associated operations in most textbooks on algorithmics.
-    *
-    *  @see checkTree
-    */
-   private TimeoutImpl[] q;
-
-   /**
-    *  Debugging helper.
-    */
-   private void assertExpr(boolean expr)
+   /** Lazy constructions of the TimeoutFactory singleton */
+   public synchronized static TimeoutFactory getSingleton()
    {
-      if (!expr)
+      if (singleton == null)
       {
-         RuntimeException ex = new RuntimeException("***** assert failed *****");
-         try
-         {
-            Thread.sleep(30000);
-         }
-         catch (Exception e)
-         {
-         }
+         singleton = new TimeoutFactory(DEFAULT_TP);
       }
+      return singleton;
    }
-
+   
    /**
-    *  Check invariants of the queue.
+    *  Schedules a new timeout using the singleton TimeoutFactory
     */
-   private void checkTree()
+   static public Timeout createTimeout(long time, TimeoutTarget target)
    {
-      assertExpr(size >= 0);
-      assertExpr(size < q.length);
-      assertExpr(q[0] == null);
-      if (size > 0)
-      {
-         assertExpr(q[1] != null);
-         assertExpr(q[1].index == 1);
-         for (int i = 2; i <= size; ++i)
-         {
-            assertExpr(q[i] != null);
-            assertExpr(q[i].index == i);
-            assertExpr(q[i >> 1].time <= q[i].time); // parent fires first
-         }
-         for (int i = size + 1; i < q.length; ++i)
-            assertExpr(q[i] == null);
-      }
+      return getSingleton().schedule(time, target);
    }
-
+   
    /**
-    *  Check invariants of the free list.
+    * Constructs a new TimeoutFactory that uses the provided ThreadPool
     */
-   private void checkFreeList()
+   public TimeoutFactory(ThreadPool threadPool)
    {
-      TimeoutImpl to = freeList;
-      while (to != null)
+      this.threadPool = threadPool;
+      try
       {
-         assertExpr(to.index == TimeoutImpl.DONE);
-         to = to.nextFree;
+         queue = (TimeoutPriorityQueue) priorityQueueClass.newInstance(); 
       }
+      catch (Exception e)
+      {
+         throw new RuntimeException("Cannot instantiate " + priorityQueueClass,e);
+      }
+      
+      // setup the workerThread
+      workerThread = new Thread("TimeoutFactory-" + timeoutFactoriesCount++)
+      {
+         public void run()
+         {
+            doWork();
+         }
+      };
+      workerThread.setDaemon(true);
+      workerThread.start();
    }
-
+   
    /**
-    *  Swap two nodes in the tree.
+    * Constructs a new TimeoutFactory that uses the default thread pool
     */
-   private void swap(int a, int b)
+   public TimeoutFactory()
    {
-      // INV: assertExpr(a > 0);
-      // INV: assertExpr(a <= size);
-      // INV: assertExpr(b > 0);
-      // INV: assertExpr(b <= size);
-      // INV: assertExpr(q[a] != null);
-      // INV: assertExpr(q[b] != null);
-      // INV: assertExpr(q[a].index == a);
-      // INV: assertExpr(q[b].index == b);
-      TimeoutImpl temp = q[a];
-      q[a] = q[b];
-      q[a].index = a;
-      q[b] = temp;
-      q[b].index = b;
+      this(DEFAULT_TP);
    }
-
+   
    /**
-    *  A new node has been added at index <code>index</code>.
-    *  Normalize the tree by moving the new node up the tree.
-    *
-    *  @return True iff the tree was modified.
+    * Schedules a new timeout.
+    * 
+    * @param time absolute time
+    * @param target target to fire
     */
-   private boolean normalizeUp(int index)
+   public Timeout schedule(long time, TimeoutTarget target)
    {
-      // INV: assertExpr(index > 0);
-      // INV: assertExpr(index <= size);
-      // INV: assertExpr(q[index] != null);
-      if (index == 1)
-         return false; // at root
-      boolean ret = false;
-      long t = q[index].time;
-      int p = index >> 1;
-      while (q[p].time > t)
-      {
-         // INV: assertExpr(q[index].time == t);
-         swap(p, index);
-         ret = true;
-         if (p == 1)
-            break; // at root
-         index = p;
-         p >>= 1;
-      }
-      return ret;
-   }
+      if (cancelled.get())
+         throw new IllegalStateException("TimeoutFactory has been cancelled");      
+      if (time < 0)
+         throw new IllegalArgumentException("Negative time");
+      if (target == null)
+         throw new IllegalArgumentException("Null timeout target");
 
+      return queue.offer(time, target);
+   }
+   
    /**
-    *  Remove a node from the tree and normalize.
-    *
-    *  @return The removed node.
+    * Schedules a new timeout.
+    * 
+    * @param time absolute time
+    * @param run runnable to run
     */
-   private TimeoutImpl removeNode(int index)
+   public Timeout schedule(long time, Runnable run)
    {
-      // INV: assertExpr(index > 0);
-      // INV: assertExpr(index <= size);
-      TimeoutImpl res = q[index];
-      // INV: assertExpr(res != null);
-      // INV: assertExpr(res.index == index);
-      if (index == size)
-      {
-         --size;
-         q[index] = null;
-         return res;
-      }
-      swap(index, size); // Exchange removed node with last leaf node
-      --size;
-      // INV: assertExpr(res.index == size + 1);
-      q[res.index] = null;
-      if (normalizeUp(index))
-         return res; // Node moved up, so it shouldn't move down
-      long t = q[index].time;
-      int c = index << 1;
-      while (c <= size)
-      {
-         // INV: assertExpr(q[index].time == t);
-         TimeoutImpl l = q[c];
-         // INV: assertExpr(l != null);
-         // INV: assertExpr(l.index == c);
-         if (c + 1 <= size)
-         {
-            // two children, swap with smallest
-            TimeoutImpl r = q[c + 1];
-            // INV: assertExpr(r != null);
-            // INV: assertExpr(r.index == c+1);
-            if (l.time <= r.time)
-            {
-               if (t <= l.time)
-                  break; // done
-               swap(index, c);
-               index = c;
-            }
-            else
-            {
-               if (t <= r.time)
-                  break; // done
-               swap(index, c + 1);
-               index = c + 1;
-            }
-         }
-         else
-         { // one child
-            if (t <= l.time)
-               break; // done
-            swap(index, c);
-            index = c;
-         }
-         c = index << 1;
-      }
-      return res;
+      return schedule(time, new TimeoutTargetImpl(run));
    }
-
+   
    /**
-    *  Create a new timeout.
+    * Cancels all submitted tasks, stops the worker
+    * thread and clean-ups everything except for the
+    * thread pool. Scheduling new timeouts after cancel
+    * is called results in a IllegalStateException.
     */
-   private synchronized Timeout newTimeout(long time, TimeoutTarget target)
+   public void cancel()
    {
-      // INV: checkTree();
-      // INV: assertExpr(size < q.length);
-      if (++size == q.length)
+      // obviously the singleton TimeoutFactory cannot
+      // be cancelled since its reference is not accessible
+      
+      // let the worker thread cleanup
+      if (cancelled.set(true) == false);
       {
-         TimeoutImpl[] newQ = new TimeoutImpl[2 * q.length];
-         System.arraycopy(q, 0, newQ, 0, q.length);
-         q = newQ;
+         // Cancel the priority queue
+         queue.cancel();
       }
-      // INV: assertExpr(size < q.length);
-      // INV: assertExpr(q[size] == null);
-      TimeoutImpl timeout;
-      if (freeList != null)
-      {
-         timeout = q[size] = freeList;
-         freeList = timeout.nextFree;
-         // INV: checkFreeList();
-         // INV: assertExpr(timeout.index == TimeoutImpl.DONE);
-      }
-      else
-         timeout = q[size] = new TimeoutImpl();
-      timeout.index = size;
-      timeout.time = time;
-      timeout.target = target;
-      normalizeUp(size);
-      if (timeout.index == 1)
-         notify();
-      // INV: checkTree();
-      return timeout;
    }
-
+   
    /**
-    *  Cancel a timeout.
+    * Returns true if the TimeoutFactory has been cancelled,
+    * false if it is operational (i.e. accepts timeout schedules).
     */
-   private void dropTimeout(TimeoutImpl timeout)
+   public boolean isCancelled()
    {
-      synchronized (this)
-      {
-         if (timeout.index > 0)
-         {
-            // Active timeout, remove it.
-            // INV: assertExpr(q[timeout.index] == timeout);
-            // INV: checkTree();
-            removeNode(timeout.index);
-            // INV: checkTree();
-            timeout.index = TimeoutImpl.DONE;
-            timeout.nextFree = freeList;
-            freeList = timeout;
-            // INV: checkFreeList();
-            return;
-         }
-      }
+      return cancelled.get();
    }
 
    /**
     *  Timeout worker method.
-    *  This method never returns. Whenever it is time to do a timeout,
-    *  the callback method is called from here.
     */
    private void doWork()
    {
-      while (true)
+      while (cancelled.get() == false)
       {
-         TimeoutImpl work = null;
-         // Look for work
-         synchronized (this)
-         {
-            if (size == 0)
-            {
-               try
-               {
-                  wait();
-               }
-               catch (InterruptedException ex)
-               {
-               }
-            }
-            else
-            {
-               long now = System.currentTimeMillis();
-               if (q[1].time > now)
-               {
-                  try
-                  {
-                     wait(q[1].time - now);
-                  }
-                  catch (InterruptedException ex)
-                  {
-                  }
-               }
-               if (size > 0 && q[1].time <= System.currentTimeMillis())
-               {
-                  work = removeNode(1);
-                  work.index = TimeoutImpl.TIMEOUT;
-               }
-            }
-         }
+         TimeoutExt work = queue.take();
          // Do work, if any
          if (work != null)
          {
-            // Create a new thread to do the callback.
+            // Wrap the TimeoutExt with a runnable that invokes the target callback
             TimeoutWorker worker = new TimeoutWorker(work);
             try
             {
@@ -532,58 +224,73 @@
             }
             catch (Throwable t)
             {
-               log.error(t, t);
+               // protect the worker thread from pool enqueue errors
+               ThrowableHandler.add(ThrowableHandler.Type.ERROR, t);
             }
+            synchronized (work)
+            {
+               work.done();
+            }            
          }
       }
+      
+      // TimeoutFactory was cancelled
+      queue.cancel();
    }
-
-   /** Our singleton instance. */
-   static private TimeoutFactory singleton;
-
-   /** Our private constructor. */
-   private TimeoutFactory()
-   {
-      freeList = null;
-      size = 0;
-      q = new TimeoutImpl[16];
-   }
-
+   
    /**
-    *  Initialize class.
-    *  The will initialize the singleton and create a single
-    *  worker thread.
+    *  A runnable that fires the timeout callback
     */
-   static
+   private static class TimeoutWorker implements Runnable
    {
-      singleton = new TimeoutFactory();
-      Thread thread = new Thread("TimeoutFactory")
+      private TimeoutExt work;
+
+      /**
+       *  Create a new instance.
+       *
+       *  @param work The timeout that should be fired.
+       */
+      TimeoutWorker(TimeoutExt work)
       {
-         public void run()
+         this.work = work;
+      }
+
+      /**
+       *  Override to fire the timeout.
+       */
+      public void run()
+      {
+         try
          {
-            try
-            {
-               singleton.doWork();
-            }
-            catch (Throwable t)
-            {
-               log.error(t, t);
-            }
+            work.getTimeoutTarget().timedOut(work);
          }
-      };
-      thread.setDaemon(true);
-      thread.start();
+         catch (Throwable t)
+         {
+            // protect the thread pool thread from receiving this error
+            ThrowableHandler.add(ThrowableHandler.Type.ERROR, t);
+         }
+         synchronized (work)
+         {
+            work.done();
+         }
+      }
    }
-
+   
    /**
-    *  Schedule a new timeout.
+    * Simple TimeoutTarget implementation that wraps a Runnable
     */
-   static public Timeout createTimeout(long time, TimeoutTarget target)
+   private static class TimeoutTargetImpl implements TimeoutTarget
    {
-      if (time <= 0)
-         throw new IllegalArgumentException("Time not positive");
-      if (target == null)
-         throw new IllegalArgumentException("Null target");
-      return singleton.newTimeout(time, target);
+      Runnable runnable;
+      
+      TimeoutTargetImpl(Runnable runnable)
+      {
+         this.runnable = runnable;
+      }
+      
+      public void timedOut(Timeout ignored)
+      {
+         runnable.run();
+      }
    }
-}
+}
\ No newline at end of file

Copied: branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/timeout/TimeoutPriorityQueue.java (from rev 55341, branches/JBoss_4_0_3_SP1_JBAS3259/common/src/main/org/jboss/util/timeout/TimeoutPriorityQueue.java)

Copied: branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/timeout/TimeoutPriorityQueueImpl.java (from rev 55341, branches/JBoss_4_0_3_SP1_JBAS3259/common/src/main/org/jboss/util/timeout/TimeoutPriorityQueueImpl.java)

Modified: branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/timeout/TimeoutTarget.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/timeout/TimeoutTarget.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/common/src/main/org/jboss/util/timeout/TimeoutTarget.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,22 +1,36 @@
 /*
-* JBoss, the OpenSource J2EE webOS
-*
-* Distributable under LGPL license.
-* See terms of license at gnu.org.
-*/
+ * 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.util.timeout;
 
-
 /**
- *  The interface of objects that can receive timeouts.
+ * The interface of objects that can receive timeouts.
  *   
- *  @author <a href="osh at sparre.dk">Ole Husgaard</a>
- *  @version $Revision$
+ * @author <a href="osh at sparre.dk">Ole Husgaard</a>
+ * @version $Revision$
 */
-public interface TimeoutTarget {
+public interface TimeoutTarget
+{
    /**
     *  The timeout callback function is invoked when the timeout expires.
     */
    public void timedOut(Timeout timeout);
 }
-

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/AcknowledgementRequest.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/AcknowledgementRequest.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/AcknowledgementRequest.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,8 +1,24 @@
 /*
- * JBossMQ, the OpenSource JMS implementation
- * 
- * Distributable under LGPL license. See terms of license at gnu.org.
- */
+* 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.mq;
 
 import java.io.Externalizable;
@@ -42,8 +58,23 @@
    
    // Constructors --------------------------------------------------
    
+   public AcknowledgementRequest()
+   {
+      this(false);
+   }
+
+   public AcknowledgementRequest(boolean ack)
+   {
+      this.isAck = ack;
+   }
+   
    // Public --------------------------------------------------------
    
+   public boolean isAck()
+   {
+      return isAck;
+   }
+   
    // Object overrides ----------------------------------------------
    
    public boolean equals(Object o)
@@ -66,7 +97,8 @@
 
    public String toString()
    {
-      return "AcknowledgementRequest:" + (isAck ? "ACK" : "NACK") + "," + destination + "," + messageID;
+      return "AcknowledgementRequest:" +
+         ((isAck) ? "ACK" : "NACK") + "," + destination + "," + messageID;
    }
 
    public void readExternal(java.io.ObjectInput in) throws java.io.IOException
@@ -94,4 +126,4 @@
    // Private -------------------------------------------------------
    
    // Inner classes -------------------------------------------------
-}
\ No newline at end of file
+}

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/Connection.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/Connection.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/Connection.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,8 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE webOS
- * 
- * Distributable under LGPL license. See terms of license at gnu.org.
- */
+* 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.mq;
 
 import java.io.IOException;
@@ -21,6 +37,7 @@
 import javax.jms.Queue;
 import javax.jms.TemporaryQueue;
 import javax.jms.TemporaryTopic;
+import javax.transaction.xa.Xid;
 
 import org.jboss.logging.Logger;
 import org.jboss.mq.il.ClientILService;
@@ -29,6 +46,7 @@
 
 import EDU.oswego.cs.dl.util.concurrent.ClockDaemon;
 import EDU.oswego.cs.dl.util.concurrent.Semaphore;
+import EDU.oswego.cs.dl.util.concurrent.SynchronizedBoolean;
 import EDU.oswego.cs.dl.util.concurrent.ThreadFactory;
 
 /**
@@ -83,8 +101,6 @@
  */
 public abstract class Connection implements Serializable, javax.jms.Connection
 {
-   // Constants -----------------------------------------------------
-
    /** The serialVersionUID */
    private static final long serialVersionUID = 87938199839407082L;
 
@@ -97,71 +113,44 @@
    /** Whether trace is enabled */
    static boolean trace = log.isTraceEnabled();
 
-   /**
-	 * Manages the thread that pings the connection to see if it is 'alive'
-	 */
+   /** Manages the thread that pings the connection to see if it is 'alive' */
    static protected ClockDaemon clockDaemon = new ClockDaemon();
 
-   // Attributes ----------------------------------------------------
-
-   /**
-	 * Maps a destination to a LinkedList of Subscriptions
-	 */
+   /** Maps a destination to a LinkedList of Subscriptions */
    public HashMap destinationSubscriptions = new HashMap();
 
-   /**
-	 * Maps a a subsction id to a Subscription
-	 */
+   /** Maps a subscription id to a Subscription */
    public HashMap subscriptions = new HashMap();
-   /**
-	 * Is the connection stopped ?
-	 */
+
+   /** Is the connection stopped ? */
    public boolean modeStop;
 
-   /**
-	 * This is our connection to the JMS server
-	 */
+   /** This is our connection to the JMS server */
    protected ServerIL serverIL;
 
-   /**
-	 * This is the clientID
-	 */
+   /** This is the clientID */
    protected String clientID;
 
-   /**
-	 * The connection token is used to identify our connection to the server.
-	 */
+   /** The connection token is used to identify our connection to the server. */
    protected ConnectionToken connectionToken;
 
-   /**
-	 * The object that sets up the client IL
-	 */
+   /** The object that sets up the client IL */
    protected ClientILService clientILService;
 
-   /**
-	 * How often to ping the connection
-	 */
+   /** How often to ping the connection */
    protected long pingPeriod = 1000 * 60;
 
-   /**
-	 * This feild is reset when a ping is sent, set when ponged.
-	 */
+   /** This field is reset when a ping is sent, set when ponged. */
    protected boolean ponged = true;
 
-   /**
-	 * This is used to know when the PingTask is running
-	 */
+   /** This is used to know when the PingTask is running */
    Semaphore pingTaskSemaphore = new Semaphore(1);
 
-   /**
-	 * Identifies the PinkTask in the ClockDaemon
-	 */
+   /** Identifies the PinkTask in the ClockDaemon */
    Object pingTaskId;
 
-   /**
-	 * Set a soon as close() is called on the connection.
-	 */
-   protected volatile boolean closing = false;
+   /** Set a soon as close() is called on the connection. */
+   private SynchronizedBoolean closing = new SynchronizedBoolean(false);
 
    /** Whether setClientId is Allowed */
    private volatile boolean setClientIdAllowed = true;
@@ -171,11 +160,13 @@
 
    /** Numbers subscriptions */
    int subscriptionCounter = Integer.MIN_VALUE;
+
    /** The lock for subscriptionCounter */
    Object subCountLock = new Object();
 
    /** Is the connection closed */
-   boolean closed;
+   private SynchronizedBoolean closed = new SynchronizedBoolean(false);
+
    /** Used to control tranactions */
    SpyXAResourceManager spyXAResourceManager;
 
@@ -205,9 +196,7 @@
 
    /** Temporary destinations created by this connection */
    protected HashSet temps = new HashSet();
-
-   // Static --------------------------------------------------------
-
+   
    static
    {
       log.debug("Setting the clockDaemon's thread factory");
@@ -228,8 +217,6 @@
          threadGroup = new ThreadGroup("JBossMQ Client Threads");
       return threadGroup;
    }
-   
-   // Constructors --------------------------------------------------
 
    /**
 	 * Create a new Connection
@@ -241,11 +228,9 @@
 	 */
    Connection(String userName, String password, GenericConnectionFactory genericConnectionFactory) throws JMSException
    {
-
       //Set the attributes
       createdSessions = new HashSet();
       connectionToken = null;
-      closed = false;
       lastMessageID = 0;
       modeStop = true;
 
@@ -338,8 +323,6 @@
       this(null, null, genericConnectionFactory);
    }
 
-   // Public --------------------------------------------------------
-
    /**
 	 * Gets the ServerIL attribute of the Connection object
 	 * 
@@ -385,7 +368,7 @@
    public void asynchDeliver(ReceiveRequest requests[])
    {
       // If we are closing the connection, the server will nack the messages
-      if (closing)
+      if (closing.get())
          return;
 
       if (trace)
@@ -395,23 +378,24 @@
       {
          for (int i = 0; i < requests.length; i++)
          {
+            ReceiveRequest r = requests[i];
             if (trace)
-               log.trace("Processing request=" + requests[i] + " " + this);
+               log.trace("Processing request=" + r + " " + this);
             
-            SpyConsumer consumer = (SpyConsumer) subscriptions.get(requests[i].subscriptionId);
-            requests[i].message.createAcknowledgementRequest(requests[i].subscriptionId.intValue());
+            SpyConsumer consumer = (SpyConsumer) subscriptions.get(r.subscriptionId);
+            r.message.createAcknowledgementRequest(r.subscriptionId.intValue());
 
             if (consumer == null)
             {
-               send(requests[i].message.getAcknowledgementRequest(false));
-               log.debug("WARNING: NACK issued due to non existent subscription " + requests[i].message.header.messageId);
+               send(r.message.getAcknowledgementRequest(false));
+               log.debug("WARNING: NACK issued due to non existent subscription " + r.message.header.messageId);
                continue;
             }
 
             if (trace)
-               log.trace("Delivering messageid=" + requests[i].message.header.messageId + " to consumer=" + consumer);
+               log.trace("Delivering messageid=" + r.message.header.messageId + " to consumer=" + consumer);
             
-            consumer.addMessage(requests[i].message);
+            consumer.addMessage(r.message);
          }
       }
       catch (Throwable t)
@@ -431,7 +415,7 @@
          log.trace("Notified of failure reason=" + reason + " " + this, t);
 
       // Exceptions due to closing will be ignored.
-      if (closing)
+      if (closing.get())
          return;
 
       JMSException excep = SpyJMSException.getAsJMSException(reason, t);
@@ -481,9 +465,7 @@
 	 */
    public void deleteTemporaryDestination(SpyDestination dest) throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
-
+      checkClosed();
       if (trace)
          log.trace("DeleteDestination dest=" + dest + " " + this);
       try
@@ -510,12 +492,9 @@
       }
    }
 
-   // Connection implementation -------------------------------------
-
    public void setClientID(String cID) throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
+      checkClosed();
       if (clientID != null)
          throw new IllegalStateException("The connection has already a clientID");
       if (setClientIdAllowed == false)
@@ -539,24 +518,20 @@
 
    public String getClientID() throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
-
+      checkClosed();
       return clientID;
    }
 
    public ExceptionListener getExceptionListener() throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
+      checkClosed();
       checkClientID();
       return exceptionListener;
    }
 
    public void setExceptionListener(ExceptionListener listener) throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
+      checkClosed();
       checkClientID();
 
       exceptionListener = listener;
@@ -564,8 +539,7 @@
 
    public ConnectionMetaData getMetaData() throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
+      checkClosed();
       checkClientID();
 
       return new SpyConnectionMetaData();
@@ -573,12 +547,12 @@
 
    public synchronized void close() throws JMSException
    {
-      if (closed)
+      if (closed.get())
          return;
       if (trace)
          log.trace("Closing connection " + this);
       
-      closing = true;
+      closing.set(true);
 
       // We don't want to notify the exception listener
       exceptionListener = null;
@@ -592,7 +566,7 @@
       }
       catch (Throwable t)
       {
-         exception = SpyJMSException.getAsJMSException("Error duing stop", t);
+         log.trace("Error during stop", t);
       }
       
       if (trace)
@@ -604,14 +578,15 @@
       }
       for (int i = 0; i < vect.length; i++)
       {
+         SpySession session = (SpySession) vect[i];
          try
          {
-            ((SpySession) vect[i]).close();
+            session.close();
          }
          catch (Throwable t)
          {
-            if (exception == null)
-               exception = SpyJMSException.getAsJMSException("Error closing sessions", t);
+            if (trace)
+               log.trace("Error closing session " + session, t);
          }
       }
       if (trace)
@@ -625,8 +600,7 @@
       }
       catch (Throwable t)
       {
-         if (exception == null)
-            exception = SpyJMSException.getAsJMSException("Cannot close properly the connection", t);
+         log.trace("Cannot close properly the connection", t);
       }
 
       if (trace)
@@ -649,13 +623,12 @@
       }
       catch (Throwable t)
       {
-         if (exception == null)
-            exception = SpyJMSException.getAsJMSException("Cannot stop the client il service", t);
+         log.trace("Cannot stop the client il service", t);
       }
 
       // Only set the closed flag after all the objects that depend
       // on this connection have been closed.
-      closed = true;
+      closed.set(true);
 
       if (trace)
          log.trace("Disconnected from server " + this);
@@ -667,8 +640,7 @@
 
    public void start() throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
+      checkClosed();
       checkClientID();
 
       if (modeStop == false)
@@ -690,14 +662,11 @@
 
    public void stop() throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
+      checkClosed();
       checkClientID();
       doStop();
    }
 
-   // Object overrides ----------------------------------------------
-
    public String toString()
    {
       StringBuffer buffer = new StringBuffer();
@@ -707,9 +676,9 @@
          buffer.append("token=").append(connectionToken);
       else
          buffer.append("clientID=").append(clientID);
-      if (closed)
+      if (closed.get())
          buffer.append(" CLOSED");
-      else if (closing)
+      else if (closing.get())
          buffer.append(" CLOSING");
       buffer.append(" rcvstate=");
       if (modeStop)
@@ -720,8 +689,6 @@
       return buffer.toString();
    }
 
-   // Package protected ---------------------------------------------
-
    /**
 	 * Get the next message id
 	 * <p>
@@ -738,9 +705,7 @@
 	 */
    String getNewMessageID() throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
-
+      checkClosed();
       synchronized (sb)
       {
          sb.setLength(0);
@@ -795,9 +760,7 @@
 	 */
    void addConsumer(SpyConsumer consumer) throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
-
+      checkClosed();
       Subscription req = consumer.getSubscription();
       synchronized (subCountLock)
       {
@@ -846,9 +809,7 @@
 	 */
    SpyMessage[] browse(Queue queue, String selector) throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
-
+      checkClosed();
       if (trace)
          log.trace("Browsing queue=" + queue + " selector=" + selector + " " + this);
 
@@ -871,9 +832,7 @@
 	 */
    void pingServer(long clientTime) throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
-
+      checkClosed();
       trace = log.isTraceEnabled();
       if (trace)
          log.trace("PING " + clientTime + " " + this);
@@ -898,9 +857,7 @@
 	 */
    SpyMessage receive(Subscription sub, long wait) throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
-
+      checkClosed();
       if (trace)
          log.trace("Receive subscription=" + sub + " wait=" + wait);
 
@@ -926,9 +883,7 @@
     */
    void removeConsumer(SpyConsumer consumer) throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
-
+      checkClosed();
       Subscription req = consumer.getSubscription();
       if (trace)
          log.trace("removeConsumer req=" + req);
@@ -954,9 +909,7 @@
     */
    void sendToServer(SpyMessage mes) throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
-
+      checkClosed();
       if (trace)
          log.trace("SendToServer message=" + mes.header.jmsMessageID + " " + this);
       
@@ -1021,8 +974,6 @@
       }
    }
 
-   // Protected -----------------------------------------------------
-
    /**
 	 * Check that a clientID exists. If not get one from server.
 	 * 
@@ -1128,9 +1079,7 @@
 	 */
    protected void send(AcknowledgementRequest item) throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
-
+      checkClosed();
       if (trace)
          log.trace("Acknowledge item=" + item + " " + this);
 
@@ -1152,9 +1101,7 @@
 	 */
    protected void send(TransactionRequest transaction) throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
-
+      checkClosed();
       if (trace)
          log.trace("Transact request=" + transaction + " " + this);
 
@@ -1166,7 +1113,35 @@
       {
          SpyJMSException.rethrowAsJMSException("Cannot process a transaction", t);
       }
+   }
 
+   /**
+    * Recover
+    * 
+    * @param flags the flags
+    * @throws JMSException for any error
+    */
+   protected Xid[] recover(int flags) throws JMSException
+   {
+      checkClosed();
+      if (trace)
+         log.trace("Recover flags=" + flags + " " + this);
+
+      try
+      {
+         if (serverIL instanceof Recoverable)
+         {
+            Recoverable recoverableIL = (Recoverable) serverIL;
+            return recoverableIL.recover(connectionToken, flags);
+         }
+      }
+      catch (Throwable t)
+      {
+         SpyJMSException.rethrowAsJMSException("Cannot recover", t);
+      }
+      
+      log.warn(serverIL + " does not implement " + Recoverable.class.getName());
+      return new Xid[0];
    }
 
    /**
@@ -1209,8 +1184,6 @@
          SpyJMSException.rethrowAsJMSException("Cannot stop a the client IL service", t);
       }
    }
-
-   // Private -------------------------------------------------------
    
    /**
     * Stop delivery
@@ -1259,6 +1232,17 @@
          }
       }
    }
+   
+   /**
+    * Check whether we are closed
+    * 
+    * @throws IllegalStateException when the session is closed
+    */
+   protected void checkClosed() throws IllegalStateException
+   {
+      if (closed.get())
+         throw new IllegalStateException("The connection is closed");
+   }
 
    /**
     * Start the ping thread
@@ -1293,8 +1277,6 @@
       }
    }
 
-   // Inner classes -------------------------------------------------
-
    /**
 	 * The ping task
 	 */
@@ -1361,7 +1343,7 @@
       {
          try
          {
-            synchronized (el)
+            synchronized (elLock)
             {
                el.onException(excep);
             }

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/JBossMQXid.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/JBossMQXid.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/JBossMQXid.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,8 +1,24 @@
 /*
- * JBossMQ, the OpenSource JMS implementation
- * 
- * Distributable under LGPL license. See terms of license at gnu.org.
- */
+* 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.mq;
 
 import java.io.Serializable;
@@ -20,13 +36,9 @@
  */
 public class JBossMQXid implements Serializable, Xid
 {
-   // Constants -----------------------------------------------------
-
    /** The serialVersionUID */
    private static final long serialVersionUID = -2227021688745286343L;
 
-   // Attributes ----------------------------------------------------
-
    /** The format id */
    private int formatId;
 
@@ -42,10 +54,6 @@
    /** Cached hashCode() */
    private transient int cachedHashCode;
 
-   // Static --------------------------------------------------------
-
-   // Constructors --------------------------------------------------
-
    /**
     * Create a new wrapper Xid
     * 
@@ -58,10 +66,6 @@
       branchQualifier = xid.getBranchQualifier();
    }
 
-   // Public --------------------------------------------------------
-
-   // Xid implementation --------------------------------------------
-
    public int getFormatId()
    {
       return formatId;
@@ -77,8 +81,6 @@
       return branchQualifier;
    }
 
-   // Object overrides ----------------------------------------------
-
    public boolean equals(Object object)
    {
       if (object == null || (object instanceof Xid) == false)
@@ -111,18 +113,15 @@
          StringBuffer buffer = new StringBuffer();
          buffer.append("JBossMQXid[FormatId=").append(getFormatId());
          buffer.append(" GlobalId=").append(new String(getGlobalTransactionId()).trim());
-         buffer.append(" BranchQual=").append(new String(getBranchQualifier()).trim());
+         byte[] branchQualifer = getBranchQualifier();
+         buffer.append(" BranchQual=");
+         if (branchQualifer == null)
+            buffer.append("null");
+         else
+            buffer.append(new String(getBranchQualifier()).trim());
          buffer.append(']');
          cachedToString = buffer.toString();
       }
       return cachedToString;
    }
-
-   // Package protected ---------------------------------------------
-
-   // Protected -----------------------------------------------------
-
-   // Private -------------------------------------------------------
-
-   // Inner classes -------------------------------------------------
 }
\ No newline at end of file

Copied: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/Recoverable.java (from rev 55341, branches/JBoss_4_0_3_SP1_JBAS3259/messaging/src/main/org/jboss/mq/Recoverable.java)

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyConnection.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyConnection.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyConnection.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,8 +1,24 @@
 /*
- * JBossMQ, the OpenSource JMS implementation
- * 
- * Distributable under LGPL license. See terms of license at gnu.org.
- */
+* 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.mq;
 
 import java.io.Serializable;
@@ -36,14 +52,20 @@
  */
 public class SpyConnection extends Connection implements Serializable, TopicConnection, QueueConnection
 {
-   // Constants -----------------------------------------------------
-
    private static final long serialVersionUID = -6227193901482445607L;
 
-   // Attributes ----------------------------------------------------
+   /** Unified */
+   public static final int UNIFIED = 0; 
 
-   // Constructor ---------------------------------------------------
+   /** Queue */
+   public static final int QUEUE = 1; 
 
+   /** Topic */
+   public static final int TOPIC = 2; 
+   
+   /** The type of connection */
+   private int type = UNIFIED;
+   
    /**
 	 * Create a new SpyConnection
 	 * 
@@ -68,26 +90,47 @@
       super(gcf);
    }
 
-   // Public --------------------------------------------------------
+   /**
+    * Create a new SpyConnection
+    * 
+    * @param type the type of connection 
+    * @param userId the user
+    * @param password the password
+    * @param gcf the constructing class
+    * @throws JMSException for any error
+    */
+   public SpyConnection(int type, String userId, String password, GenericConnectionFactory gcf) throws JMSException
+   {
+      super(userId, password, gcf);
+      this.type = type;
+   }
 
-   // Connection implementation -------------------------------------
+   /**
+    * Create a new SpyConnection
+    * @param type the type of connection 
+    * @param gcf the constructing class
+    * @throws JMSException for any error
+    */
+   public SpyConnection(int type, GenericConnectionFactory gcf) throws JMSException
+   {
+      super(gcf);
+      this.type = type;
+   }
 
    public ConnectionConsumer createConnectionConsumer(Destination destination, String messageSelector,
          ServerSessionPool sessionPool, int maxMessages) throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
-
+      checkClosed();
       if (destination == null)
          throw new InvalidDestinationException("Null destination");
-
+      checkTemporary(destination);
+      
       return new SpyConnectionConsumer(this, destination, messageSelector, sessionPool, maxMessages);
    }
 
    public Session createSession(boolean transacted, int acknowledgeMode) throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
+      checkClosed();
       checkClientID();
 
       if (transacted)
@@ -103,12 +146,9 @@
       return session;
    }
 
-   // TopicConnection implementation --------------------------------
-
    public TopicSession createTopicSession(boolean transacted, int acknowledgeMode) throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
+      checkClosed();
       checkClientID();
 
       if (transacted)
@@ -127,13 +167,13 @@
    public ConnectionConsumer createConnectionConsumer(Topic topic, String messageSelector,
          ServerSessionPool sessionPool, int maxMessages) throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
-
+      checkClosed();
+      if (type == QUEUE)
+         throw new IllegalStateException("Cannot create a topic consumer on a QueueConnection");
       if (topic == null)
          throw new InvalidDestinationException("Null topic");
-
       checkClientID();
+      checkTemporary(topic);
 
       return new SpyConnectionConsumer(this, topic, messageSelector, sessionPool, maxMessages);
    }
@@ -141,9 +181,9 @@
    public ConnectionConsumer createDurableConnectionConsumer(Topic topic, String subscriptionName,
          String messageSelector, ServerSessionPool sessionPool, int maxMessages) throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
-
+      checkClosed();
+      if (type == QUEUE)
+         throw new IllegalStateException("Cannot create a topic consumer on a QueueConnection");
       if (topic == null)
          throw new InvalidDestinationException("Null topic");
       if (topic instanceof TemporaryTopic)
@@ -159,23 +199,20 @@
    public ConnectionConsumer createConnectionConsumer(Queue queue, String messageSelector,
          ServerSessionPool sessionPool, int maxMessages) throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
-
+      checkClosed();
+      if (type == TOPIC)
+         throw new IllegalStateException("Cannot create a queue consumer on a TopicConnection");
       if (queue == null)
          throw new InvalidDestinationException("Null queue");
+      checkTemporary(queue);
 
       return new SpyConnectionConsumer(this, queue, messageSelector, sessionPool, maxMessages);
    }
 
-   // QueueConnection implementation --------------------------------
-
    public QueueSession createQueueSession(boolean transacted, int acknowledgeMode) throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
+      checkClosed();
       checkClientID();
-
       if (transacted)
          acknowledgeMode = 0;
       QueueSession session = new SpyQueueSession(this, transacted, acknowledgeMode);
@@ -189,14 +226,10 @@
       return session;
    }
    
-   // Package protected ---------------------------------------------
-   
    TemporaryTopic getTemporaryTopic() throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
+      checkClosed();
       checkClientID();
-
       try
       {
          SpyTemporaryTopic temp = (SpyTemporaryTopic) serverIL.getTemporaryTopic(connectionToken);
@@ -216,12 +249,10 @@
 
    Topic createTopic(String name) throws JMSException
    {
+      checkClosed();
+      checkClientID();
       try
       {
-         if (closed)
-            throw new IllegalStateException("The connection is closed");
-         checkClientID();
-
          return serverIL.createTopic(connectionToken, name);
       }
       catch (Throwable t)
@@ -233,12 +264,8 @@
 
    TemporaryQueue getTemporaryQueue() throws JMSException
    {
-      if (closed)
-      {
-         throw new IllegalStateException("The connection is closed");
-      }
+      checkClosed();
       checkClientID();
-
       try
       {
          SpyTemporaryQueue temp = (SpyTemporaryQueue) serverIL.getTemporaryQueue(connectionToken);
@@ -258,11 +285,10 @@
 
    Queue createQueue(String name) throws JMSException
    {
+      checkClosed();
+      checkClientID();
       try
       {
-         if (closed)
-            throw new IllegalStateException("The connection is closed");
-         checkClientID();
 
          return serverIL.createQueue(connectionToken, name);
       }
@@ -272,10 +298,4 @@
          throw new UnreachableStatementException();
       }
    }
-   
-   // Protected -----------------------------------------------------
-   
-   // Private -------------------------------------------------------
-   
-   // Inner classes -------------------------------------------------
 }
\ No newline at end of file

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyJMSException.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyJMSException.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyJMSException.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,12 +1,24 @@
-/***************************************
- *                                     *
- *  JBoss: The OpenSource J2EE WebOS   *
- *                                     *
- *  Distributable under LGPL license.  *
- *  See terms of license at gnu.org.   *
- *                                     *
- ***************************************/
-
+/*
+* 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.mq;
 
 import java.io.PrintWriter;
@@ -27,18 +39,12 @@
  */
 public class SpyJMSException extends JMSException implements NestedThrowable
 {
-   // Constants -----------------------------------------------------
-
    /** The serialVersionUID */
    static final long serialVersionUID = 5216406958161784593L;
 
-   // Attributes ----------------------------------------------------
-
    /** The nested throwable */
    protected Throwable nested;
 
-   // Static --------------------------------------------------------
-
    /**
     * Converts a throwable to a JMSException if it is not already
     * 
@@ -65,8 +71,6 @@
       else
          return new SpyJMSException(message, t);
    }
-   
-   // Constructors --------------------------------------------------
 
    /**
 	 * Construct a <tt>SpyJMSException</tt> with the specified detail message.
@@ -106,8 +110,6 @@
       NestedThrowable.Util.checkNested(this, nested);
    }
 
-   // Public --------------------------------------------------------
-
    /**
 	 * Construct a <tt>SpyJMSException</tt> with the specified nested <tt>Throwable</tt>.
 	 * 
@@ -118,8 +120,6 @@
       this(nested.getMessage(), nested);
    }
 
-   // NestedException implementation --------------------------------
-
    public void setLinkedException(final Exception e)
    {
       this.nested = e;
@@ -136,8 +136,6 @@
       return new NestedException(nested);
    }
 
-   // Throwable overrides -------------------------------------------
-
    public Throwable getNested()
    {
       return nested;
@@ -171,12 +169,4 @@
    {
       printStackTrace(System.err);
    }
-
-   // Package protected ---------------------------------------------
-
-   // Protected -----------------------------------------------------
-
-   // Private -------------------------------------------------------
-
-   // Inner classes -------------------------------------------------
 }
\ No newline at end of file

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyMessage.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyMessage.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyMessage.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,8 +1,24 @@
 /*
- * JBossMQ, the OpenSource JMS implementation
- * 
- * Distributable under LGPL license. See terms of license at gnu.org.
- */
+* 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.mq;
 
 import java.io.Externalizable;
@@ -17,7 +33,6 @@
 import java.util.Map;
 
 import javax.jms.Destination;
-import javax.jms.IllegalStateException;
 import javax.jms.JMSException;
 import javax.jms.Message;
 import javax.jms.MessageFormatException;
@@ -44,6 +59,11 @@
    private final static long serialVersionUID = 467206190892964404L;
 
    /**
+    * Standard property for delivery count
+    */
+   public static final String PROPERTY_DELIVERY_COUNT = "JMSXDeliveryCount";
+
+   /**
 	 * JBoss-vendor specific property for scheduling a JMS message. In
 	 * milliseconds since January 1, 1970.
 	 */
@@ -69,6 +89,21 @@
 	 */
    public static final String PROPERTY_REDELIVERY_LIMIT = "JMS_JBOSS_REDELIVERY_LIMIT";
 
+   /** 
+   * JBoss-vendor property name holding original destination.
+   */
+   public static final String PROPERTY_ORIG_DESTINATION = "JBOSS_ORIG_DESTINATION";
+
+   /** 
+   * JBoss-vendor property name holding original expiration value.
+   */
+   public static final String PROPERTY_ORIG_EXPIRATION = "JBOSS_ORIG_EXPIRATION";
+
+   /** 
+   * JBoss-vendor property name holding original message ID value.
+   */
+   public static final String PROPERTY_ORIG_MESSAGEID = "JBOSS_ORIG_MESSAGEID";
+
    /** An object message */
    protected static final byte OBJECT_MESS = 1;
    /** An bytes message */
@@ -315,26 +350,10 @@
     */
    public void doAcknowledge() throws JMSException
    {
-      if (session.closed)
-         throw new IllegalStateException("Session is closed.");
       session.doAcknowledge(this, getAcknowledgementRequest(true));
    }
 
    /**
-    * Actually nack a message
-    *
-    * @throws JMSException for any error
-    */
-   public void doNegAcknowledge() throws JMSException
-   {
-      if (session.closed)
-      {
-         throw new IllegalStateException("Session is closed.");
-      }
-      session.doAcknowledge(this, getAcknowledgementRequest(false));
-   }
-
-   /**
     * Create an acknowledgement request for the message
     */
    public void createAcknowledgementRequest(int subscriptionId)
@@ -354,11 +373,10 @@
    public AcknowledgementRequest getAcknowledgementRequest(boolean isAck) throws JMSException
    {
       //don't know if we have to copy but to be on safe side...
-      AcknowledgementRequest item = new AcknowledgementRequest();
+      AcknowledgementRequest item = new AcknowledgementRequest(isAck);
       item.destination = ack.destination;
       item.messageID = ack.messageID;
       item.subscriberId = ack.subscriberId;
-      item.isAck = isAck;
       return item;
    }
 
@@ -935,9 +953,6 @@
       if (name.equals(""))
          throw new IllegalArgumentException("The name of a property must not be an empty String.");
 
-      if (Strings.isValidJavaIdentifier(name) == false)
-         throw new IllegalArgumentException("The property name '" + name + "' is not a valid java identifier.");
-
       if (reservedIdentifiers.contains(name))
          throw new IllegalArgumentException("The property name '" + name + "' is reserved due to selector syntax.");
 
@@ -963,6 +978,19 @@
             if (!(value instanceof Number))
                throw new JMSException(name + " must be Number: " + value);
          }
+         else if (name.equals(PROPERTY_ORIG_EXPIRATION))
+         {
+            if (!(value instanceof Long))
+               throw new JMSException(name + " must be Long: " + value);
+         }
+         else if (name.equals(PROPERTY_ORIG_DESTINATION))
+         {
+            // no validation
+         }
+         else if (name.equals(PROPERTY_ORIG_MESSAGEID))
+         {
+            // no validation
+         }
          else
          {
             throw new JMSException("Illegal property name: " + name);
@@ -977,6 +1005,10 @@
             return;
          throw new JMSException("Illegal property name: " + name);
       }
+
+      if (Strings.isValidJavaIdentifier(name) == false)
+         throw new IllegalArgumentException("The property name '" + name + "' is not a valid java identifier.");
+
    }
 
    /**

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyXAConnection.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyXAConnection.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyXAConnection.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,13 +1,28 @@
 /*
- * JBossMQ, the OpenSource JMS implementation
- * 
- * Distributable under LGPL license. See terms of license at gnu.org.
- */
+* 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.mq;
 
 import java.io.Serializable;
 
-import javax.jms.IllegalStateException;
 import javax.jms.JMSException;
 import javax.jms.QueueSession;
 import javax.jms.Session;
@@ -28,16 +43,8 @@
  */
 public class SpyXAConnection extends SpyConnection implements Serializable, XAConnection, XATopicConnection, XAQueueConnection
 {
-   // Constants -----------------------------------------------------
-
    /** The serialVersionUID */
    static final long serialVersionUID = 1258716704996031025L;
-   
-   // Attributes ----------------------------------------------------
-   
-   // Static --------------------------------------------------------
-   
-   // Constructors --------------------------------------------------
 
    /**
     * Create a new SpyXAConnection
@@ -63,10 +70,6 @@
       super(gcf);
    }
    
-   // Public --------------------------------------------------------
-   
-   // Connection overrides ------------------------------------------
-   
    public Session createSession(boolean transacted, int acknowledgeMode) throws JMSException
    {
       return createXASession();
@@ -81,13 +84,10 @@
    {
       return (TopicSession) createXATopicSession();
    }
-   
-   // XAConnection implementation -----------------------------------
 
    public XASession createXASession() throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
+      checkClosed();
       checkClientID();
 
       XASession session = new SpySession(this, true, 0, true);
@@ -101,8 +101,7 @@
 
    public XAQueueSession createXAQueueSession() throws JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
+      checkClosed();
       checkClientID();
 
       XAQueueSession session = new SpyQueueSession(this, true, 0, true);
@@ -118,8 +117,7 @@
 
    public XATopicSession createXATopicSession() throws javax.jms.JMSException
    {
-      if (closed)
-         throw new IllegalStateException("The connection is closed");
+      checkClosed();
       checkClientID();
 
       XATopicSession session = new SpyTopicSession(this, true, 0, true);
@@ -130,12 +128,4 @@
       }
       return session;
    }
-   
-   // Package protected ---------------------------------------------
-   
-   // Protected -----------------------------------------------------
-   
-   // Private -------------------------------------------------------
-   
-   // Inner classes -------------------------------------------------
 }
\ No newline at end of file

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyXAException.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyXAException.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyXAException.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,21 +1,33 @@
-/***************************************
- *                                     *
- *  JBoss: The OpenSource J2EE WebOS   *
- *                                     *
- *  Distributable under LGPL license.  *
- *  See terms of license at gnu.org.   *
- *                                     *
- ***************************************/
-
+/*
+* 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.mq;
 
+import java.io.PrintStream;
 import java.io.PrintWriter;
-import java.io.PrintStream;
 
 import javax.transaction.xa.XAException;
 
+import org.jboss.util.NestedException;
 import org.jboss.util.NestedThrowable;
-import org.jboss.util.NestedException;
 
 /**
  * An XAException with a nested throwable
@@ -25,19 +37,43 @@
  */
 public class SpyXAException extends XAException implements NestedThrowable
 {
-   // Constants -----------------------------------------------------
-
    /** The serialVersionUID */
    static final long serialVersionUID = 7814140228056884098L;
-   
-   // Attributes ----------------------------------------------------
 
    /** The nested throwable */
    protected Throwable nested;
+
+   /**
+    * Converts a throwable to an XAException if it is not already
+    * 
+    * @param message any message to add to a constructed XAException
+    * @param t the throwable
+    * @return XAException never (always throws)
+    * @throws XAException always
+    */
+   public static XAException rethrowAsXAException(String message, Throwable t) throws XAException
+   {
+      throw getAsXAException(message, t);
+   }
    
-   // Static --------------------------------------------------------
-   
-   // Constructors --------------------------------------------------
+   /**
+    * Converts a throwable to an XAException if it is not already
+    * 
+    * @param message any message to add to a constructed XAException
+    * @param t the throwable
+    * @return an XAException
+    */
+   public static XAException getAsXAException(String message, Throwable t)
+   {
+      if (t instanceof XAException)
+         return (XAException) t;
+      else
+      {
+         SpyXAException e = new SpyXAException(message, t);
+         e.errorCode = XAException.XAER_RMERR;
+         return e;
+      }
+   }
 
    /**
     * Construct a <tt>SpyXAException</tt>
@@ -106,17 +142,11 @@
       super(code);
       this.nested = t;
    }
-   
-   // Public --------------------------------------------------------
-   
-   // NestedException implementation --------------------------------
 
    public Throwable getNested()
    {
       return nested;
    }
-   
-   // Throwable overrides -------------------------------------------
 
    public Throwable getCause()
    {
@@ -137,7 +167,7 @@
       if (nested == null)
          return this;
       if (nested instanceof Exception)
-        {
+      {
          return (Exception) nested;
       }
       return new NestedException(nested);
@@ -151,7 +181,7 @@
    public void printStackTrace(final PrintStream stream)
    {
       if (nested == null || NestedThrowable.PARENT_TRACE_ENABLED)
-        {
+      {
          super.printStackTrace(stream);
       }
       NestedThrowable.Util.print(nested, stream);
@@ -160,7 +190,7 @@
    public void printStackTrace(final PrintWriter writer)
    {
       if (nested == null || NestedThrowable.PARENT_TRACE_ENABLED)
-        {
+      {
          super.printStackTrace(writer);
       }
       NestedThrowable.Util.print(nested, writer);
@@ -170,13 +200,4 @@
    {
       printStackTrace(System.err);
    }
-   
-   // Package protected ---------------------------------------------
-   
-   // Protected -----------------------------------------------------
-   
-   // Private -------------------------------------------------------
-   
-   // Inner classes -------------------------------------------------
-
 }
\ No newline at end of file

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyXAResource.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyXAResource.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyXAResource.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBossMQ, the OpenSource JMS implementation
- * 
- * Distributable under LGPL license. See terms of license at gnu.org.
- */
-
+* 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.mq;
 
 import javax.transaction.xa.XAException;
@@ -21,22 +36,14 @@
  */
 public class SpyXAResource implements XAResource
 {
-   // Constants -----------------------------------------------------
-
    /** The log */
    private static final Logger log = Logger.getLogger(SpyXAResource.class);
    
    /** Whether trace is enabled */
    private static boolean trace = log.isTraceEnabled();
-   
-   // Attributes ----------------------------------------------------
 
    /** The session */
    SpySession session;
-   
-   // Static --------------------------------------------------------
-   
-   // Constructors --------------------------------------------------
 
    /**
     * Create a new SpyXAResource
@@ -52,10 +59,6 @@
       if (trace)
          log.trace("Created " + this);
    }
-   
-   // Public --------------------------------------------------------
-   
-   // XAResource implementation -------------------------------------
 
    public boolean setTransactionTimeout(int arg1) throws XAException
    {
@@ -73,18 +76,20 @@
          return false;
       return ((SpyXAResource) arg1).session.connection.spyXAResourceManager == session.connection.spyXAResourceManager;
    }
+
    public void commit(Xid xid, boolean onePhase) throws XAException
    {
       if (trace)
          log.trace("Commit xid=" + xid + ", onePhase=" + onePhase + " " + this);
 
+      xid = convertXid(xid);
       try
       {
          session.connection.spyXAResourceManager.commit(xid, onePhase);
       }
       catch (Throwable t)
       {
-         throw new SpyXAException(XAException.XAER_RMERR, t);
+         throw SpyXAException.getAsXAException("Resource manager error during commit", t);
       }
    }
 
@@ -93,6 +98,7 @@
       if (trace)
          log.trace("End xid=" + xid + ", flags=" + flags + " " +this);
 
+      xid = convertXid(xid);
       synchronized (session.runLock)
       {
 
@@ -118,51 +124,72 @@
    {
       if (trace)
          log.trace("Forget xid=" + xid + " " + this);
+      
+      xid = convertXid(xid);
+      try
+      {
+         session.connection.spyXAResourceManager.forget(xid);
+      }
+      catch (Throwable t)
+      {
+         throw SpyXAException.getAsXAException("Resource manager error during forget", t);
+      }
    }
 
    public int prepare(Xid xid) throws XAException
    {
-      if (log.isTraceEnabled())
+      if (trace)
          log.trace("Prepare xid=" + xid + " " + this);
 
+      xid = convertXid(xid);
       try
       {
          return session.connection.spyXAResourceManager.prepare(xid);
       }
       catch (Throwable t)
       {
-         throw new SpyXAException(XAException.XAER_RMERR, t);
+         throw SpyXAException.getAsXAException("Resource manager error during prepare", t);
       }
    }
 
    public Xid[] recover(int arg1) throws XAException
    {
-      if (log.isTraceEnabled())
+      if (trace)
          log.trace("Recover arg1=" + arg1 + " " + this);
 
-      return new Xid[0];
+      try
+      {
+         return session.connection.spyXAResourceManager.recover(arg1);
+      }
+      catch (Throwable t)
+      {
+         throw SpyXAException.getAsXAException("Resource manager error during recover", t);
+      }
    }
 
    public void rollback(Xid xid) throws XAException
    {
-      if (log.isTraceEnabled())
+      if (trace)
          log.trace("Rollback xid=" + xid + " " + this);
 
+      xid = convertXid(xid);
       try
       {
          session.connection.spyXAResourceManager.rollback(xid);
       }
       catch (Throwable t)
       {
-         throw new SpyXAException(XAException.XAER_RMERR, t);
+         throw SpyXAException.getAsXAException("Resource manager error during rollback", t);
       }
    }
 
    public void start(Xid xid, int flags) throws XAException
    {
-      if (log.isTraceEnabled())
+      if (trace)
          log.trace("Start xid=" + xid + ", flags=" + flags + " " + this);
 
+      xid = convertXid(xid);
+
       boolean convertTx = false;
       if (session.getCurrentTransactionId() != null)
       {
@@ -172,7 +199,9 @@
          }
          else
          {
-            throw new XAException(XAException.XAER_OUTSIDE);
+            XAException e = new XAException("Attempt to enlist in " + xid + " with TMNOFLAGS when already enlisted " + session.getCurrentTransactionId());
+            e.errorCode = XAException.XAER_OUTSIDE; // REVIEW: Is this the correct error code?
+            throw e;
          }
       }
 
@@ -205,18 +234,30 @@
       }
    }
    
-   // Object overrides ----------------------------------------------
-   
    public String toString()
    {
       return "SpyXAResource[session=" + session + ']';
    }
    
-   // Package protected ---------------------------------------------
-   
-   // Protected -----------------------------------------------------
-   
-   // Private -------------------------------------------------------
-   
-   // Inner classes -------------------------------------------------
+   /**
+    * Convert the external xid to our internal one
+    * 
+    * @param xid the xid
+    * @return our internal xid
+    * @throws XAException for a null xid
+    */
+   protected Xid convertXid(Xid xid) throws XAException
+   {
+      if (xid == null)
+      {
+         XAException e = new XAException("Null xid");
+         e.errorCode = XAException.XAER_NOTA;
+         throw e;
+      }
+      
+      if (xid instanceof JBossMQXid)
+         return xid;
+      
+      return new JBossMQXid(xid);
+   }
 }
\ No newline at end of file

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyXAResourceManager.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyXAResourceManager.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/SpyXAResourceManager.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBossMQ, the OpenSource JMS implementation
- * 
- * Distributable under LGPL license. See terms of license at gnu.org.
- */
-
+* 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.mq;
 
 import java.io.Serializable;
@@ -14,6 +29,7 @@
 
 import javax.jms.JMSException;
 import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
 import javax.transaction.xa.Xid;
 
 import org.jboss.logging.Logger;
@@ -28,8 +44,6 @@
  */
 public class SpyXAResourceManager implements Serializable
 {
-   // Constants -----------------------------------------------------
-
    /** The serialVersionUID */
    static final long serialVersionUID = -6268132972627753772L;
    /** The log */
@@ -43,8 +57,7 @@
    private final static byte TX_PREPARED = 3;
    private final static byte TX_COMMITED = 4;
    private final static byte TX_ROLLEDBACK = 5;
-   
-   // Attributes ----------------------------------------------------
+   private final static byte TX_READONLY = 6;
 
    /** The connection */
    private Connection connection;
@@ -52,11 +65,7 @@
    private Map transactions = new ConcurrentReaderHashMap();
    /** The next xid */
    private long nextInternalXid = Long.MIN_VALUE;
-
-   // Static --------------------------------------------------------
    
-   // Constructors --------------------------------------------------
-   
    /**
     * Create a new SpyXAResourceManager
     *
@@ -67,8 +76,6 @@
       super();
       connection = conn;
    }
-   
-   // Public --------------------------------------------------------
 
    /**
     * Acknowledge a message
@@ -127,10 +134,20 @@
 
       TXState state = (TXState) transactions.remove(xid);
       if (state == null)
-         throw new XAException(XAException.XAER_NOTA);
+      {
+         XAException e = new XAException("Unknown transaction during commit " + xid);
+         e.errorCode = XAException.XAER_NOTA;
+         throw e;
+      }
 
       if (onePhase)
-        {
+      {
+         if (state.isReadOnly())
+         {
+            if (trace)
+               log.trace("Nothing to do for " + xid);
+         }
+         
          TransactionRequest transaction = new TransactionRequest();
          transaction.requestType = TransactionRequest.ONE_PHASE_COMMIT_REQUEST;
          transaction.xid = null;
@@ -150,8 +167,18 @@
       }
       else
       {
+         if (state.txState == TX_READONLY)
+         {
+            if (trace)
+               log.trace("Nothing to do for " + xid);
+            return;
+         }
          if (state.txState != TX_PREPARED)
-            throw new XAException("The transaction had not been prepared");
+         {
+            XAException e = new XAException("Cannot complete 2 phase commit, the transaction has not been prepared " + xid);
+            e.errorCode = XAException.XAER_PROTO;
+            throw e;
+         }
          TransactionRequest transaction = new TransactionRequest();
          transaction.xid = xid;
          transaction.requestType = TransactionRequest.TWO_PHASE_COMMIT_COMMIT_REQUEST;
@@ -167,7 +194,11 @@
 
       TXState state = (TXState) transactions.get(xid);
       if (state == null)
-         throw new XAException(XAException.XAER_NOTA);
+      {
+         XAException e = new XAException("Unknown transaction during delist " + xid);
+         e.errorCode = XAException.XAER_NOTA;
+         throw e;
+      }
       state.txState = TX_ENDED;
    }
 
@@ -177,7 +208,11 @@
          log.trace("Joining tx xid=" + xid);
 
       if (!transactions.containsKey(xid))
-         throw new XAException(XAException.XAER_NOTA);
+      {
+         XAException e = new XAException("Unknown transaction during join " + xid);
+         e.errorCode = XAException.XAER_NOTA;
+         throw e;
+      }
       return xid;
    }
 
@@ -188,7 +223,20 @@
 
       TXState state = (TXState) transactions.get(xid);
       if (state == null)
-         throw new XAException(XAException.XAER_NOTA);
+      {
+         XAException e = new XAException("Unknown transaction during prepare " + xid);
+         e.errorCode = XAException.XAER_NOTA;
+         throw e;
+      }
+
+      if (state.isReadOnly())
+      {
+         if (trace)
+            log.trace("Vote read only for " + xid);
+         state.txState = TX_READONLY;
+         return XAResource.XA_RDONLY;
+      }
+      
       TransactionRequest transaction = new TransactionRequest();
       transaction.requestType = TransactionRequest.TWO_PHASE_COMMIT_PREPARE_REQUEST;
       transaction.xid = xid;
@@ -206,7 +254,7 @@
       }
       connection.send(transaction);
       state.txState = TX_PREPARED;
-      return javax.transaction.xa.XAResource.XA_OK;
+      return XAResource.XA_OK;
    }
 
    public Object resumeTx(Xid xid) throws XAException
@@ -215,7 +263,11 @@
          log.trace("Resuming tx xid=" + xid);
 
       if (!transactions.containsKey(xid))
-         throw new XAException(XAException.XAER_NOTA);
+      {
+         XAException e = new XAException("Unknown transaction during resume " + xid);
+         e.errorCode = XAException.XAER_NOTA;
+         throw e;
+      }
       return xid;
    }
 
@@ -226,7 +278,17 @@
 
       TXState state = (TXState) transactions.remove(xid);
       if (state == null)
-         throw new XAException(XAException.XAER_NOTA);
+      {
+         XAException e = new XAException("Unknown transaction during rollback " + xid);
+         e.errorCode = XAException.XAER_NOTA;
+         throw e;
+      }
+      if (state.txState == TX_READONLY)
+      {
+         if (trace)
+            log.trace("Nothing to do for " + xid);
+         return;
+      }
       if (state.txState != TX_PREPARED)
       {
          TransactionRequest transaction = new TransactionRequest();
@@ -239,7 +301,7 @@
             transaction.acks = job;
             //Neg Acknowlege all consumed messages
             for (int i = 0; i < transaction.acks.length; i++)
-              {
+            {
                transaction.acks[i].isAck = false;
             }
          }
@@ -255,6 +317,39 @@
       state.txState = TX_ROLLEDBACK;
    }
 
+   public Xid[] recover(int arg) throws XAException, JMSException
+   {
+      if (trace)
+         log.trace("Recover arg=" + arg);
+      
+      Xid[] xids = connection.recover(arg);
+
+      // Make sure we have a reference to each xid
+      for (int i = 0; i < xids.length; ++i)
+      {
+         if (transactions.containsKey(xids[i]) == false)
+         {
+            TXState state = new TXState();
+            state.txState = TX_PREPARED;
+            transactions.put(xids[i], state);
+         }
+      }
+      return xids;
+   }
+
+   public void forget(Xid xid) throws XAException, JMSException
+   {
+      if (trace)
+         log.trace("Forget xid=" + xid);
+
+      TXState state = (TXState) transactions.get(xid);
+      if (state == null)
+         return;
+      if (state.txState != TX_PREPARED)
+         transactions.remove(xid);
+      rollback(xid);
+   }
+   
    public synchronized Long getNewXid()
    {
       return new Long(nextInternalXid++);
@@ -277,7 +372,11 @@
          log.trace("Starting tx xid=" + xid);
 
       if (transactions.containsKey(xid))
-         throw new XAException(XAException.XAER_DUPID);
+      {
+         XAException e = new XAException("Duplicate transaction id during enlist " + xid);
+         e.errorCode = XAException.XAER_DUPID;
+         throw e;
+      }
       transactions.put(xid, new TXState());
       return xid;
    }
@@ -288,7 +387,11 @@
          log.trace("Suppending tx xid=" + xid);
 
       if (!transactions.containsKey(xid))
-         throw new XAException(XAException.XAER_NOTA);
+      {
+         XAException e = new XAException("Unknown transaction during suspend " + xid);
+         e.errorCode = XAException.XAER_NOTA;
+         throw e;
+      }
       return xid;
    }
 
@@ -298,32 +401,37 @@
          log.trace("Converting tx anonXid=" + anonXid + ", xid=" + xid);
 
       if (!transactions.containsKey(anonXid))
-         throw new XAException(XAException.XAER_NOTA);
+      {
+         XAException e = new XAException("Unknown transaction during convert " + anonXid);
+         e.errorCode = XAException.XAER_NOTA;
+         throw e;
+      }
       if (transactions.containsKey(xid))
-         throw new XAException(XAException.XAER_DUPID);
+      {
+         XAException e = new XAException("Duplicate transaction during convert " + xid);
+         e.errorCode = XAException.XAER_DUPID;
+         throw e;
+      }
       TXState s = (TXState) transactions.remove(anonXid);
 
       transactions.put(xid, s);
       return xid;
    }
-   
-   // Package protected ---------------------------------------------
-   
-   // Protected -----------------------------------------------------
-   
-   // Private -------------------------------------------------------
-   
-   // Inner classes -------------------------------------------------
 
    /**
-	  * The transaction state
-	  */
+    * The transaction state
+	*/
    static class TXState
    {
       byte txState = TX_OPEN;
       ArrayList sentMessages = new ArrayList();
       ArrayList ackedMessages = new ArrayList();
 
+      public boolean isReadOnly()
+      {
+         return sentMessages.size() == 0 && ackedMessages.size() == 0;
+      }
+      
       public String toString()
       {
          StringBuffer buffer = new StringBuffer(100);

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/http/HTTPServerIL.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/http/HTTPServerIL.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/http/HTTPServerIL.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.http;
 
 import java.io.Serializable;
@@ -14,11 +29,13 @@
 import javax.jms.TemporaryQueue;
 import javax.jms.TemporaryTopic;
 import javax.jms.Topic;
+import javax.transaction.xa.Xid;
 
 import org.jboss.logging.Logger;
 import org.jboss.mq.AcknowledgementRequest;
 import org.jboss.mq.ConnectionToken;
 import org.jboss.mq.DurableSubscriptionID;
+import org.jboss.mq.Recoverable;
 import org.jboss.mq.SpyDestination;
 import org.jboss.mq.SpyMessage;
 import org.jboss.mq.Subscription;
@@ -37,7 +54,7 @@
  * @version   $Revision$
  * @created   January 15, 2003
  */
-public class HTTPServerIL implements Serializable, ServerIL
+public class HTTPServerIL implements Serializable, ServerIL, Recoverable
 {
     static final long serialVersionUID = -864073076154976490L;
 
@@ -333,6 +350,20 @@
         this.postRequest(request);
     }
     
+    public Xid[] recover(ConnectionToken dc, int flags) throws Exception
+    {
+        if (log.isTraceEnabled())
+            log.trace("recover(ConnectionToken " + dc + ", flags=" + flags + ")");
+        HTTPILRequest request = new HTTPILRequest();
+        request.setMethodName("recover");
+        request.setArguments
+        (
+           new Object[] { dc, new Integer(flags) }, 
+           new Class[]  { ConnectionToken.class, Integer.class }
+        );
+        return (Xid[]) this.postRequest(request);
+    }
+    
     public void unsubscribe(ConnectionToken dc, int subscriptionId) throws Exception
     {
         if (log.isTraceEnabled())

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/jvm/JVMServerIL.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/jvm/JVMServerIL.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/jvm/JVMServerIL.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,8 +1,23 @@
 /*
- * JBoss, the OpenSource J2EE webOS
+ * 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.
  *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
+ * 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.mq.il.jvm;
 
@@ -12,10 +27,12 @@
 import javax.jms.TemporaryQueue;
 import javax.jms.TemporaryTopic;
 import javax.jms.Topic;
+import javax.transaction.xa.Xid;
 
 import org.jboss.mq.AcknowledgementRequest;
 import org.jboss.mq.ConnectionToken;
 import org.jboss.mq.DurableSubscriptionID;
+import org.jboss.mq.Recoverable;
 import org.jboss.mq.SpyDestination;
 import org.jboss.mq.SpyMessage;
 import org.jboss.mq.TransactionRequest;
@@ -28,10 +45,11 @@
  * @author    Hiram Chirino (Cojonudo14 at hotmail.com)
  * @author    Norbert Lataille (Norbert.Lataille at m4x.org)
  * @author    <a href="pra at tim.se">Peter Antman</a>
+ * @author    <a href="adrian at jboss.org">Adrian Brock</a>
  * @version   $Revision$
  * @created   August 16, 2001
  */
-public class JVMServerIL implements org.jboss.mq.il.ServerIL
+public class JVMServerIL implements ServerIL, Recoverable
 {
    //The server implementation
    private final Invoker server;
@@ -43,300 +61,132 @@
     */
    public JVMServerIL(Invoker s)
    {
-      if (s == null) 
-      {
+      if (s == null)
          throw new IllegalArgumentException("JMSServer must be non null in constructor");
-      } // end of if ()
-      
       server = s;
    }
 
-   /**
-    * Sets the ConnectionToken attribute of the JVMServerIL object
-    *
-    * @param newConnectionToken  The new ConnectionToken value
-    */
    public void setConnectionToken(ConnectionToken newConnectionToken)
    {
       // We cannot try to cache the token since this IL is stateless
    }
 
-   /**
-    * Sets the Enabled attribute of the JVMServerIL object
-    *
-    * @param dc             The new Enabled value
-    * @param enabled        The new Enabled value
-    * @exception Exception  Description of Exception
-    */
-   public void setEnabled(ConnectionToken dc, boolean enabled)
-          throws Exception
+   public void setEnabled(ConnectionToken dc, boolean enabled) throws Exception
    {
       server.setEnabled(dc, enabled);
    }
 
-   /**
-    * Gets the ID attribute of the JVMServerIL object
-    *
-    * @return                  The ID value
-    * @exception JMSException  Description of Exception
-    */
-   public String getID()
-          throws JMSException
+   public String getID() throws JMSException
    {
       return server.getID();
    }
 
-   /**
-    * Gets the TemporaryQueue attribute of the JVMServerIL object
-    *
-    * @param dc                Description of Parameter
-    * @return                  The TemporaryQueue value
-    * @exception JMSException  Description of Exception
-    */
-   public TemporaryQueue getTemporaryQueue(ConnectionToken dc)
-          throws JMSException
+   public TemporaryQueue getTemporaryQueue(ConnectionToken dc) throws JMSException
    {
       return server.getTemporaryQueue(dc);
    }
 
-   /**
-    * Gets the TemporaryTopic attribute of the JVMServerIL object
-    *
-    * @param dc                Description of Parameter
-    * @return                  The TemporaryTopic value
-    * @exception JMSException  Description of Exception
-    */
-   public TemporaryTopic getTemporaryTopic(ConnectionToken dc)
-          throws JMSException
+   public TemporaryTopic getTemporaryTopic(ConnectionToken dc) throws JMSException
    {
       return server.getTemporaryTopic(dc);
    }
 
-   /**
-    * No need to clone because there are no instance variables tha can get
-    * clobbered. All Multiple connections can share the same JVMServerIL object
-    *
-    * @return   Description of the Returned Value
-    */
    public ServerIL cloneServerIL()
    {
       return this;
    }
 
-   /**
-    * Adds a feature to the Message attribute of the JVMServerIL object
-    *
-    * @param dc                The feature to be added to the Message attribute
-    * @param val               The feature to be added to the Message attribute
-    * @exception JMSException  Description of Exception
-    */
-   public void addMessage(ConnectionToken dc, SpyMessage val)
-          throws JMSException
+   public void addMessage(ConnectionToken dc, SpyMessage val) throws JMSException
    {
       server.addMessage(dc, val.myClone());
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc                Description of Parameter
-    * @param dest              Description of Parameter
-    * @return                  Description of the Returned Value
-    * @exception JMSException  Description of Exception
-    */
-   public Topic createTopic(ConnectionToken dc, String dest)
-          throws JMSException
+   public Topic createTopic(ConnectionToken dc, String dest) throws JMSException
    {
       return server.createTopic(dc, dest);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc                Description of Parameter
-    * @param dest              Description of Parameter
-    * @return                  Description of the Returned Value
-    * @exception JMSException  Description of Exception
-    */
-   public Queue createQueue(ConnectionToken dc, String dest)
-          throws JMSException
+   public Queue createQueue(ConnectionToken dc, String dest) throws JMSException
    {
       return server.createQueue(dc, dest);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc                Description of Parameter
-    * @param dest              Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
-   public void deleteTemporaryDestination(ConnectionToken dc, SpyDestination dest)
-          throws JMSException
+   public void deleteTemporaryDestination(ConnectionToken dc, SpyDestination dest) throws JMSException
    {
       server.deleteTemporaryDestination(dc, dest);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param ID                Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
-   public void checkID(String ID)
-          throws JMSException
+   public void checkID(String ID) throws JMSException
    {
       server.checkID(ID);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc                Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
-   public void connectionClosing(ConnectionToken dc)
-          throws JMSException
+   public void connectionClosing(ConnectionToken dc) throws JMSException
    {
       server.connectionClosing(dc);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param item           Description of Parameter
-    * @exception Exception  Description of Exception
-    */
-   public void acknowledge(ConnectionToken dc, AcknowledgementRequest item)
-          throws Exception
+   public void acknowledge(ConnectionToken dc, AcknowledgementRequest item) throws Exception
    {
       server.acknowledge(dc, item);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param dest           Description of Parameter
-    * @param selector       Description of Parameter
-    * @return               Description of the Returned Value
-    * @exception Exception  Description of Exception
-    */
-   public SpyMessage[] browse(ConnectionToken dc, Destination dest, String selector)
-          throws Exception
+   public SpyMessage[] browse(ConnectionToken dc, Destination dest, String selector) throws Exception
    {
       return server.browse(dc, dest, selector);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param subscriberId   Description of Parameter
-    * @param wait           Description of Parameter
-    * @return               Description of the Returned Value
-    * @exception Exception  Description of Exception
-    */
-   public SpyMessage receive(ConnectionToken dc, int subscriberId, long wait)
-          throws Exception
+   public SpyMessage receive(ConnectionToken dc, int subscriberId, long wait) throws Exception
    {
       SpyMessage message = server.receive(dc, subscriberId, wait);
       //copy message to avoid server side problems with persisted message if message is edited client side.
-      if(message != null)
+      if (message != null)
          message = message.myClone();
       return message;
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc              Description of Parameter
-    * @param subscriptionId  Description of Parameter
-    * @exception Exception   Description of Exception
-    */
-   public void unsubscribe(ConnectionToken dc, int subscriptionId)
-          throws Exception
+   public void unsubscribe(ConnectionToken dc, int subscriptionId) throws Exception
    {
       server.unsubscribe(dc, subscriptionId);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param id             Description of Parameter
-    * @exception Exception  Description of Exception
-    */
-   public void destroySubscription(ConnectionToken dc,DurableSubscriptionID id)
-          throws Exception
+   public void destroySubscription(ConnectionToken dc, DurableSubscriptionID id) throws Exception
    {
-      server.destroySubscription(dc,id);
+      server.destroySubscription(dc, id);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param userName          Description of Parameter
-    * @param password          Description of Parameter
-    * @return                  Description of the Returned Value
-    * @exception JMSException  Description of Exception
-    */
-   public String checkUser(String userName, String password)
-          throws JMSException
+   public String checkUser(String userName, String password) throws JMSException
    {
       return server.checkUser(userName, password);
    }
-   
-   /**
-    * Authenticate user
-    *
-    * @param userName          Description of Parameter
-    * @param password          Description of Parameter
-    * @return                  a sessionID
-    * @exception JMSException  Description of Exception
-    */
-   public String authenticate(String userName, String password)
-          throws JMSException
+
+   public String authenticate(String userName, String password) throws JMSException
    {
       return server.authenticate(userName, password);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param s              Description of Parameter
-    * @exception Exception  Description of Exception
-    */
-   public void subscribe(ConnectionToken dc, org.jboss.mq.Subscription s)
-          throws Exception
+   public void subscribe(ConnectionToken dc, org.jboss.mq.Subscription s) throws Exception
    {
       server.subscribe(dc, s.myClone());
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc                Description of Parameter
-    * @param t                 Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
-   public void transact(org.jboss.mq.ConnectionToken dc, TransactionRequest t)
-          throws JMSException
+   public void transact(org.jboss.mq.ConnectionToken dc, TransactionRequest t) throws JMSException
    {
       server.transact(dc, t);
    }
 
-   /**
-    * ping method comment.
-    *
-    * @param dc                Description of Parameter
-    * @param clientTime        Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
-   public void ping(org.jboss.mq.ConnectionToken dc, long clientTime)
-          throws JMSException
+   public void ping(org.jboss.mq.ConnectionToken dc, long clientTime) throws JMSException
    {
       server.ping(dc, clientTime);
    }
+
+   public Xid[] recover(ConnectionToken dc, int flags) throws Exception
+   {
+      if (server instanceof Recoverable)
+      {
+         Recoverable recoverable = (Recoverable) server;
+         return recoverable.recover(dc, flags);
+      }
+      throw new IllegalStateException("Invoker does not implement recoverable " + server);
+   }
 }

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/ServerSocketManagerHandler.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/ServerSocketManagerHandler.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/ServerSocketManagerHandler.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,17 +1,34 @@
 /*
-* JBoss, the OpenSource J2EE webOS
+* 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.
 *
-* Distributable under LGPL license.
-* See terms of license at gnu.org.
+* 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.mq.il.uil2;
 
 import java.rmi.RemoteException;
 import javax.jms.Destination;
+import javax.transaction.xa.Xid;
 
 import org.jboss.logging.Logger;
 import org.jboss.mq.ConnectionToken;
 import org.jboss.mq.AcknowledgementRequest;
+import org.jboss.mq.Recoverable;
 import org.jboss.mq.SpyMessage;
 import org.jboss.mq.SpyDestination;
 import org.jboss.mq.TransactionRequest;
@@ -26,6 +43,7 @@
 import org.jboss.mq.il.uil2.msgs.CreateDestMsg;
 import org.jboss.mq.il.uil2.msgs.DeleteTemporaryDestMsg;
 import org.jboss.mq.il.uil2.msgs.GetIDMsg;
+import org.jboss.mq.il.uil2.msgs.RecoverMsg;
 import org.jboss.mq.il.uil2.msgs.TemporaryDestMsg;
 import org.jboss.mq.il.uil2.msgs.ReceiveMsg;
 import org.jboss.mq.il.uil2.msgs.EnableConnectionMsg;
@@ -85,6 +103,7 @@
             AcknowledgementRequestMsg ackmsg = (AcknowledgementRequestMsg) msg;
             AcknowledgementRequest ack = ackmsg.getAck();
             server.acknowledge(connectionToken, ack);
+            // We send the reply although on newer clients it is ignored.
             socketMgr.sendReply(msg);
             break;
          case m_addMessage:
@@ -172,6 +191,18 @@
             server.transact(connectionToken, trans);
             socketMgr.sendReply(msg);
             break;
+         case m_recover:
+            RecoverMsg recmsg = (RecoverMsg) msg;
+            int flags = recmsg.getFlags();
+            if (server instanceof Recoverable)
+            {
+               Recoverable recoverable = (Recoverable) server;
+               Xid[] xids = recoverable.recover(connectionToken, flags);
+               recmsg.setXids(xids);
+               socketMgr.sendReply(msg);
+               break;
+            }
+            throw new IllegalStateException("Invoker does not implement recoverable " + server);
          case m_unsubscribe:
             UnsubscribeMsg umsg = (UnsubscribeMsg) msg;
             server.unsubscribe(connectionToken, umsg.getSubscriptionID());

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/SocketManager.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/SocketManager.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/SocketManager.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE WebOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2;
 
 import java.io.IOException;
@@ -24,6 +39,7 @@
 import EDU.oswego.cs.dl.util.concurrent.LinkedQueue;
 import EDU.oswego.cs.dl.util.concurrent.PooledExecutor;
 import EDU.oswego.cs.dl.util.concurrent.SynchronizedBoolean;
+import EDU.oswego.cs.dl.util.concurrent.SynchronizedInt;
 import EDU.oswego.cs.dl.util.concurrent.ThreadFactory;
 
 /** Used to manage the client/server and server/client communication in an
@@ -41,7 +57,7 @@
    private static final int STOPPED = 0;
    private static final int STARTED = 1;
    private static final int STOPPING = 2;
-   private static int taskID = 0;
+   private static SynchronizedInt taskID = new SynchronizedInt(0);
 
    /** The socket created by the IL layer */
    private Socket socket;
@@ -111,14 +127,12 @@
          pool.setThreadFactory(new UILThreadFactory(id));
       }
 
-      taskID++;
       ReadTask readTask = new ReadTask();
-      readThread = new Thread(tg, readTask, "UIL2.SocketManager.ReadTask#" + taskID + " client=" +  ipAddress);
+      readThread = new Thread(tg, readTask, "UIL2.SocketManager.ReadTask#" + taskID.increment() + " client=" +  ipAddress);
       readThread.setDaemon(true);
 
-      taskID++;
       WriteTask writeTask = new WriteTask();
-      writeThread = new Thread(tg, writeTask, "UIL2.SocketManager.WriteTask#" + taskID + " client=" + ipAddress);
+      writeThread = new Thread(tg, writeTask, "UIL2.SocketManager.WriteTask#" + taskID.increment() + " client=" + ipAddress);
       writeThread.setDaemon(true);
       
       synchronized (running)
@@ -211,12 +225,12 @@
          throw msg.error;
       }
    }
-   /** Send a one-way message. Typically this is a reply message, but it
-    * could be an asynchronous msg that does not need a reply as it true
-    * for ping msgs.
+
+   /** 
+    * Send a reply.
     *
-    * @param msg
-    * @throws Exception
+    * @param msg the message
+    * @throws Exception for any error
     */
    public void sendReply(BaseMsg msg) throws Exception
    {
@@ -224,6 +238,18 @@
       internalSendMessage(msg, false);
    }
 
+   /** 
+    * Send a one-way.
+    *
+    * @param msg the message
+    * @throws Exception for any error
+    */
+   public void sendOneWay(BaseMsg msg) throws Exception
+   {
+      msg.getMsgID();
+      internalSendMessage(msg, false);
+   }
+
    /** This places the msg into the sendQueue and returns if waitOnReply
     * is false, or enques the msg to the sendQueue, places the msg
     * in the replyMap and waits on the msg.

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/SocketManagerHandler.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/SocketManagerHandler.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/SocketManagerHandler.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,8 +1,23 @@
 /*
-* JBoss, the OpenSource J2EE webOS
+* 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.
 *
-* Distributable under LGPL license.
-* See terms of license at gnu.org.
+* 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.mq.il.uil2;
 

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/UILClientIL.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/UILClientIL.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/UILClientIL.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2;
 
 import java.io.Serializable;
@@ -32,22 +47,13 @@
 
    private transient SocketManager socketMgr;
 
-   /**
-    * #Description of the Method
-    *
-    * @exception Exception  Description of Exception
-    */
    public void close()
           throws Exception
    {
+      if (socketMgr != null)
+         socketMgr.stop();
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dest           Description of Parameter
-    * @exception Exception  Description of Exception
-    */
    public void deleteTemporaryDestination(SpyDestination dest)
           throws Exception
    {
@@ -55,12 +61,6 @@
       socketMgr.sendReply(msg);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param serverTime     Description of Parameter
-    * @exception Exception  Description of Exception
-    */
    public void pong(long serverTime)
           throws Exception
    {
@@ -69,12 +69,6 @@
       socketMgr.sendReply(msg);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param messages       Description of Parameter
-    * @exception Exception  Description of Exception
-    */
    public void receive(ReceiveRequest messages[])
           throws Exception
    {

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/UILClientILService.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/UILClientILService.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/UILClientILService.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2;
 
 import java.lang.reflect.UndeclaredThrowableException;
@@ -94,6 +109,9 @@
          log.trace("Begin handleMsg, msgType: " + msgType);
       switch( msgType )
       {
+         case m_acknowledge:
+            // We have to ignore NACK replies because of backwards compatibility
+            break;
          case m_receiveRequest:
             ReceiveRequestMsg rmsg = (ReceiveRequestMsg) msg;
             ReceiveRequest[] messages = rmsg.getMessages();

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/UILServerIL.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/UILServerIL.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/UILServerIL.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE WebOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2;
 
 import java.io.Serializable;
@@ -18,12 +33,14 @@
 import javax.jms.TemporaryTopic;
 import javax.jms.Topic;
 import javax.net.SocketFactory;
+import javax.transaction.xa.Xid;
 
 import org.jboss.logging.Logger;
 import org.jboss.mq.AcknowledgementRequest;
 import org.jboss.mq.Connection;
 import org.jboss.mq.ConnectionToken;
 import org.jboss.mq.DurableSubscriptionID;
+import org.jboss.mq.Recoverable;
 import org.jboss.mq.SpyDestination;
 import org.jboss.mq.SpyMessage;
 import org.jboss.mq.TransactionRequest;
@@ -32,6 +49,7 @@
 import org.jboss.mq.il.uil2.msgs.ConnectionTokenMsg;
 import org.jboss.mq.il.uil2.msgs.EnableConnectionMsg;
 import org.jboss.mq.il.uil2.msgs.GetIDMsg;
+import org.jboss.mq.il.uil2.msgs.RecoverMsg;
 import org.jboss.mq.il.uil2.msgs.TemporaryDestMsg;
 import org.jboss.mq.il.uil2.msgs.AcknowledgementRequestMsg;
 import org.jboss.mq.il.uil2.msgs.AddMsg;
@@ -56,7 +74,7 @@
  * @version $Revision$
  */
 public class UILServerIL
-   implements Cloneable, MsgTypes, Serializable, ServerIL
+   implements Cloneable, MsgTypes, Serializable, ServerIL, Recoverable
 {
    /** @since 1.7, at least jboss-3.2.5, jboss-4.0.0 */
    private static final long serialVersionUID = 853594001646066224L;
@@ -169,12 +187,6 @@
       this.connectPort = connectPort;
    }
 
-   /**
-    * Sets the ConnectionToken attribute of the UILServerIL object
-    *
-    * @param dest           The new ConnectionToken value
-    * @exception Exception  Description of Exception
-    */
    public void setConnectionToken(ConnectionToken dest)
           throws Exception
    {
@@ -182,14 +194,6 @@
       getSocketMgr().sendMessage(msg);
    }
 
-   /**
-    * Sets the Enabled attribute of the UILServerIL object
-    *
-    * @param dc                The new Enabled value
-    * @param enabled           The new Enabled value
-    * @exception JMSException  Description of Exception
-    * @exception Exception     Description of Exception
-    */
    public void setEnabled(ConnectionToken dc, boolean enabled)
           throws JMSException, Exception
    {
@@ -197,12 +201,6 @@
       getSocketMgr().sendMessage(msg);
    }
 
-   /**
-    * Gets the ID attribute of the UILServerIL object
-    *
-    * @return               The ID value
-    * @exception Exception  Description of Exception
-    */
    public String getID()
           throws Exception
    {
@@ -212,14 +210,6 @@
       return id;
    }
 
-   /**
-    * Gets the TemporaryQueue attribute of the UILServerIL object
-    *
-    * @param dc                Description of Parameter
-    * @return                  The TemporaryQueue value
-    * @exception JMSException  Description of Exception
-    * @exception Exception     Description of Exception
-    */
    public TemporaryQueue getTemporaryQueue(ConnectionToken dc)
           throws JMSException, Exception
    {
@@ -229,14 +219,6 @@
       return dest;
    }
 
-   /**
-    * Gets the TemporaryTopic attribute of the UILServerIL object
-    *
-    * @param dc                Description of Parameter
-    * @return                  The TemporaryTopic value
-    * @exception JMSException  Description of Exception
-    * @exception Exception     Description of Exception
-    */
    public TemporaryTopic getTemporaryTopic(ConnectionToken dc)
           throws JMSException, Exception
    {
@@ -246,28 +228,16 @@
       return dest;
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc                Description of Parameter
-    * @param item              Description of Parameter
-    * @exception JMSException  Description of Exception
-    * @exception Exception     Description of Exception
-    */
    public void acknowledge(ConnectionToken dc, AcknowledgementRequest item)
           throws JMSException, Exception
    {
       AcknowledgementRequestMsg msg = new AcknowledgementRequestMsg(item);
-      getSocketMgr().sendMessage(msg);
+      if (item.isAck())
+         getSocketMgr().sendMessage(msg);
+      else
+         getSocketMgr().sendOneWay(msg);
    }
 
-   /**
-    * Adds a feature to the Message attribute of the UILServerIL object
-    *
-    * @param dc             The feature to be added to the Message attribute
-    * @param val            The feature to be added to the Message attribute
-    * @exception Exception  Description of Exception
-    */
    public void addMessage(ConnectionToken dc, SpyMessage val)
           throws Exception
    {
@@ -275,16 +245,6 @@
       getSocketMgr().sendMessage(msg);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc                Description of Parameter
-    * @param dest              Description of Parameter
-    * @param selector          Description of Parameter
-    * @return                  Description of the Returned Value
-    * @exception JMSException  Description of Exception
-    * @exception Exception     Description of Exception
-    */
    public SpyMessage[] browse(ConnectionToken dc, Destination dest, String selector)
           throws JMSException, Exception
    {
@@ -294,13 +254,6 @@
       return msgs;
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param id                Description of Parameter
-    * @exception JMSException  Description of Exception
-    * @exception Exception     Description of Exception
-    */
    public void checkID(String id)
           throws JMSException, Exception
    {
@@ -308,15 +261,6 @@
       getSocketMgr().sendMessage(msg);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param username          Description of Parameter
-    * @param password          Description of Parameter
-    * @return                  Description of the Returned Value
-    * @exception JMSException  Description of Exception
-    * @exception Exception     Description of Exception
-    */
    public String checkUser(String username, String password)
           throws JMSException, Exception
    {
@@ -326,15 +270,6 @@
       return clientID;
    }
 
-   /**
-    * Authenticate the user
-    *
-    * @param username          Description of Parameter
-    * @param password          Description of Parameter
-    * @return                  a sessionID
-    * @exception JMSException  Description of Exception
-    * @exception Exception     Description of Exception
-    */
    public String authenticate(String username, String password)
           throws JMSException, Exception
    {
@@ -344,38 +279,18 @@
       return sessionID;
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @return                                Description of the Returned Value
-    * @exception CloneNotSupportedException  Description of Exception
-    */
    public Object clone()
           throws CloneNotSupportedException
    {
       return super.clone();
    }
 
-   /**
-    * Need to clone because there are instance variables tha can get clobbered.
-    * All Multiple connections can NOT share the same JVMServerIL object
-    *
-    * @return               Description of the Returned Value
-    * @exception Exception  Description of Exception
-    */
    public ServerIL cloneServerIL()
           throws Exception
    {
       return (ServerIL)clone();
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc                Description of Parameter
-    * @exception JMSException  Description of Exception
-    * @exception Exception     Description of Exception
-    */
    public void connectionClosing(ConnectionToken dc)
           throws JMSException, Exception
    {
@@ -390,15 +305,6 @@
       destroyConnection();
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc - the destination connection token
-    * @param destName - the name of the destination
-    * @return  
-    * @exception JMSException  Description of Exception
-    * @exception Exception     Description of Exception
-    */
    public Queue createQueue(ConnectionToken dc, String destName)
           throws JMSException, Exception
    {
@@ -408,15 +314,6 @@
       return dest;
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc - the destination connection token
-    * @param destName - the name of the destination
-    * @return                  Description of the Returned Value
-    * @exception JMSException  Description of Exception
-    * @exception Exception     Description of Exception
-    */
    public Topic createTopic(ConnectionToken dc, String destName)
           throws JMSException, Exception
    {
@@ -426,14 +323,6 @@
       return dest;
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc                Description of Parameter
-    * @param dest              Description of Parameter
-    * @exception JMSException  Description of Exception
-    * @exception Exception     Description of Exception
-    */
    public void deleteTemporaryDestination(ConnectionToken dc, SpyDestination dest)
           throws JMSException, Exception
    {
@@ -441,13 +330,6 @@
       getSocketMgr().sendMessage(msg);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param id                Description of Parameter
-    * @exception JMSException  Description of Exception
-    * @exception Exception     Description of Exception
-    */
    public void destroySubscription(ConnectionToken dc,DurableSubscriptionID id)
           throws JMSException, Exception
    {
@@ -455,13 +337,6 @@
       getSocketMgr().sendMessage(msg);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param clientTime     Description of Parameter
-    * @exception Exception  Description of Exception
-    */
    public void ping(ConnectionToken dc, long clientTime)
           throws Exception
    {
@@ -470,15 +345,6 @@
       getSocketMgr().sendReply(msg);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param subscriberId   Description of Parameter
-    * @param wait           Description of Parameter
-    * @return               Description of the Returned Value
-    * @exception Exception  Description of Exception
-    */
    public SpyMessage receive(ConnectionToken dc, int subscriberId, long wait)
           throws Exception, Exception
    {
@@ -488,14 +354,6 @@
       return reply;
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc                Description of Parameter
-    * @param s                 Description of Parameter
-    * @exception JMSException  Description of Exception
-    * @exception Exception     Description of Exception
-    */
    public void subscribe(ConnectionToken dc, org.jboss.mq.Subscription s)
           throws JMSException, Exception
    {
@@ -503,29 +361,21 @@
       getSocketMgr().sendMessage(msg);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc                Description of Parameter
-    * @param t                 Description of Parameter
-    * @exception JMSException  Description of Exception
-    * @exception Exception     Description of Exception
-    */
-   public void transact(org.jboss.mq.ConnectionToken dc, TransactionRequest t)
+   public void transact(ConnectionToken dc, TransactionRequest t)
           throws JMSException, Exception
    {
       TransactMsg msg = new TransactMsg(t);
       getSocketMgr().sendMessage(msg);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc - the destination connection token
-    * @param subscriptionID    Description of Parameter
-    * @exception JMSException  Description of Exception
-    * @exception Exception     Description of Exception
-    */
+   public Xid[] recover(ConnectionToken dc, int flags) throws Exception
+   {
+      RecoverMsg msg = new RecoverMsg(flags);
+      getSocketMgr().sendMessage(msg);
+      Xid[] reply = msg.getXids();
+      return reply;
+   }
+
    public void unsubscribe(ConnectionToken dc, int subscriptionID)
           throws JMSException, Exception
    {
@@ -541,11 +391,6 @@
       return socketMgr;
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @exception Exception  Description of Exception
-    */
    protected void checkConnection()
           throws Exception
    {

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/UILServerILFactory.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/UILServerILFactory.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/UILServerILFactory.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2;
 
 import java.util.Properties;

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/UILServerILService.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/UILServerILService.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/UILServerILService.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2;
 
 import java.io.IOException;
@@ -36,7 +51,6 @@
 {
    final static int SO_TIMEOUT = 5000;
 
-   private Invoker server;
    /** The security domain name to use with SSL aware socket factories.
     */
    private String securityDomain;
@@ -140,11 +154,12 @@
             socket.setSoTimeout(readTimeout);
             socket.setTcpNoDelay(enableTcpNoDelay);
             socketMgr = new SocketManager(socket);
-            ServerSocketManagerHandler handler = new ServerSocketManagerHandler(server, socketMgr);
+            ServerSocketManagerHandler handler = new ServerSocketManagerHandler(lookupJMSServer(), socketMgr);
             socketMgr.setHandler(handler);
             socketMgr.setBufferSize(bufferSize);
             socketMgr.setChunkSize(chunkSize);
-            socketMgr.start(server.getThreadGroup());
+            Invoker s = lookupJMSServer();
+            socketMgr.start(s.getThreadGroup());
          }
          catch (IOException e)
          {
@@ -168,7 +183,6 @@
    {
       super.startService();
       running = true;
-      this.server = lookupJMSServer();
 
       // Use the default javax.net.ServerSocketFactory if none was set
       if (serverSocketFactory == null)
@@ -204,7 +218,7 @@
 
       InetAddress socketAddress = serverSocket.getInetAddress();
       log.info("JBossMQ UIL service available at : " + socketAddress + ":" + serverSocket.getLocalPort());
-      acceptThread = new Thread(server.getThreadGroup(), this, "UILServerILService Accept Thread");
+      acceptThread = new Thread(lookupJMSServer().getThreadGroup(), this, "UILServerILService Accept Thread");
       acceptThread.start();
 
       /* We need to check the socketAddress against "0.0.0.0/0.0.0.0"

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/UILServerILServiceMBean.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/UILServerILServiceMBean.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/UILServerILServiceMBean.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2;
 
 /**

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/AcknowledgementRequestMsg.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/AcknowledgementRequestMsg.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/AcknowledgementRequestMsg.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE WebOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2.msgs;
 
 import java.io.ObjectOutputStream;

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/AddMsg.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/AddMsg.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/AddMsg.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE WebOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2.msgs;
 
 import java.io.ObjectOutputStream;

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/BaseMsg.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/BaseMsg.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/BaseMsg.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE WebOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2.msgs;
 
 import java.io.ObjectOutputStream;
@@ -130,6 +145,9 @@
          case MsgTypes.m_transact:
             msg = new TransactMsg();
             break;
+         case MsgTypes.m_recover:
+            msg = new RecoverMsg();
+            break;
          case MsgTypes.m_unsubscribe:
             msg = new UnsubscribeMsg();
             break;
@@ -217,6 +235,9 @@
          case MsgTypes.m_transact:
             msgTypeString = "m_transact";
             break;
+         case MsgTypes.m_recover:
+            msgTypeString = "m_recover";
+            break;
          case MsgTypes.m_unsubscribe:
             msgTypeString = "m_unsubscribe";
             break;

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/BrowseMsg.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/BrowseMsg.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/BrowseMsg.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE WebOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2.msgs;
 
 import java.io.ObjectOutputStream;

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/CheckIDMsg.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/CheckIDMsg.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/CheckIDMsg.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE WebOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2.msgs;
 
 import java.io.IOException;

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/CheckUserMsg.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/CheckUserMsg.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/CheckUserMsg.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE WebOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2.msgs;
 
 import java.io.IOException;

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/CloseMsg.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/CloseMsg.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/CloseMsg.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE WebOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2.msgs;
 
 /**

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/ConnectionTokenMsg.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/ConnectionTokenMsg.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/ConnectionTokenMsg.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE WebOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2.msgs;
 
 import java.io.ObjectOutputStream;

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/CreateDestMsg.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/CreateDestMsg.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/CreateDestMsg.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE WebOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2.msgs;
 
 import java.io.ObjectOutputStream;

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/DeleteSubscriptionMsg.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/DeleteSubscriptionMsg.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/DeleteSubscriptionMsg.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE WebOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2.msgs;
 
 import java.io.ObjectOutputStream;

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/DeleteTemporaryDestMsg.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/DeleteTemporaryDestMsg.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/DeleteTemporaryDestMsg.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE WebOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2.msgs;
 
 import java.io.ObjectOutputStream;

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/DynCircularBuffer.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/DynCircularBuffer.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/DynCircularBuffer.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE WebOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2.msgs;
 
 /** A circular byte[] buffer capable of expanding its capacity

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/EnableConnectionMsg.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/EnableConnectionMsg.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/EnableConnectionMsg.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE WebOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2.msgs;
 
 import java.io.IOException;

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/GetIDMsg.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/GetIDMsg.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/GetIDMsg.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE WebOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2.msgs;
 
 import java.io.ObjectOutputStream;

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/MsgTypes.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/MsgTypes.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/MsgTypes.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE WebOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2.msgs;
 
 /**
@@ -36,5 +51,5 @@
    final static int m_close = 23;
    final static int m_pong = 24;
    final static int m_receiveRequest = 25;
-
+   final static int m_recover = 26;
 }

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/PingMsg.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/PingMsg.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/PingMsg.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE WebOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2.msgs;
 
 import java.io.ObjectInputStream;

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/ReceiveMsg.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/ReceiveMsg.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/ReceiveMsg.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE WebOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2.msgs;
 
 import java.io.IOException;

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/ReceiveRequestMsg.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/ReceiveRequestMsg.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/ReceiveRequestMsg.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE WebOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2.msgs;
 
 import java.io.ObjectOutputStream;

Copied: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/RecoverMsg.java (from rev 55341, branches/JBoss_4_0_3_SP1_JBAS3259/messaging/src/main/org/jboss/mq/il/uil2/msgs/RecoverMsg.java)

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/SubscribeMsg.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/SubscribeMsg.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/SubscribeMsg.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE WebOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2.msgs;
 
 import java.io.IOException;

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/TemporaryDestMsg.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/TemporaryDestMsg.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/TemporaryDestMsg.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE WebOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2.msgs;
 
 import java.io.IOException;

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/TransactMsg.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/TransactMsg.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/TransactMsg.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE WebOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2.msgs;
 
 import java.io.IOException;

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/UnsubscribeMsg.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/UnsubscribeMsg.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/il/uil2/msgs/UnsubscribeMsg.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE WebOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.uil2.msgs;
 
 import java.io.IOException;

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/pm/Tx.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/pm/Tx.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/pm/Tx.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,8 +1,23 @@
 /*
-* JBoss, the OpenSource J2EE webOS
+* 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.
 *
-* Distributable under LGPL license.
-* See terms of license at gnu.org.
+* 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.mq.pm;
 
@@ -10,6 +25,7 @@
 import java.util.ArrayList;
 
 import javax.jms.JMSException;
+import javax.transaction.xa.Xid;
 
 /**
  * A transaction
@@ -19,8 +35,6 @@
  */
 public class Tx implements Comparable, Externalizable
 {
-   // Constants -----------------------------------------------------
-
    /** The serialVersionUID */
    static final long serialVersionUID = -5428592493990463362L;  
 
@@ -28,15 +42,24 @@
    private static final int OPEN = 0;
    /** Transaction ended */
    private static final int ENDED = 2;
+
+   /** Restore unknown */
+   public static final int UNKNOWN = 0;
+
+   /** Restore addition */
+   public static final int ADD = 1;
+
+   /** Restore remove */
+   public static final int REMOVE = -1;
    
-   // Attributes ----------------------------------------------------
-
    /** The transaction value */
    long value = 0;
    
    /** Whether the transaction has been persisted */
    boolean persisted = false;
 
+   transient Xid xid;
+   
    /** List of Runnable tasks */
    transient ArrayList postCommitTasks;
    /** List of Runnable tasks */
@@ -48,10 +71,6 @@
    /** The lock */
    transient Object lock = new Object();
    
-   // Static --------------------------------------------------------
-   
-   // Constructors --------------------------------------------------
-   
    /**
     * Create a new Tx for externailzation
     */
@@ -69,8 +88,6 @@
       this.value = value;
    }
    
-   // Public --------------------------------------------------------
-   
    /**
     * Set the value
     *
@@ -92,6 +109,26 @@
    }
 
    /**
+    * Get the xid.
+    * 
+    * @return the xid.
+    */
+   public Xid getXid()
+   {
+      return xid;
+   }
+
+   /**
+    * Set the xid.
+    * 
+    * @param xid the xid.
+    */
+   public void setXid(Xid xid)
+   {
+      this.xid = xid;
+   }
+
+   /**
     * Get whether the transaction has been persisted
     *
     * @return true when persisted
@@ -126,15 +163,11 @@
       return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1));
    }
    
-   // Comparable implementation -------------------------------------
-   
    public int compareTo(Object o)
    {
       return compareTo((Tx) o);
    }
    
-   // Externalizable implementation ---------------------------------
-   
    public void readExternal(java.io.ObjectInput in) throws java.io.IOException
    {
       value = in.readLong();
@@ -145,8 +178,6 @@
       out.writeLong(value);
    }
    
-   // Object overrides ----------------------------------------------
-   
    public String toString()
    {
       return String.valueOf(value);
@@ -156,8 +187,6 @@
    {
       return (int) (value ^ (value >> 32));
    }
-   
-   // Package protected ---------------------------------------------
 
    /**
     * Commit the transaction
@@ -260,10 +289,4 @@
          postRollbackTasks.add(task);
       }
    }
-   
-   // Protected -----------------------------------------------------
-   
-   // Private -------------------------------------------------------
-   
-   // Inner classes -------------------------------------------------
 }
\ No newline at end of file

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/pm/TxManager.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/pm/TxManager.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/pm/TxManager.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,16 +1,40 @@
 /*
- * JBossMQ, the OpenSource JMS implementation
- * 
- * Distributable under LGPL license. See terms of license at gnu.org.
- */
+* 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.mq.pm;
 
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
 import javax.jms.JMSException;
+import javax.transaction.xa.Xid;
 
+import org.jboss.logging.Logger;
 import org.jboss.mq.ConnectionToken;
+import org.jboss.mq.Recoverable;
 import org.jboss.mq.SpyJMSException;
 
 import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap;
+import EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArraySet;
 
 /**
  * This class allows provides the base for user supplied persistence packages.
@@ -20,37 +44,34 @@
  * @author <a href="mailto:adrian at jboss.org">Adrian Brock</a>
  * @version $Revision$
  */
-public class TxManager
+public class TxManager implements Recoverable
 {
-   // Constants -----------------------------------------------------
+   /** The log */
+   private static final Logger log = Logger.getLogger(TxManager.class);
    
-   // Attributes ----------------------------------------------------
-
    /** The persistence manager */
    PersistenceManager persistenceManager;
    
    /** Maps Global transactions to local transactions */
    ConcurrentHashMap globalToLocal = new ConcurrentHashMap();
    
+   /** Prepared Transactions Map<Xid, PreparedInfo<Tx>> */
+   ConcurrentHashMap prepared = new ConcurrentHashMap();
+   
    /**
     * Create a new TxManager
     *
     * @param pm the persistence manager
     */
-   // Static --------------------------------------------------------
-   
-   // Constructors --------------------------------------------------
-
    public TxManager(PersistenceManager pm)
    {
       persistenceManager = pm;
    }
-   
-   // Public --------------------------------------------------------
 
    /**
 	 * Return the local transaction id for a distributed transaction id.
 	 * 
+     * @deprecated
 	 * @param dc the connection
 	 * @param xid the transaction id
 	 * @return The Prepared transaction
@@ -86,10 +107,48 @@
 	 */
    public final void commitTx(Tx txId) throws JMSException
    {
+      boolean trace = log.isTraceEnabled();
+      if (trace)
+         log.trace("Commit branch=" + txId.longValue());
       txId.commit(persistenceManager);
    }
 
    /**
+    * Commit the transaction to the persistent store.
+    *
+    * @param dc the connection token
+    * @param xid the transaction
+    * @exception JMSException for any error
+    */
+   public final void commitTx(ConnectionToken dc, Object xid) throws JMSException
+   {
+      boolean trace = log.isTraceEnabled();
+      GlobalXID gxid = new GlobalXID(dc, xid);
+      Tx txid = (Tx) globalToLocal.get(gxid);
+      if (txid == null)
+      {
+         PreparedInfo preparedInfo = (PreparedInfo) prepared.get(xid);
+         if (preparedInfo == null)
+            throw new SpyJMSException("Transaction does not exist from: " + dc.getClientID() + " xid=" + xid);
+         Set txids = preparedInfo.getTxids();
+         for (Iterator i = txids.iterator(); i.hasNext();)
+         {
+            txid = (Tx) i.next();
+            if (trace)
+               log.trace("Commit xid=" + xid + " branch=" + txid.longValue());
+            txid.commit(persistenceManager);
+         }
+         prepared.remove(xid);
+      }
+      else
+      {
+         if (trace)
+            log.trace("Commit xid=" + xid + " branch=" + txid.longValue());
+         txid.commit(persistenceManager);
+      }
+   }
+   
+   /**
     * Add an operation for after a commit
     *
     * @param txId the transaction
@@ -115,10 +174,48 @@
 	 */
    public void rollbackTx(Tx txId) throws JMSException
    {
+      boolean trace = log.isTraceEnabled();
+      if (trace)
+         log.trace("Rollback branch=" + txId.longValue());
       txId.rollback(persistenceManager);
    }
 
    /**
+    * Rollback the transaction
+    *
+    * @param dc the connection token
+    * @param xid the transaction
+    * @exception JMSException for any error
+    */
+   public final void rollbackTx(ConnectionToken dc, Object xid) throws JMSException
+   {
+      boolean trace = log.isTraceEnabled();
+      GlobalXID gxid = new GlobalXID(dc, xid);
+      Tx txid = (Tx) globalToLocal.get(gxid);
+      if (txid == null)
+      {
+         PreparedInfo preparedInfo = (PreparedInfo) prepared.get(xid);
+         if (preparedInfo == null)
+            throw new SpyJMSException("Transaction does not exist from: " + dc.getClientID() + " xid=" + xid);
+         Set txids = preparedInfo.getTxids();
+         for (Iterator i = txids.iterator(); i.hasNext();)
+         {
+            txid = (Tx) i.next();
+            if (trace)
+               log.trace("Rolling back xid=" + xid + " branch=" + txid.longValue());
+            txid.rollback(persistenceManager);
+         }
+         prepared.remove(xid);
+      }
+      else
+      {
+         if (trace)
+            log.trace("Rolling back xid=" + xid + " branch=" + txid.longValue());
+         txid.rollback(persistenceManager);
+      }
+   }
+
+   /**
     * Add an operation for after a rollback
     *
     * @param txId the transaction
@@ -145,12 +242,13 @@
 	 */
    public Tx createTx(ConnectionToken dc, Object xid) throws JMSException
    {
-
       GlobalXID gxid = new GlobalXID(dc, xid);
       if (globalToLocal.containsKey(gxid))
          throw new SpyJMSException("Duplicate transaction from: " + dc.getClientID() + " xid=" + xid);
 
       Tx txId = createTx();
+      if (xid != null && xid instanceof Xid)
+         txId.setXid((Xid) xid);
       globalToLocal.put(gxid, txId);
 
       //Tasks to remove the global to local mappings on commit/rollback
@@ -159,15 +257,77 @@
 
       return txId;
    }
+
+   /**
+    * Restore a prepared transaction
+    * 
+    * @param txId the transaction id
+    * @throws JMSException for any error
+    */
+   public void restoreTx(Tx txId) throws JMSException
+   {
+      addPreparedTx(txId, txId.getXid(), true);
+   }
+
+   /**
+    * Add a prepared transactions
+    * 
+    * @param txId the transaction id
+    * @param xid the xid
+    * @param inDoubt whether it is in doubt
+    * @throws JMSException for any error
+    */
+   void addPreparedTx(Tx txId, Xid xid, boolean inDoubt) throws JMSException
+   {
+      PreparedInfo preparedInfo = (PreparedInfo) prepared.get(xid);
+      if (preparedInfo == null)
+      {
+         preparedInfo = new PreparedInfo(xid, false);
+         prepared.put(xid, preparedInfo);
+      }
+      preparedInfo.add(txId);
+      if (inDoubt)
+         preparedInfo.setInDoubt(true);
+   }
    
-   // Package protected ---------------------------------------------
+   /**
+    * Mark the transaction branch as prepared
+    * 
+    * @param dc the connection token
+    * @param xid the xid
+    * @param txId the transaction
+    * @throws JMSException for any error
+    */
+   public void markPrepared(ConnectionToken dc, Object xid, Tx txId) throws JMSException
+   {
+      try
+      {
+         if (xid instanceof Xid)
+            addPreparedTx(txId, (Xid) xid, false);
+      }
+      catch (Throwable t)
+      {
+         SpyJMSException.rethrowAsJMSException("Error marking transaction as prepared xid=" + xid + " tx=" + txId, t);
+      }
+   }
+
+   public Xid[] recover(ConnectionToken dc, int flags) throws Exception
+   {
+      Set preparedXids = prepared.keySet();
+      Xid[] xids = (Xid[]) preparedXids.toArray(new Xid[preparedXids.size()]);
+      return xids;
+   }
    
-   // Protected -----------------------------------------------------
+   /**
+    * Get the prepared transactions
+    * 
+    * @return
+    */
+   public Map getPreparedTransactions()
+   {
+      return prepared;
+   }
    
-   // Private -------------------------------------------------------
-   
-   // Inner classes -------------------------------------------------
-   
    /**
 	 * A global transaction
 	 */
@@ -202,7 +362,118 @@
 
       public void run()
       {
-         globalToLocal.remove(this);
+         Tx txId = (Tx) globalToLocal.remove(this);
+         // Tidyup the prepared transactions
+         if (txId != null)
+         {
+            PreparedInfo preparedInfo = (PreparedInfo) prepared.get(xid);
+            if (preparedInfo != null)
+            {
+               preparedInfo.remove(txId);
+               if (preparedInfo.isEmpty())
+                  prepared.remove(xid);
+            }
+         }
       }
    }
+
+   /**
+    * Information about a prepared global transaction
+    * 
+    * @author <a href="adrian at jboss.com">Adrian Brock</a>
+    * @version $Revision$
+    */
+   public static class PreparedInfo
+   {
+      /** The XID */
+      private Xid xid;
+      
+      /** Whether the transaction is in doubt */
+      private boolean inDoubt;
+      
+      /** The local transaction branches */
+      private Set txids = new CopyOnWriteArraySet();
+
+      /**
+       * Create a new PreparedInfo.
+       * 
+       * @param xid the xid
+       * @param indoubt whether the transaction is in doubt
+       */
+      public PreparedInfo(Xid xid, boolean inDoubt)
+      {
+         this.xid = xid;
+         this.inDoubt = inDoubt;
+      }
+
+      /**
+       * Whether the transaction is in doubt
+       * 
+       * @return true when in doubt
+       */
+      public boolean isInDoubt()
+      {
+         return inDoubt;
+      }
+      
+      /**
+       * Set the in doubt
+       * 
+       * @param inDoubt the in doubt value
+       */
+      public void setInDoubt(boolean inDoubt)
+      {
+         this.inDoubt = inDoubt;
+      }
+      
+      /**
+       * Get the XID
+       * 
+       * @return
+       */
+      public Xid getXid()
+      {
+         return xid;
+      }
+
+      /**
+       * Get the local branches
+       * 
+       * @return the local branches
+       */
+      public Set getTxids()
+      {
+         return txids;
+      }
+      
+      /**
+       * Add a local branch
+       * 
+       * @param txid the local branch
+       */
+      public void add(Tx txid)
+      {
+         txids.add(txid);
+      }
+      
+      /**
+       * Remove a local branch
+       * 
+       * @param txid the local branch
+       */
+      public void remove(Tx txid)
+      {
+         txids.remove(txid);
+      }
+      
+      /**
+       * Whether there are no local branches
+       * 
+       * @return true when there no local branches
+       */
+      public boolean isEmpty()
+      {
+         return txids.isEmpty();
+      }
+   }
 }
\ No newline at end of file

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/pm/jdbc2/PersistenceManager.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/pm/jdbc2/PersistenceManager.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/pm/jdbc2/PersistenceManager.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBossMQ, the OpenSource JMS implementation
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.pm.jdbc2;
 
 import java.io.ByteArrayInputStream;
@@ -16,20 +31,30 @@
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
 import java.util.Properties;
 
 import javax.jms.JMSException;
+import javax.management.AttributeNotFoundException;
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanException;
 import javax.management.ObjectName;
+import javax.management.ReflectionException;
 import javax.naming.InitialContext;
+import javax.naming.NamingException;
 import javax.sql.DataSource;
 import javax.transaction.Status;
 import javax.transaction.Transaction;
 import javax.transaction.TransactionManager;
+import javax.transaction.xa.Xid;
 
 import org.jboss.mq.SpyDestination;
 import org.jboss.mq.SpyJMSException;
 import org.jboss.mq.SpyMessage;
 import org.jboss.mq.SpyTopic;
+import org.jboss.mq.pm.CacheStore;
 import org.jboss.mq.pm.Tx;
 import org.jboss.mq.pm.TxManager;
 import org.jboss.mq.server.JMSDestination;
@@ -45,16 +70,13 @@
  * This class manages all persistence related services for JDBC based
  * persistence.
  *
- * @jmx:mbean extends="org.jboss.system.ServiceMBean, org.jboss.mq.pm.PersistenceManagerMBean, org.jboss.mq.pm.CacheStoreMBean"
- *
  * @author Jayesh Parayali (jayeshpk1 at yahoo.com)
  * @author Hiram Chirino (cojonudo14 at hotmail.com)
- *
- *  @version $Revision$
+ * @author Adrian Brock (adrian at jboss.com)
+ * @version $Revision$
  */
-public class PersistenceManager
-   extends ServiceMBeanSupport
-   implements PersistenceManagerMBean, org.jboss.mq.pm.PersistenceManager, org.jboss.mq.pm.CacheStore
+public class PersistenceManager extends ServiceMBeanSupport
+   implements PersistenceManagerMBean, org.jboss.mq.pm.PersistenceManager, CacheStore
 {
 
    /////////////////////////////////////////////////////////////////////////////////
@@ -80,6 +102,9 @@
    
    /** The recovery retries */
    private int recoveryRetries = 0;
+   
+   /** The recover messages chunk  */
+   private int recoverMessagesChunk = 0;
 
    /////////////////////////////////////////////////////////////////////////////////
    //
@@ -88,17 +113,26 @@
    /////////////////////////////////////////////////////////////////////////////////
 
    protected String UPDATE_MARKED_MESSAGES = "UPDATE JMS_MESSAGES SET TXID=?, TXOP=? WHERE TXOP=?";
+   protected String UPDATE_MARKED_MESSAGES_XARECOVERY = "UPDATE JMS_MESSAGES SET TXID=?, TXOP=? WHERE TXOP=? AND TXID NOT IN (SELECT TXID FROM JMS_TRANSACTIONS WHERE XID IS NOT NULL)";
    protected String UPDATE_MARKED_MESSAGES_WITH_TX = "UPDATE JMS_MESSAGES SET TXID=?, TXOP=? WHERE TXOP=? AND TXID=?";
    protected String DELETE_MARKED_MESSAGES_WITH_TX =
       "DELETE FROM JMS_MESSAGES WHERE TXID IN (SELECT TXID FROM JMS_TRANSACTIONS) AND TXOP=?";
+   protected String DELETE_MARKED_MESSAGES_WITH_TX_XARECOVERY =
+      "DELETE FROM JMS_MESSAGES WHERE TXID IN (SELECT TXID FROM JMS_TRANSACTIONS WHERE XID = NULL) AND TXOP=?";
    protected String DELETE_TX = "DELETE FROM JMS_TRANSACTIONS WHERE TXID = ?";
    protected String DELETE_MARKED_MESSAGES = "DELETE FROM JMS_MESSAGES WHERE TXID=? AND TXOP=?";
    protected String DELETE_TEMPORARY_MESSAGES = "DELETE FROM JMS_MESSAGES WHERE TXOP = 'T'";
    protected String INSERT_TX = "INSERT INTO JMS_TRANSACTIONS (TXID) values(?)";
+   protected String INSERT_TX_XARECOVERY = "INSERT INTO JMS_TRANSACTIONS (TXID, XID) values(?, ?)";
    protected String DELETE_ALL_TX = "DELETE FROM JMS_TRANSACTIONS";
+   protected String DELETE_ALL_TX_XARECOVERY = "DELETE FROM JMS_TRANSACTIONS WHERE XID = NULL";
    protected String SELECT_MAX_TX = "SELECT MAX(TXID) FROM (SELECT MAX(TXID) FROM JMS_TRANSACTIONS UNION SELECT MAX(TXID) FROM JMS_MESSAGES)";
+   protected String SELECT_ALL_TX_XARECOVERY = "SELECT TXID, XID FROM JMS_TRANSACTIONS";
    protected String SELECT_MESSAGES_IN_DEST = "SELECT MESSAGEID, MESSAGEBLOB FROM JMS_MESSAGES WHERE DESTINATION=?";
+   protected String SELECT_MESSAGES_IN_DEST_XARECOVERY = "SELECT MESSAGEID, MESSAGEBLOB, TXID, TXOP FROM JMS_MESSAGES WHERE DESTINATION=?";
+   protected String SELECT_MESSAGE_KEYS_IN_DEST = "SELECT MESSAGEID FROM JMS_MESSAGES WHERE DESTINATION=?";
    protected String SELECT_MESSAGE = "SELECT MESSAGEID, MESSAGEBLOB FROM JMS_MESSAGES WHERE MESSAGEID=? AND DESTINATION=?";
+   protected String SELECT_MESSAGE_XARECOVERY = "SELECT MESSAGEID, MESSAGEBLOB, TXID, TXOP FROM JMS_MESSAGES WHERE MESSAGEID=? AND DESTINATION=?";
    protected String INSERT_MESSAGE =
       "INSERT INTO JMS_MESSAGES (MESSAGEID, DESTINATION, MESSAGEBLOB, TXID, TXOP) VALUES(?,?,?,?,?)";
    protected String MARK_MESSAGE = "UPDATE JMS_MESSAGES SET TXID=?, TXOP=? WHERE MESSAGEID=? AND DESTINATION=?";
@@ -111,6 +145,7 @@
    protected String CREATE_IDX_MESSAGE_TXOP_TXID = "CREATE INDEX JMS_MESSAGES_TXOP_TXID ON JMS_MESSAGES (TXOP, TXID)";
    protected String CREATE_IDX_MESSAGE_DESTINATION = "CREATE INDEX JMS_MESSAGES_DESTINATION ON JMS_MESSAGES (DESTINATION)";
    protected String CREATE_TX_TABLE = "CREATE TABLE JMS_TRANSACTIONS ( TXID INTEGER, PRIMARY KEY (TXID) )";
+   protected String CREATE_TX_TABLE_XARECOVERY = "CREATE TABLE JMS_TRANSACTIONS ( TXID INTEGER, XID OBJECT, PRIMARY KEY (TXID) )";
 
    protected static final int OBJECT_BLOB = 0;
    protected static final int BYTES_BLOB = 1;
@@ -122,6 +157,8 @@
 
    protected  int connectionRetryAttempts = 5;
 
+   protected boolean xaRecovery = false;
+   
    /////////////////////////////////////////////////////////////////////////////////
    //
    // Constructor.
@@ -143,7 +180,6 @@
 
       void startTX() throws JMSException
       {
-         //log.debug("starting a new TM transaction");
          try
          {
             // Thread arriving must be clean (jboss doesn't set the thread
@@ -171,7 +207,6 @@
 
       void setRollbackOnly() throws JMSException
       {
-         //log.debug("rolling back a TM transaction");
          try
          {
             tm.setRollbackOnly();
@@ -184,7 +219,6 @@
 
       void endTX() throws JMSException
       {
-         //log.debug("ending TM transaction.");
          try
          {
             if (tm.getStatus() == Status.STATUS_MARKED_ROLLBACK)
@@ -306,14 +340,17 @@
                }
             }
 
+            String createTxTable = CREATE_TX_TABLE;
+            if (xaRecovery)
+               createTxTable = CREATE_TX_TABLE_XARECOVERY;
             try
             {
-               stmt = c.prepareStatement(CREATE_TX_TABLE);
+               stmt = c.prepareStatement(createTxTable);
                stmt.executeUpdate();
             }
             catch (SQLException e)
             {
-               log.debug("Could not create table with SQL: " + CREATE_TX_TABLE, e);
+               log.debug("Could not create table with SQL: " + createTxTable, e);
             }
             finally
             {
@@ -384,38 +421,72 @@
          rs = stmt.executeQuery();
          if (rs.next())
             nextTransactionId.set(rs.getLong(1) + 1);
+         rs.close();
+         rs = null;
          stmt.close();
+         stmt = null;
 
          // Delete all the temporary messages.
          stmt = c.prepareStatement(DELETE_TEMPORARY_MESSAGES);
          stmt.executeUpdate();
          stmt.close();
+         stmt = null;
 
          // Delete all the messages that were added but thier tx's were not commited.
-         stmt = c.prepareStatement(DELETE_MARKED_MESSAGES_WITH_TX);
+         String deleteMarkedMessagesWithTx = DELETE_MARKED_MESSAGES_WITH_TX;
+         if (xaRecovery)
+            deleteMarkedMessagesWithTx = DELETE_MARKED_MESSAGES_WITH_TX_XARECOVERY;
+         stmt = c.prepareStatement(deleteMarkedMessagesWithTx);
          stmt.setString(1, "A");
          stmt.executeUpdate();
          stmt.close();
+         stmt = null;
 
          // Restore all the messages that were removed but their tx's were not commited.
-         stmt = c.prepareStatement(UPDATE_MARKED_MESSAGES);
+         String updateMarkedMessages = UPDATE_MARKED_MESSAGES;
+         if (xaRecovery)
+            updateMarkedMessages = UPDATE_MARKED_MESSAGES_XARECOVERY;
+         stmt = c.prepareStatement(updateMarkedMessages);
          stmt.setNull(1, java.sql.Types.BIGINT);
          stmt.setString(2, "A");
          stmt.setString(3, "D");
          stmt.executeUpdate();
          stmt.close();
+         stmt = null;
 
          // Now recovery is complete, clear the transaction table.
-         stmt = c.prepareStatement(DELETE_ALL_TX);
+         String deleteAllTx = DELETE_ALL_TX;
+         if (xaRecovery)
+            deleteAllTx = DELETE_ALL_TX_XARECOVERY;
+         stmt = c.prepareStatement(deleteAllTx);
          stmt.execute();
          stmt.close();
+         stmt = null;
+
+         // If we are doing XARecovery restore the prepared transactions
+         if (xaRecovery)
+         {
+            stmt = c.prepareStatement(SELECT_ALL_TX_XARECOVERY);
+            rs = stmt.executeQuery();
+            while (rs.next())
+            {
+               long txid = rs.getLong(1);
+               Xid xid = extractXid(rs, 2);
+               Tx tx = new Tx(txid);
+               tx.setXid(xid);
+               tx.checkPersisted();
+               txManager.restoreTx(tx);
+            }
+            rs.close();
+            rs = null;
+            stmt.close();
+            stmt = null;
+         }
       }
-      catch (SQLException e)
+      catch (Exception e)
       {
          tms.setRollbackOnly();
-         throw new SpyJMSException(
-            "Could not resolve uncommited transactions.  Message recovery may not be accurate",
-            e);
+         throw new SpyJMSException("Could not resolve uncommited transactions.  Message recovery may not be accurate", e);
       }
       finally
       {
@@ -502,32 +573,129 @@
    
    synchronized protected void internalRestoreQueue(JMSDestination jmsDest, SpyDestination dest) throws JMSException
    {
+      // Work out the prepared transactions
+      Map prepared = null;
+      if (xaRecovery)
+      {
+         prepared = new HashMap();
+         Map map = txManager.getPreparedTransactions();
+         for (Iterator i = map.values().iterator(); i.hasNext();)
+         {
+            TxManager.PreparedInfo info = (TxManager.PreparedInfo) i.next();
+            for (Iterator j = info.getTxids().iterator(); j.hasNext();)
+            {
+               Tx tx = (Tx) j.next();
+               prepared.put(new Long(tx.longValue()), tx);
+            }
+         }
+      }
+      
       TransactionManagerStrategy tms = new TransactionManagerStrategy();
       tms.startTX();
       Connection c = null;
       PreparedStatement stmt = null;
+      PreparedStatement stmt2 = null; 
       ResultSet rs = null;
       boolean threadWasInterrupted = Thread.interrupted();
       try
       {
-
+         String selectMessagesInDest = SELECT_MESSAGES_IN_DEST;
+         String selectMessage = SELECT_MESSAGE;
+         if (xaRecovery)
+         {
+            selectMessagesInDest = SELECT_MESSAGES_IN_DEST_XARECOVERY;
+            selectMessage = SELECT_MESSAGE_XARECOVERY;
+         }
          c = this.getConnection();
-         stmt = c.prepareStatement(SELECT_MESSAGES_IN_DEST);
+         if (recoverMessagesChunk == 0)
+            stmt = c.prepareStatement(selectMessagesInDest);
+         else
+         {
+            stmt = c.prepareStatement(SELECT_MESSAGE_KEYS_IN_DEST);
+            stmt2 = c.prepareStatement(selectMessage);
+         }
          stmt.setString(1, dest.toString());
 
+         long txid = 0;
+         String txop = null;
          rs = stmt.executeQuery();
          int counter = 0;
+         int recovery = 0;
          while (rs.next())
          {
-            SpyMessage message = extractMessage(rs);
+            long msgid = rs.getLong(1);
+            SpyMessage message = null;
+            if (recoverMessagesChunk == 0)
+            {
+               message = extractMessage(rs);
+               if (xaRecovery)
+               {
+                  txid = rs.getLong(3);
+                  txop = rs.getString(4);
+               }
+            }
+            else
+            {
+               ResultSet rs2 = null;
+               try
+               {
+                  stmt2.setLong(1, msgid);
+                  stmt2.setString(2, dest.toString());
+                  rs2 = stmt2.executeQuery();
+                  if (rs2.next())
+                  {
+                     message = extractMessage(rs2);
+                     if (xaRecovery)
+                     {
+                        txid = rs.getLong(3);
+                        txop = rs.getString(4);
+                     }
+                  }
+                  else
+                     log.warn("Failed to find message msgid=" + msgid +" dest=" + dest);
+               }
+               finally
+               {
+                  if (rs2 != null)
+                  {
+                     try
+                     {
+                        rs2.close();
+                     }
+                     catch (Exception ignored)
+                     {
+                     }
+                  }
+               }
+            }
             // The durable subscription is not serialized
             if (dest instanceof SpyTopic)
                message.header.durableSubscriberID = ((SpyTopic) dest).getDurableSubscriptionID();
-            jmsDest.restoreMessage(message);
+
+            if (xaRecovery == false || txid == 0 || txop == null)
+               jmsDest.restoreMessage(message);
+            else
+            {
+               Tx tx = (Tx) prepared.get(new Long(txid));
+               if (tx == null)
+                  jmsDest.restoreMessage(message);
+               else if ("A".equals(txop))
+               {
+                  jmsDest.restoreMessage(message, tx, Tx.ADD);
+                  recovery++;
+               }
+               else if ("D".equals(txop))
+               {
+                  jmsDest.restoreMessage(message, tx, Tx.REMOVE);
+                  recovery++;
+               }
+               else
+                  throw new IllegalStateException("Unknown txop=" + txop + " for msg=" + msgid + " dest=" + dest);
+            }
             counter++;
          }
 
-         log.debug("Restored " + counter + " message(s) to: " + dest);
+         log.debug("Restored " + counter + " message(s) to: " + dest + " " + recovery + " need recovery.");
       }
       catch (IOException e)
       {
@@ -543,21 +711,24 @@
       {
          try
          {
-            rs.close();
+            if (rs != null)
+               rs.close();
          }
          catch (Throwable ignore)
          {
          }
          try
          {
-            stmt.close();
+            if (stmt != null)
+               stmt.close();
          }
          catch (Throwable ignore)
          {
          }
          try
          {
-            c.close();
+            if (c != null)
+               c.close();
          }
          catch (Throwable ignore)
          {
@@ -617,6 +788,42 @@
       }
    }
 
+   Xid extractXid(ResultSet rs, int column) throws SQLException, IOException, ClassNotFoundException
+   {
+      try
+      {
+         Xid xid = null;
+
+         if (blobType == OBJECT_BLOB)
+         {
+            xid = (Xid) rs.getObject(column);
+         }
+         else if (blobType == BYTES_BLOB)
+         {
+            byte[] st = rs.getBytes(column);
+            ByteArrayInputStream baip = new ByteArrayInputStream(st);
+            ObjectInputStream ois = new ObjectInputStream(baip);
+            xid = (Xid) ois.readObject();
+         }
+         else if (blobType == BINARYSTREAM_BLOB)
+         {
+            ObjectInputStream ois = new ObjectInputStream(rs.getBinaryStream(column));
+            xid = (Xid) ois.readObject();
+         }
+         else if (blobType == BLOB_BLOB)
+         {
+            ObjectInputStream ois = new ObjectInputStream(rs.getBlob(column).getBinaryStream());
+            xid = (Xid) ois.readObject();
+         }
+
+         return xid;
+      }
+      catch (StreamCorruptedException e)
+      {
+         throw new IOException("Could not load the message: " + e);
+      }
+   }
+
    /////////////////////////////////////////////////////////////////////////////////
    //
    // TX Commit
@@ -648,7 +855,8 @@
       {
          try
          {
-            c.close();
+            if (c != null)
+               c.close();
          }
          catch (Throwable ignore)
          {
@@ -675,7 +883,8 @@
       {
          try
          {
-            stmt.close();
+            if (stmt != null)
+               stmt.close();
          }
          catch (Throwable e)
          {
@@ -683,20 +892,32 @@
       }
    }
 
-   public void addTXRecord(Connection c, long txid) throws SQLException
+   public void addTXRecord(Connection c, Tx txid) throws SQLException, IOException
    {
       PreparedStatement stmt = null;
       try
       {
-         stmt = c.prepareStatement(INSERT_TX);
-         stmt.setLong(1, txid);
+         String insertTx = INSERT_TX;
+         if (xaRecovery)
+            insertTx = INSERT_TX_XARECOVERY;
+         stmt = c.prepareStatement(insertTx);
+         stmt.setLong(1, txid.longValue());
+         if (xaRecovery)
+         {
+            Xid xid = txid.getXid();
+            if (xid != null)
+               setBlob(stmt, 2, xid);
+            else
+               stmt.setNull(2, java.sql.Types.BLOB);
+         }
          stmt.executeUpdate();
       }
       finally
       {
          try
          {
-            stmt.close();
+            if (stmt != null)
+               stmt.close();
          }
          catch (Throwable e)
          {
@@ -717,7 +938,8 @@
       {
          try
          {
-            stmt.close();
+            if (stmt != null)
+               stmt.close();
          }
          catch (Throwable e)
          {
@@ -755,7 +977,7 @@
          stmt.setLong(4, txId.longValue());
          stmt.executeUpdate();
          stmt.close();
-
+         stmt = null;
       }
       catch (SQLException e)
       {
@@ -768,6 +990,12 @@
          {
             if (stmt != null)
                stmt.close();
+         }
+         catch (Throwable ignore)
+         {
+         }
+         try
+         {
             if (c != null)
                c.close();
          }
@@ -799,9 +1027,9 @@
       try
       {
          if (tx != null && tx.checkPersisted() == false)
-            addTXRecord(c, tx.longValue());
+            addTXRecord(c, tx);
       }
-      catch (SQLException e)
+      catch (Exception e)
       {
          tms.setRollbackOnly();
          throw new SpyJMSException("Could not create tx: " + tx.longValue(), e);
@@ -869,7 +1097,8 @@
       {
          try
          {
-            c.close();
+            if (c != null)
+               c.close();
          }
          catch (Throwable ignore)
          {
@@ -902,13 +1131,13 @@
          stmt.setString(5, mark);
 
          stmt.executeUpdate();
-
       }
       finally
       {
          try
          {
-            stmt.close();
+            if (stmt != null)
+               stmt.close();
          }
          catch (Throwable ignore)
          {
@@ -936,13 +1165,13 @@
          stmt.setLong(3, messageid);
          stmt.setString(4, destination);
          stmt.executeUpdate();
-
       }
       finally
       {
          try
          {
-            stmt.close();
+            if (stmt != null)
+               stmt.close();
          }
          catch (Throwable ignore)
          {
@@ -991,6 +1220,46 @@
       }
    }
 
+   public void setBlob(PreparedStatement stmt, int column, Xid xid) throws IOException, SQLException
+   {
+      if (blobType == OBJECT_BLOB)
+      {
+         stmt.setObject(column, xid);
+      }
+      else if (blobType == BYTES_BLOB)
+      {
+         ByteArrayOutputStream baos = new ByteArrayOutputStream();
+         ObjectOutputStream oos = new ObjectOutputStream(baos);
+         oos.writeObject(xid);
+         oos.flush();
+         byte[] messageAsBytes = baos.toByteArray();
+         stmt.setBytes(column, messageAsBytes);
+      }
+      else if (blobType == BINARYSTREAM_BLOB)
+      {
+         ByteArrayOutputStream baos = new ByteArrayOutputStream();
+         ObjectOutputStream oos = new ObjectOutputStream(baos);
+         oos.writeObject(xid);
+         oos.flush();
+         byte[] messageAsBytes = baos.toByteArray();
+         ByteArrayInputStream bais = new ByteArrayInputStream(messageAsBytes);
+         stmt.setBinaryStream(column, bais, messageAsBytes.length);
+      }
+      else if (blobType == BLOB_BLOB)
+      {
+
+         throw new RuntimeException("BLOB_TYPE: BLOB_BLOB is not yet implemented.");
+         /** TODO:
+         ByteArrayOutputStream baos= new ByteArrayOutputStream();
+         ObjectOutputStream oos= new ObjectOutputStream(baos);
+         oos.writeObject(xid);
+         byte[] messageAsBytes= baos.toByteArray();
+         ByteArrayInputStream bais= new ByteArrayInputStream(messageAsBytes);
+         stmt.setBsetBinaryStream(column, bais, messageAsBytes.length);
+         */
+      }
+   }
+
    /////////////////////////////////////////////////////////////////////////////////
    //
    // Updating a message
@@ -1045,14 +1314,16 @@
       {
          try
          {
-            stmt.close();
+            if (stmt != null)
+               stmt.close();
          }
          catch (Throwable ignore)
          {
          }
          try
          {
-            c.close();
+            if (c != null)
+               c.close();
          }
          catch (Throwable ignore)
          {
@@ -1139,14 +1410,16 @@
       {
          try
          {
-            stmt.close();
+            if (stmt != null)
+               stmt.close();
          }
          catch (Throwable ignore)
          {
          }
          try
          {
-            c.close();
+            if (c != null)
+               c.close();
          }
          catch (Throwable ignore)
          {
@@ -1171,17 +1444,11 @@
       return txManager;
    }
 
-   /*
-    * @see PersistenceManager#closeQueue(JMSDestination, SpyDestination)
-    */
    public void closeQueue(JMSDestination jmsDest, SpyDestination dest) throws JMSException
    {
       // Nothing to clean up, all the state is in the db.
    }
 
-   /*
-    * @see CacheStore#loadFromStorage(MessageReference)
-    */
    public SpyMessage loadFromStorage(MessageReference messageRef) throws JMSException
    {
       if (log.isTraceEnabled())
@@ -1222,21 +1489,24 @@
       {
          try
          {
-            rs.close();
+            if (rs != null)
+               rs.close();
          }
          catch (Throwable ignore)
          {
          }
          try
          {
-            stmt.close();
+            if (stmt != null)
+               stmt.close();
          }
          catch (Throwable ignore)
          {
          }
          try
          {
-            c.close();
+            if (c != null)
+               c.close();
          }
          catch (Throwable ignore)
          {
@@ -1290,14 +1560,16 @@
       {
          try
          {
-            stmt.close();
+            if (stmt != null)
+               stmt.close();
          }
          catch (Throwable ignore)
          {
          }
          try
          {
-            c.close();
+            if (c != null)
+               c.close();
          }
          catch (Throwable ignore)
          {
@@ -1310,9 +1582,6 @@
       }
    }
 
-   /*
-    * @see CacheStore#saveToStorage(MessageReference, SpyMessage)
-    */
    public void saveToStorage(MessageReference messageRef, SpyMessage message) throws JMSException
    {
       // Ignore save operations for persistent messages sent to persistent queues
@@ -1352,7 +1621,8 @@
       {
          try
          {
-            c.close();
+            if (c != null)
+               c.close();
          }
          catch (Throwable ignore)
          {
@@ -1437,18 +1707,28 @@
    public void startService() throws Exception
    {
       UPDATE_MARKED_MESSAGES = sqlProperties.getProperty("UPDATE_MARKED_MESSAGES", UPDATE_MARKED_MESSAGES);
+      UPDATE_MARKED_MESSAGES_XARECOVERY = 
+         sqlProperties.getProperty("UPDATE_MARKED_MESSAGES_XARECOVERY", UPDATE_MARKED_MESSAGES_XARECOVERY);
       UPDATE_MARKED_MESSAGES_WITH_TX =
          sqlProperties.getProperty("UPDATE_MARKED_MESSAGES_WITH_TX", UPDATE_MARKED_MESSAGES_WITH_TX);
       DELETE_MARKED_MESSAGES_WITH_TX =
          sqlProperties.getProperty("DELETE_MARKED_MESSAGES_WITH_TX", DELETE_MARKED_MESSAGES_WITH_TX);
+      DELETE_MARKED_MESSAGES_WITH_TX_XARECOVERY =
+         sqlProperties.getProperty("DELETE_MARKED_MESSAGES_WITH_TX_XARECOVERY", DELETE_MARKED_MESSAGES_WITH_TX_XARECOVERY);
       DELETE_TX = sqlProperties.getProperty("DELETE_TX", DELETE_TX);
       DELETE_MARKED_MESSAGES = sqlProperties.getProperty("DELETE_MARKED_MESSAGES", DELETE_MARKED_MESSAGES);
       DELETE_TEMPORARY_MESSAGES = sqlProperties.getProperty("DELETE_TEMPORARY_MESSAGES", DELETE_TEMPORARY_MESSAGES);
       INSERT_TX = sqlProperties.getProperty("INSERT_TX", INSERT_TX);
+      INSERT_TX_XARECOVERY = sqlProperties.getProperty("INSERT_TX_XARECOVERY", INSERT_TX_XARECOVERY);
       DELETE_ALL_TX = sqlProperties.getProperty("DELETE_ALL_TX", DELETE_ALL_TX);
+      DELETE_ALL_TX_XARECOVERY = sqlProperties.getProperty("DELETE_ALL_TX_XARECOVERY", DELETE_ALL_TX_XARECOVERY);
+      SELECT_ALL_TX_XARECOVERY = sqlProperties.getProperty("SELECT_ALL_TX_XARECOVERY", SELECT_ALL_TX_XARECOVERY);
       SELECT_MAX_TX = sqlProperties.getProperty("SELECT_MAX_TX", SELECT_MAX_TX);
       SELECT_MESSAGES_IN_DEST = sqlProperties.getProperty("SELECT_MESSAGES_IN_DEST", SELECT_MESSAGES_IN_DEST);
+      SELECT_MESSAGES_IN_DEST_XARECOVERY = sqlProperties.getProperty("SELECT_MESSAGES_IN_DEST_XARECOVERY", SELECT_MESSAGES_IN_DEST_XARECOVERY);
+      SELECT_MESSAGE_KEYS_IN_DEST = sqlProperties.getProperty("SELECT_MESSAGE_KEYS_IN_DEST", SELECT_MESSAGE_KEYS_IN_DEST);
       SELECT_MESSAGE = sqlProperties.getProperty("SELECT_MESSAGE", SELECT_MESSAGE);
+      SELECT_MESSAGE_XARECOVERY = sqlProperties.getProperty("SELECT_MESSAGE_XARECOVERY", SELECT_MESSAGE_XARECOVERY);
       INSERT_MESSAGE = sqlProperties.getProperty("INSERT_MESSAGE", INSERT_MESSAGE);
       MARK_MESSAGE = sqlProperties.getProperty("MARK_MESSAGE", MARK_MESSAGE);
       DELETE_MESSAGE = sqlProperties.getProperty("DELETE_MESSAGE", DELETE_MESSAGE);
@@ -1457,6 +1737,7 @@
       CREATE_IDX_MESSAGE_TXOP_TXID = sqlProperties.getProperty("CREATE_IDX_MESSAGE_TXOP_TXID", CREATE_IDX_MESSAGE_TXOP_TXID);
       CREATE_IDX_MESSAGE_DESTINATION = sqlProperties.getProperty("CREATE_IDX_MESSAGE_DESTINATION", CREATE_IDX_MESSAGE_DESTINATION);
       CREATE_TX_TABLE = sqlProperties.getProperty("CREATE_TX_TABLE", CREATE_TX_TABLE);
+      CREATE_TX_TABLE_XARECOVERY = sqlProperties.getProperty("CREATE_TX_TABLE_XARECOVERY", CREATE_TX_TABLE_XARECOVERY);
       createTables = sqlProperties.getProperty("CREATE_TABLES_ON_STARTUP", "true").equalsIgnoreCase("true");
       String s = sqlProperties.getProperty("BLOB_TYPE", "OBJECT_BLOB");
 
@@ -1477,16 +1758,10 @@
          blobType = BLOB_BLOB;
       }
 
-      //Find the ConnectionFactoryLoader MBean so we can find the datasource
-      String dsName = (String) getServer().getAttribute(connectionManagerName, "BindName");
-      //Get an InitialContext
 
-      InitialContext ctx = new InitialContext();
-      datasource = (DataSource) ctx.lookup(dsName);
+      // initialize tm and datasource
+      initializeFields();
 
-      //Get the Transaction Manager so we can control the jdbc tx
-      tm = (TransactionManager) ctx.lookup(TransactionManagerService.JNDI_NAME);
-
       log.debug("Creating Schema");
       createSchema();
       
@@ -1514,48 +1789,40 @@
          SpyJMSException.rethrowAsJMSException("Unable to resolve transactions retries=" + recoveryRetries, error);
    }
 
-   /**
-    * Describe <code>getInstance</code> method here.
-    *
-    * @return an <code>Object</code> value
-    * @jmx:managed-attribute
-    */
+   protected void initializeFields()
+           throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException, NamingException
+   {
+      //Find the ConnectionFactoryLoader MBean so we can find the datasource
+      String dsName = (String) getServer().getAttribute(connectionManagerName, "BindName");
+      //Get an InitialContext
+
+      InitialContext ctx = new InitialContext();
+      datasource = (DataSource) ctx.lookup(dsName);
+
+      //Get the Transaction Manager so we can control the jdbc tx
+      tm = (TransactionManager) ctx.lookup(TransactionManagerService.JNDI_NAME);
+   }
+
    public Object getInstance()
    {
       return this;
    }
 
-   /**
-    * Describe <code>getMessageCache</code> method here.
-    *
-    * @return an <code>ObjectName</code> value
-    */
    public ObjectName getMessageCache()
    {
       throw new UnsupportedOperationException("This is now set on the destination manager");
    }
 
-   /**
-    * Describe <code>setMessageCache</code> method here.
-    *
-    * @param messageCache an <code>ObjectName</code> value
-    */
    public void setMessageCache(ObjectName messageCache)
    {
       throw new UnsupportedOperationException("This is now set on the destination manager");
    }
 
-   /**
-    * @jmx:managed-attribute
-    */
    public ObjectName getConnectionManager()
    {
       return connectionManagerName;
    }
 
-   /**
-    * @jmx:managed-attribute
-    */
    public void setConnectionManager(ObjectName connectionManagerName)
    {
       this.connectionManagerName = connectionManagerName;
@@ -1566,13 +1833,6 @@
       throw new UnsupportedOperationException("This is now set on the destination manager");
    }
 
-   /**
-    * Gets the sqlProperties.
-    *
-    * @jmx:managed-attribute
-    *
-    * @return Returns a Properties
-    */
    public String getSqlProperties()
    {
       try
@@ -1587,47 +1847,24 @@
       }
    }
 
-   /**
-    * Sets the sqlProperties.
-    *
-    * @jmx:managed-attribute
-    *
-    * @param sqlProperties The sqlProperties to set
-    */
    public void setSqlProperties(String value)
    {
       try
       {
-
          ByteArrayInputStream is = new ByteArrayInputStream(value.getBytes());
          sqlProperties = new Properties();
          sqlProperties.load(is);
-
       }
       catch (IOException shouldnothappen)
       {
       }
    }
 
-   /**
-    * Sets the ConnectionRetryAttempts.
-    *
-    * @jmx:managed-attribute
-    *
-    * @param connectionRetryAttempts value
-    */
    public void setConnectionRetryAttempts(int value)
    {
       this.connectionRetryAttempts = value;
    }
 
-   /**
-    * Gets the ConnectionRetryAttempts.
-    *
-    * @jmx:managed-attribute
-    *
-    * @return Returns a ConnectionRetryAttempt value
-    */
    public int getConnectionRetryAttempts()
    {
       return this.connectionRetryAttempts;
@@ -1652,4 +1889,29 @@
    {
       this.recoveryRetries = retries;
    }
+
+   public int getRecoverMessagesChunk()
+   {
+      return recoverMessagesChunk;
+   }
+
+   public void setRecoverMessagesChunk(int recoverMessagesChunk)
+   {
+      if (recoverMessagesChunk != 0 && recoverMessagesChunk != 1)
+      {
+         log.warn("Only the values 0 and 1 are currently support for chunk size, using chunk size=1");
+         recoverMessagesChunk = 1;
+      }
+      this.recoverMessagesChunk = recoverMessagesChunk;
+   }
+
+   public boolean isXARecovery()
+   {
+      return xaRecovery;
+   }
+
+   public void setXARecovery(boolean xaRecovery)
+   {
+      this.xaRecovery = xaRecovery;
+   }
 }

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/pm/jdbc2/PersistenceManagerMBean.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/pm/jdbc2/PersistenceManagerMBean.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/pm/jdbc2/PersistenceManagerMBean.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.pm.jdbc2;
 
 import javax.management.ObjectName;
@@ -13,6 +28,11 @@
 
 /**
  * MBean interface.
+ * 
+ * @author Jayesh Parayali (jayeshpk1 at yahoo.com)
+ * @author Hiram Chirino (cojonudo14 at hotmail.com)
+ * @author Adrian Brock (adrian at jboss.com)
+ * @version $Revision$
  */
 public interface PersistenceManagerMBean extends ServiceMBean, org.jboss.mq.pm.PersistenceManagerMBean, CacheStoreMBean
 {
@@ -81,11 +101,43 @@
 
    /**
     * Returns the recovery retries
+    * 
+    * @return the retries
     */
-   public int getRecoveryRetries();
+   int getRecoveryRetries();
 
    /**
     * Set the recovery retries
+    * 
+    * @param retries the number of retries
     */
-   public void setRecoveryRetries(int retries);
+   void setRecoveryRetries(int retries);
+
+   /**
+    * Returns the recover messages chunk
+    * 
+    * @return the chunk size
+    */
+   int getRecoverMessagesChunk();
+
+   /**
+    * Set the recover messages chunk
+    * 
+    * @param recoverMessagesChunk the chunk size
+    */
+   void setRecoverMessagesChunk(int recoverMessagesChunk);
+
+   /**
+    * Get the xaRecovery.
+    * 
+    * @return the xaRecovery.
+    */
+   boolean isXARecovery();
+
+   /**
+    * Set the xaRecovery.
+    * 
+    * @param xaRecovery the xaRecovery.
+    */
+   void setXARecovery(boolean xaRecovery);
 }

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/BasicQueue.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/BasicQueue.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/BasicQueue.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBossMQ, the OpenSource JMS implementation
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.server;
 
 import java.util.ArrayList;
@@ -13,6 +28,7 @@
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.Map;
+import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
 
@@ -23,12 +39,14 @@
 import org.jboss.mq.AcknowledgementRequest;
 import org.jboss.mq.DestinationFullException;
 import org.jboss.mq.SpyJMSException;
+import org.jboss.mq.SpyDestination;
 import org.jboss.mq.SpyMessage;
 import org.jboss.mq.Subscription;
 import org.jboss.mq.pm.Tx;
+import org.jboss.mq.pm.TxManager;
 import org.jboss.mq.selectors.Selector;
+import org.jboss.util.NestedRuntimeException;
 import org.jboss.util.timeout.Timeout;
-import org.jboss.util.timeout.TimeoutFactory;
 import org.jboss.util.timeout.TimeoutTarget;
 
 import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap;
@@ -56,12 +74,8 @@
  */
 public class BasicQueue
 {
-   // Constants -----------------------------------------------------
-
    static final Logger log = Logger.getLogger(BasicQueue.class);
 
-   // Attributes ----------------------------------------------------
-
    /** List of messages waiting to be dispatched<p>
        synchronized access on itself */
    SortedSet messages = new TreeSet();
@@ -107,11 +121,7 @@
 
    /** Have we been stopped */
    boolean stopped = false;
-   
-   // Static --------------------------------------------------------
 
-   // Constructors --------------------------------------------------
-
    /**
     * Construct a new basic queue
     * 
@@ -140,8 +150,6 @@
       }
    }
 
-   // Public --------------------------------------------------------
-
    /**
     * Retrieve the unique description for this queue
     *
@@ -212,9 +220,7 @@
                   if (message.isExpired())
                   {
                      it.remove();
-                     if (trace)
-                        log.trace("message expired: " + message);
-                     dropMessage(message);
+                     expireMessageAsync(message);
                   }
                   else if (sub.accepts(message.getHeaders()))
                   {
@@ -238,6 +244,19 @@
    }
 
    /**
+    * Get the subscribers
+    * 
+    * @return the subscribers
+    */
+   public Set getSubscribers()
+   {
+      synchronized (receivers)
+      {
+         return (Set) subscribers.clone();
+      }
+   }
+   
+   /**
     * Add a subscription from the queue
     *
     * @param sub the subscription to add
@@ -341,13 +360,7 @@
             }
          }
 
-         // The message is removed from the cache on a rollback
-         Runnable task = new AddMessagePostRollBackTask(mes);
-         server.getPersistenceManager().getTxManager().addPostRollbackTask(txId, task);
-
-         // The message gets added to the queue after the transaction commits
-         task = new AddMessagePostCommitTask(mes);
-         server.getPersistenceManager().getTxManager().addPostCommitTask(txId, task);
+         performOrPerpareAddMessage(mes, txId);
       }
       catch (Throwable t)
       {
@@ -359,14 +372,75 @@
    }
 
    /**
+    * Either perform or prepare the add message 
+    * 
+    * @param mes the message reference
+    * @param txId the transaction id
+    * @throws Exception for any error
+    */
+   protected void performOrPerpareAddMessage(MessageReference mes, Tx txId) throws Exception
+   {
+      TxManager txManager = server.getPersistenceManager().getTxManager();
+      
+      // The message is removed from the cache on a rollback
+      Runnable task = new AddMessagePostRollBackTask(mes);
+      txManager.addPostRollbackTask(txId, task);
+
+      // The message gets added to the queue after the transaction commits
+      task = new AddMessagePostCommitTask(mes);
+      txManager.addPostCommitTask(txId, task);
+   }
+   
+   /**
     * Restores a message.
+    * 
+    * @param mes the message reference
     */
    public void restoreMessage(MessageReference mes)
    {
+      restoreMessage(mes, null, Tx.UNKNOWN);
+   }
+
+   /**
+    * Restores a message.
+    * 
+    * @param mes the message reference
+    * @param txid the transaction id
+    * @param type the type of restoration
+    */
+   public void restoreMessage(MessageReference mes, Tx txid, int type)
+   {
       boolean trace = log.isTraceEnabled();
       if (trace)
-         log.trace("restoreMessage " + mes + " " + this);
-      internalAddMessage(mes);
+         log.trace("restoreMessage " + mes + " " + this + " txid=" + txid + " type=" + type);
+
+      try
+      {
+         if (txid == null)
+         {
+            internalAddMessage(mes);
+         }
+         else if (type == Tx.ADD)
+         {
+            performOrPerpareAddMessage(mes, txid);
+         }
+         else if (type == Tx.REMOVE)
+         {
+            performOrPerpareAcknowledgeMessage(mes, txid);
+         }
+         else
+         {
+            throw new IllegalStateException("Unknown restore type " + type + " for message " + mes + " txid=" + txid);
+         }
+      }
+      catch (RuntimeException e)
+      {
+         throw e;
+      }
+      catch (Exception e)
+      {
+         throw new NestedRuntimeException("Unable to restore message " + mes, e);
+      }
    }
 
    /**
@@ -470,9 +544,7 @@
 
                   if (messageRef.isExpired())
                   {
-                     if (trace)
-                        log.trace("message expired: " + messageRef);
-                     dropMessage(messageRef);
+                     expireMessageAsync(messageRef);
                      messageRef = null;
                   }
                   else
@@ -492,9 +564,7 @@
                   if (mr.isExpired())
                   {
                      i.remove();
-                     if (trace)
-                        log.trace("message expired: " + mr);
-                     dropMessage(mr);
+                     expireMessageAsync(mr);
                   }
                   else if (sub.accepts(mr.getHeaders()))
                   {
@@ -529,7 +599,7 @@
     * @param txid the transaction
     * @throws JMSException for any error
     */
-   public void acknowledge(AcknowledgementRequest item, Tx txId) throws javax.jms.JMSException
+   public void acknowledge(AcknowledgementRequest item, Tx txId) throws JMSException
    {
       boolean trace = log.isTraceEnabled();
       if (trace)
@@ -554,20 +624,16 @@
       // Was it a negative acknowledge??
       if (!item.isAck)
       {
-         Runnable task = new RestoreMessageTask(m);
+         Runnable task;
+         task = new RestoreMessageTask(m);
          server.getPersistenceManager().getTxManager().addPostCommitTask(txId, task);
-
       }
       else
       {
          if (m.isPersistent())
             server.getPersistenceManager().remove(m, txId);
 
-         Runnable task = new RestoreMessageTask(m);
-         server.getPersistenceManager().getTxManager().addPostRollbackTask(txId, task);
-
-         task = new RemoveMessageTask(m);
-         server.getPersistenceManager().getTxManager().addPostCommitTask(txId, task);
+         performOrPerpareAcknowledgeMessage(m, txId);
       }
 
       synchronized (receivers)
@@ -580,6 +646,26 @@
    }
 
    /**
+    * Either perform or prepare the acknowledge message 
+    * 
+    * @param mes the message reference
+    * @param txId the transaction id
+    * @throws Exception for any error
+    */
+   protected void performOrPerpareAcknowledgeMessage(MessageReference mes, Tx txId) throws JMSException
+   {
+      TxManager txManager = server.getPersistenceManager().getTxManager();
+      
+      // The message is restored to the queue on a rollback
+      Runnable task = new RestoreMessageTask(mes);
+      txManager.addPostRollbackTask(txId, task);
+
+      // The message is fully removed after the transaction commits
+      task = new RemoveMessageTask(mes);
+      txManager.addPostCommitTask(txId, task);
+   }
+
+   /**
     * Nack all messages for a subscription
     *
     * @param sub the subscription
@@ -632,12 +718,15 @@
          Map.Entry entry = (Map.Entry) i.next();
          MessageReference message = (MessageReference) entry.getKey();
          Timeout timeout = (Timeout) entry.getValue();
-         timeout.cancel();
-         i.remove();
-         dropMessage(message);
+         if (timeout != null)
+         {
+            timeout.cancel();
+            i.remove();
+            dropMessage(message);
+         }
       }
       scheduledMessageCount.set(0);
-      
+
       synchronized (receivers)
       {
          synchronized (messages)
@@ -747,15 +836,11 @@
    {
       return counter;
    }
-
-   // Object overrides ----------------------------------------------
    
    public String toString()
    {
       return super.toString() + "{id=" + description + '}';
    }
-   
-   // Protected -----------------------------------------------------
 
    /**
     * Clear all the events
@@ -767,8 +852,11 @@
       {
          Map.Entry entry = (Map.Entry) i.next();
          Timeout timeout = (Timeout) entry.getValue();
-         timeout.cancel();
-         i.remove();
+         if (timeout != null)
+         {
+            timeout.cancel();
+            i.remove();
+         }
       }
    }
    
@@ -820,6 +908,12 @@
       }
    }
 
+   private void addTimeout(MessageReference message, TimeoutTarget t, long ts)
+   {
+      Timeout timeout = server.getTimeoutFactory().schedule(ts, t);
+      events.put(message, timeout);
+   }
+
    /**
     * Add a message
     *
@@ -835,9 +929,7 @@
       long ts = message.messageScheduledDelivery;
       if (ts > 0 && ts > System.currentTimeMillis())
       {
-         EnqueueMessageTask t = new EnqueueMessageTask(message);
-         Timeout timeout = TimeoutFactory.createTimeout(ts, t);
-         events.put(message, timeout);
+         addTimeout(message, new EnqueueMessageTask(message), ts);
          scheduledMessageCount.increment();
          if (trace)
             log.trace("scheduled message at " + new Date(ts) + ": " + message);
@@ -848,9 +940,7 @@
       // Don't bother with expired messages
       if (message.isExpired())
       {
-         if (trace)
-            log.trace("message expired: " + message);
-         dropMessage(message);
+         expireMessageAsync(message);
          return;
       }
 
@@ -883,10 +973,7 @@
                   // the timer queue 
                   if (message.messageExpiration > 0)
                   {
-                     // This could be a waste of memory for large numbers of expirations
-                     ExpireMessageTask t = new ExpireMessageTask(message);
-                     Timeout timeout = TimeoutFactory.createTimeout(message.messageExpiration, t);
-                     events.put(message, timeout);
+                     addTimeout(message, new ExpireMessageTask(message), message.messageExpiration);
                   }
                }
             }
@@ -941,26 +1028,26 @@
    protected void setupMessageAcknowledgement(Subscription sub, MessageReference messageRef) throws JMSException
    {
       SpyMessage message = messageRef.getMessage();
-      AcknowledgementRequest ack = new AcknowledgementRequest();
-      ack.destination = message.getJMSDestination();
-      ack.messageID = message.getJMSMessageID();
-      ack.subscriberId = sub.subscriptionId;
-      ack.isAck = false;
+      AcknowledgementRequest nack = new AcknowledgementRequest(false);
+      nack.destination = message.getJMSDestination();
+      nack.messageID = message.getJMSMessageID();
+      nack.subscriberId = sub.subscriptionId;
 
       synchronized (messages)
       {
          UnackedMessageInfo unacked = new UnackedMessageInfo(messageRef, sub);
-         unacknowledgedMessages.put(ack, unacked);
-         unackedByMessageRef.put(messageRef, ack);
+         unacknowledgedMessages.put(nack, unacked);
+         unackedByMessageRef.put(messageRef, nack);
          HashMap map = (HashMap) unackedBySubscription.get(sub);
          if (map == null)
          {
             map = new HashMap();
             unackedBySubscription.put(sub, map);
          }
-         map.put(messageRef, ack);
+         map.put(messageRef, nack);
       }
    }
+
    /**
     * Remove a message
     *
@@ -1012,10 +1099,66 @@
       }
    }
 
-   // Package Private -----------------------------------------------
+   /**
+    * Expire a message asynchronously.
+    *
+    * @param messageRef the message to remove
+    */
+   protected void expireMessageAsync(MessageReference messageRef)
+   {
+      server.getThreadPool().run(new ExpireMessageTask(messageRef));
+   }
+   
+   /**
+    * Expire a message
+    *
+    * @param messageRef the message to remove
+    */
+   protected void expireMessage(MessageReference messageRef)
+   {
+      boolean trace = log.isTraceEnabled();
+      if (trace)
+         log.trace("message expired: " + messageRef);
 
-   // Private -------------------------------------------------------
+      SpyDestination ed = parameters.expiryDestination;
+      if (ed == null)
+      {
+         dropMessage(messageRef);
+         return;
+      }
 
+      if (trace)
+         log.trace("sending to: " + ed);
+
+      try
+      {
+         SpyMessage orig = messageRef.getMessage();
+         SpyMessage copy = orig.myClone();
+         copy.header.jmsPropertiesReadWrite = true;
+         copy.setJMSExpiration(0);
+         copy.setJMSDestination(ed);
+         copy.setLongProperty(SpyMessage.PROPERTY_ORIG_EXPIRATION, orig.getJMSExpiration());
+         copy.setStringProperty(SpyMessage.PROPERTY_ORIG_DESTINATION, orig.getJMSDestination().toString());
+         TxManager tm = server.getPersistenceManager().getTxManager();
+         Tx tx = tm.createTx();
+         try 
+         {
+            server.addMessage(null, copy, tx);
+            dropMessage(messageRef, tx);
+            tm.commitTx(tx);
+         }
+         catch (JMSException e)
+         {
+            tm.rollbackTx(tx);
+            throw e;
+         }
+      }
+      catch (JMSException e)
+      {
+         log.error("Could not move expired message: " + messageRef, e);
+      }
+   }
+
    /**
     * Check whether a removed subscription can be permenantly removed.
     * This method is private because it assumes external synchronization
@@ -1047,8 +1190,6 @@
       return unackedBySubscription.containsKey(sub);
    }
 
-   // Inner classes -------------------------------------------------
-
    /**
     * Rollback an add message
     */
@@ -1167,7 +1308,7 @@
    /**
     * Drop a message when it expires
     */
-   private class ExpireMessageTask implements TimeoutTarget
+   private class ExpireMessageTask implements TimeoutTarget, Runnable
    {
       private MessageReference messageRef;
 
@@ -1186,10 +1327,13 @@
             if (messages.remove(messageRef) == false)
                return;
          }
-         if (log.isTraceEnabled())
-            log.trace("message expired: " + messageRef);
-         dropMessage(messageRef);
+         expireMessage(messageRef);
       }
+
+      public void run()
+      {
+         expireMessage(messageRef);
+      }
    }
 
    /**

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/BasicQueueParameters.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/BasicQueueParameters.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/BasicQueueParameters.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,11 +1,28 @@
 /*
- * JBossMQ, the OpenSource JMS implementation
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.server;
 
+import org.jboss.mq.SpyDestination;
+
 /**
  * Parameters controlling a basic queue
  *
@@ -36,8 +53,11 @@
    public Class receiversImpl;
    
    /** The message counter history */
-   public int messageCounterHistoryDayLimit = -1;
+   public int messageCounterHistoryDayLimit = 0;
    
    /** The number of retries when recovering a queue/durable subscription */
    public int recoveryRetries = 0;
+   
+   /** The destination that receives expired messages */
+   public SpyDestination expiryDestination = null;
 }

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/JMSDestination.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/JMSDestination.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/JMSDestination.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBossMQ, the OpenSource JMS implementation
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.server;
 
 import javax.jms.JMSException;
@@ -12,6 +27,7 @@
 import org.jboss.mq.SpyDestination;
 import org.jboss.mq.SpyMessage;
 import org.jboss.mq.Subscription;
+import org.jboss.mq.pm.Tx;
 
 /**
  *  This class is a message queue which is stored (hashed by Destination) on the
@@ -20,12 +36,12 @@
  * @author     Norbert Lataille (Norbert.Lataille at m4x.org)
  * @author     Hiram Chirino (Cojonudo14 at hotmail.com)
  * @author     David Maplesden (David.Maplesden at orion.co.nz)
+ * @author     Adrian Brock (adrian at jboss.com)
  * @created    August 16, 2001
  * @version    $Revision$
  */
 public abstract class JMSDestination
 {
-
    //the Destination of this queue
    SpyDestination destination;
    //If this is a temporaryDestination, temporaryDestination=ClientConsumer of the owner, otherwise it's null
@@ -45,7 +61,6 @@
 
    static Logger cat = Logger.getLogger(JMSDestination.class);
 
-   // Constructor ---------------------------------------------------
    JMSDestination(SpyDestination dest, ClientConsumer temporary, JMSDestinationManager server, BasicQueueParameters parameters) throws JMSException
    {
       destination = dest;
@@ -73,7 +88,19 @@
 
    public abstract void restoreMessage(MessageReference message);
 
-   public abstract void restoreMessage(SpyMessage message);
+   public void restoreMessage(SpyMessage message)
+   {
+      restoreMessage(message, null, Tx.UNKNOWN);
+   }
+   
+   /**
+    * Restore a message
+    * 
+    * @param message the message
+    * @param tx any transaction
+    * @param type the type of restoration
+    */
+   public abstract void restoreMessage(SpyMessage message, Tx tx, int type);
 
    public abstract boolean isInUse();
 

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/JMSDestinationManager.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/JMSDestinationManager.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/JMSDestinationManager.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,8 +1,23 @@
 /*
- * JBoss, the OpenSource J2EE webOS
+ * 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.
  *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
+ * 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.mq.server;
 
@@ -19,8 +34,8 @@
 import javax.jms.TemporaryQueue;
 import javax.jms.TemporaryTopic;
 import javax.jms.Topic;
+import javax.transaction.xa.Xid;
 
-import org.jboss.logging.Logger;
 import org.jboss.mq.AcknowledgementRequest;
 import org.jboss.mq.ConnectionToken;
 import org.jboss.mq.DurableSubscriptionID;
@@ -36,7 +51,10 @@
 import org.jboss.mq.TransactionRequest;
 import org.jboss.mq.pm.PersistenceManager;
 import org.jboss.mq.pm.Tx;
+import org.jboss.mq.pm.TxManager;
 import org.jboss.mq.sm.StateManager;
+import org.jboss.util.threadpool.ThreadPool;
+import org.jboss.util.timeout.TimeoutFactory;
 
 import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap;
 
@@ -51,41 +69,47 @@
  */
 public class JMSDestinationManager extends JMSServerInterceptorSupport
 {
-   static Logger log = Logger.getLogger(JMSDestinationManager.class);
+   /** The version */
+   public final static String JBOSS_VERSION = "JBossMQ Version 4.0";
 
-   /**
-    * Description of the Field
-    */
-   public final static String JBOSS_VESION = "JBossMQ Version 3.2";
-
-   /////////////////////////////////////////////////////////////////////
-   // Attributes
-   /////////////////////////////////////////////////////////////////////
-
-   /** Destinations SpyDestination -> JMSDestination */ 
+   /** Destinations SpyDestination -> JMSDestination */
    public Map destinations = new ConcurrentReaderHashMap();
-   /** Destinations being closed SpyDestination -> JMSDestination */ 
+
+   /** Destinations being closed SpyDestination -> JMSDestination */
    public Map closingDestinations = new ConcurrentReaderHashMap();
-   //Thread group for server side threads.
+
+   /** Thread pool */
+   public ThreadPool threadPool;
+
    /** Thread group */
-   public ThreadGroup threadGroup = new ThreadGroup("JBossMQ Server Threads");
+   public ThreadGroup threadGroup;
 
-   //The list of ClientConsumers hased by ConnectionTokens
+   /** Timeout factory */
+   public TimeoutFactory timeoutFactory;
+
+   /** The list of ClientConsumers hased by ConnectionTokens */
    Map clientConsumers = new ConcurrentReaderHashMap();
 
-   //last id given to a client
+   /** last id given to a client */
    private int lastID = 1;
-   //last id given to a temporary topic
+
+   /** last id given to a temporary topic */
    private int lastTemporaryTopic = 1;
+
    private Object lastTemporaryTopicLock = new Object();
-   //last id given to a temporary queue
+
+   /** last id given to a temporary queue */
    private int lastTemporaryQueue = 1;
+
    private Object lastTemporaryQueueLock = new Object();
-   //The security manager
+
+   /** The security manager */
    private StateManager stateManager;
-   //The persistence manager
+
+   /** The persistence manager */
    private PersistenceManager persistenceManager;
-   //The Cache Used to hold messages
+
+   /** The Cache Used to hold messages */
    private MessageCache messageCache;
 
    private Object stateLock = new Object();
@@ -102,9 +126,6 @@
    /** Temporary queue/topic parameters */
    BasicQueueParameters parameters;
 
-   /////////////////////////////////////////////////////////////////////
-   // Constructors
-   /////////////////////////////////////////////////////////////////////
    /**
     * Constructor for the JMSServer object
     */
@@ -146,14 +167,10 @@
       persistenceManager = newPersistenceManager;
    }
 
-   /////////////////////////////////////////////////////////////////////
-   // Public Methods
-   /////////////////////////////////////////////////////////////////////
-
    /**
     * Returns <code>false</code> if the JMS server is currently running and
     * handling requests, <code>true</code> otherwise.
-   *
+    *
     * @return   <code>false</code> if the JMS server is currently running and
     *      handling requests, <code>true</code> otherwise.
     */
@@ -165,6 +182,12 @@
       }
    }
 
+   protected void checkStopped() throws IllegalStateException
+   {
+      if (isStopped())
+         throw new IllegalStateException("Server is stopped.");
+   }
+   
    /**
     *
     * @return the current client count
@@ -173,7 +196,10 @@
    {
       return clientConsumers.size();
    }
-   /** Obtain a copy of the current clients
+
+   /** 
+    * Obtain a copy of the current clients
+    * 
     * @return a HashMap<ConnectionToken, ClientConsumer> of current clients
     */
    public HashMap getClients()
@@ -181,12 +207,31 @@
       return new HashMap(clientConsumers);
    }
 
+   public void setThreadPool(ThreadPool threadPool)
+   {
+      this.threadPool = threadPool;
+   }
+
+   public ThreadPool getThreadPool()
+   {
+      return threadPool;
+   }
+
+   public void setThreadGroup(ThreadGroup threadGroup)
+   {
+      this.threadGroup = threadGroup;
+   }
+
    public ThreadGroup getThreadGroup()
    {
       return threadGroup;
    }
 
-   //Get a new ClientID for a connection
+   public TimeoutFactory getTimeoutFactory()
+   {
+      return timeoutFactory;
+   }
+
    /**
     * Gets the ID attribute of the JMSServer object
     *
@@ -196,8 +241,10 @@
    {
       String ID = null;
 
-      while (true)
+      while (isStopped() == false)
       {
+         if (stateManager == null)
+            throw new IllegalStateException("No statemanager");
          try
          {
             synchronized (idLock)
@@ -212,18 +259,15 @@
          }
       }
 
+      checkStopped();
+      
       return ID;
    }
 
-   /**
-    * Gets the TemporaryTopic attribute of the JMSServer object
-    *
-    * @param dc                Description of Parameter
-    * @return                  The TemporaryTopic value
-    * @exception JMSException  Description of Exception
-    */
    public TemporaryTopic getTemporaryTopic(ConnectionToken dc) throws JMSException
    {
+      checkStopped();
+      
       String topicName;
       synchronized (lastTemporaryTopicLock)
       {
@@ -238,15 +282,10 @@
       return topic;
    }
 
-   /**
-    * Gets the TemporaryQueue attribute of the JMSServer object
-    *
-    * @param dc                Description of Parameter
-    * @return                  The TemporaryQueue value
-    * @exception JMSException  Description of Exception
-    */
    public TemporaryQueue getTemporaryQueue(ConnectionToken dc) throws JMSException
    {
+      checkStopped();
+      
       String queueName;
       synchronized (lastTemporaryQueueLock)
       {
@@ -261,15 +300,6 @@
       return newQueue;
    }
 
-   // Gets the ClientConsumers mapped the the connection
-   // If the connection is not mapped, a new ClientConsumer is created
-   /**
-    * Gets the ClientConsumer attribute of the JMSServer object
-    *
-    * @param dc                Description of Parameter
-    * @return                  The ClientConsumer value
-    * @exception JMSException  Description of Exception
-    */
    public ClientConsumer getClientConsumer(ConnectionToken dc) throws JMSException
    {
       ClientConsumer cq = (ClientConsumer) clientConsumers.get(dc);
@@ -281,12 +311,6 @@
       return cq;
    }
 
-   /**
-    * Gets the JMSDestination attribute of the JMSServer object
-    *
-    * @param dest  Description of Parameter
-    * @return      The JMSDestination value
-    */
    public JMSDestination getJMSDestination(SpyDestination dest)
    {
       return (JMSDestination) destinations.get(dest);
@@ -322,68 +346,62 @@
     *
     * @return   The PersistenceManager value
     */
-   public org.jboss.mq.pm.PersistenceManager getPersistenceManager()
+   public PersistenceManager getPersistenceManager()
    {
       return persistenceManager;
    }
 
    /**
-    * #Description of the Method
+    * Start the server
     */
    public void startServer()
    {
       synchronized (stateLock)
       {
          this.stopped = false;
+         this.timeoutFactory = new TimeoutFactory(this.threadPool);
       }
    }
 
    /**
-    * #Description of the Method
+    * Stop the server
     */
    public void stopServer()
    {
       synchronized (stateLock)
       {
          this.stopped = true;
+         this.timeoutFactory.cancel();
+         
+         for (Iterator i = clientConsumers.keySet().iterator(); i.hasNext();)
+         {
+            ConnectionToken token = (ConnectionToken) i.next();
+            try
+            {
+               connectionClosing(token);
+            }
+            catch (Throwable t)
+            {
+               log.trace("Ignored error closing client connection " + token, t);
+            }
+         }
       }
    }
 
-   /**
-    * Check a clienID set by the client.
-    *
-    * @param ID                Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void checkID(String ID) throws JMSException
    {
+      checkStopped();
       stateManager.addLoggedOnClientId(ID);
    }
 
-   //A connection has sent a new message
-   /**
-    * Adds a feature to the Message attribute of the JMSServer object
-    *
-    * @param dc                The feature to be added to the Message attribute
-    * @param val               The feature to be added to the Message attribute
-    * @exception JMSException  Description of Exception
-    */
    public void addMessage(ConnectionToken dc, SpyMessage val) throws JMSException
    {
       addMessage(dc, val, null);
    }
 
-   //A connection has sent a new message
-   /**
-    * Adds a feature to the Message attribute of the JMSServer object
-    *
-    * @param dc                The feature to be added to the Message attribute
-    * @param val               The feature to be added to the Message attribute
-    * @param txId              The feature to be added to the Message attribute
-    * @exception JMSException  Description of Exception
-    */
    public void addMessage(ConnectionToken dc, SpyMessage val, Tx txId) throws JMSException
    {
+      checkStopped();
       JMSDestination queue = (JMSDestination) destinations.get(val.getJMSDestination());
       if (queue == null)
          throw new InvalidDestinationException("This destination does not exist! " + val.getJMSDestination());
@@ -397,25 +415,18 @@
       queue.addMessage(val, txId);
    }
 
-   /**
-    * The following function performs a Unit Of Work.
-    *
-    * @param dc                Description of Parameter
-    * @param t                 Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void transact(ConnectionToken dc, TransactionRequest t) throws JMSException
    {
-
-      org.jboss.mq.pm.TxManager txManager = persistenceManager.getTxManager();
+      checkStopped();
+      boolean trace = log.isTraceEnabled();
+      TxManager txManager = persistenceManager.getTxManager();
       if (t.requestType == TransactionRequest.ONE_PHASE_COMMIT_REQUEST)
       {
-
          Tx txId = txManager.createTx();
-
+         if (trace)
+            log.trace(dc + " 1PC " + t.xid + " txId=" + txId.longValue());
          try
          {
-
             if (t.messages != null)
             {
                for (int i = 0; i < t.messages.length; i++)
@@ -423,7 +434,6 @@
                   addMessage(dc, t.messages[i], txId);
                }
             }
-
             if (t.acks != null)
             {
                for (int i = 0; i < t.acks.length; i++)
@@ -431,9 +441,7 @@
                   acknowledge(dc, t.acks[i], txId);
                }
             }
-
             txManager.commitTx(txId);
-
          }
          catch (JMSException e)
          {
@@ -444,11 +452,11 @@
       }
       else if (t.requestType == TransactionRequest.TWO_PHASE_COMMIT_PREPARE_REQUEST)
       {
-
          Tx txId = txManager.createTx(dc, t.xid);
+         if (trace)
+            log.trace(dc + " 2PC PREPARE " + t.xid + " txId=" + txId.longValue());
          try
          {
-
             if (t.messages != null)
             {
                for (int i = 0; i < t.messages.length; i++)
@@ -456,7 +464,6 @@
                   addMessage(dc, t.messages[i], txId);
                }
             }
-
             if (t.acks != null)
             {
                for (int i = 0; i < t.acks.length; i++)
@@ -464,7 +471,8 @@
                   acknowledge(dc, t.acks[i], txId);
                }
             }
-
+            
+            txManager.markPrepared(dc, t.xid, txId);
          }
          catch (JMSException e)
          {
@@ -475,58 +483,37 @@
       }
       else if (t.requestType == TransactionRequest.TWO_PHASE_COMMIT_ROLLBACK_REQUEST)
       {
-
-         Tx txId = txManager.getPrepared(dc, t.xid);
-         txManager.rollbackTx(txId);
-
+         if (trace)
+            log.trace(dc + " 2PC ROLLBACK " + t.xid);
+         txManager.rollbackTx(dc, t.xid);
       }
       else if (t.requestType == TransactionRequest.TWO_PHASE_COMMIT_COMMIT_REQUEST)
       {
-
-         Tx txId = txManager.getPrepared(dc, t.xid);
-         txManager.commitTx(txId);
-
+         if (trace)
+            log.trace(dc + " 2PC COMMIT " + t.xid);
+         txManager.commitTx(dc, t.xid);
       }
+   }
 
+   public Xid[] recover(ConnectionToken dc, int flags) throws Exception
+   {
+      checkStopped();
+      TxManager txManager = persistenceManager.getTxManager();
+      return txManager.recover(dc, flags);
    }
 
-   //Sent by a client to Ack or Nack a message.
-   /**
-    * #Description of the Method
-    *
-    * @param dc                Description of Parameter
-    * @param item              Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void acknowledge(ConnectionToken dc, AcknowledgementRequest item) throws JMSException
    {
       acknowledge(dc, item, null);
    }
 
-   //Sent by a client to Ack or Nack a message.
-   /**
-    * #Description of the Method
-    *
-    * @param dc                Description of Parameter
-    * @param item              Description of Parameter
-    * @param txId              Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void acknowledge(ConnectionToken dc, AcknowledgementRequest item, Tx txId) throws JMSException
    {
-
+      checkStopped();
       ClientConsumer cc = getClientConsumer(dc);
       cc.acknowledge(item, txId);
-
    }
 
-   //A connection is closing [error or notification]
-   /**
-    * #Description of the Method
-    *
-    * @param dc                Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void connectionClosing(ConnectionToken dc) throws JMSException
    {
       if (dc == null)
@@ -547,11 +534,14 @@
       {
          Map.Entry entry = (Map.Entry) i.next();
          JMSDestination sq = (JMSDestination) entry.getValue();
-         ClientConsumer cc = sq.temporaryDestination;
-         if (cc != null && dc.equals(cc.connectionToken))
+         if (sq != null)
          {
-            i.remove();
-            deleteTemporaryDestination(dc, sq);
+            ClientConsumer cc = sq.temporaryDestination;
+            if (cc != null && dc.equals(cc.connectionToken))
+            {
+               i.remove();
+               deleteTemporaryDestination(dc, sq);
+            }
          }
       }
       // Close the clientIL
@@ -562,19 +552,12 @@
       }
       catch (Exception ex)
       {
-         // We skipp warning, to often the client will allways
+         // We skip warning, to often the client will always
          // have gone when we get here
          //log.warn("Could not close clientIL: " +ex,ex);
       }
-
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc                Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void connectionFailure(ConnectionToken dc) throws JMSException
    {
       //We should try again :) This behavior should under control of a Failure-Plugin
@@ -582,56 +565,29 @@
       connectionClosing(dc);
    }
 
-   //A connection object wants to subscribe to a Destination
-   /**
-    * #Description of the Method
-    *
-    * @param dc                Description of Parameter
-    * @param sub               Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void subscribe(ConnectionToken dc, Subscription sub) throws JMSException
    {
+      checkStopped();
       ClientConsumer clientConsumer = getClientConsumer(dc);
       clientConsumer.addSubscription(sub);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc                Description of Parameter
-    * @param subscriptionId    Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void unsubscribe(ConnectionToken dc, int subscriptionId) throws JMSException
    {
+      checkStopped();
       ClientConsumer clientConsumer = getClientConsumer(dc);
       clientConsumer.removeSubscription(subscriptionId);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param id                Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void destroySubscription(ConnectionToken dc, DurableSubscriptionID id) throws JMSException
    {
+      checkStopped();
       getStateManager().setDurableSubscription(this, id, null);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc                Description of Parameter
-    * @param dest              Description of Parameter
-    * @param selector          Description of Parameter
-    * @return                  Description of the Returned Value
-    * @exception JMSException  Description of Exception
-    */
    public SpyMessage[] browse(ConnectionToken dc, Destination dest, String selector) throws JMSException
    {
-
+      checkStopped();
       JMSDestination queue = (JMSDestination) destinations.get(dest);
       if (queue == null)
          throw new InvalidDestinationException("That destination does not exist! " + dest);
@@ -641,80 +597,47 @@
       return ((JMSQueue) queue).browse(selector);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc                Description of Parameter
-    * @param subscriberId      Description of Parameter
-    * @param wait              Description of Parameter
-    * @return                  Description of the Returned Value
-    * @exception JMSException  Description of Exception
-    */
    public SpyMessage receive(ConnectionToken dc, int subscriberId, long wait) throws JMSException
    {
+      checkStopped();
       ClientConsumer clientConsumer = getClientConsumer(dc);
       SpyMessage msg = clientConsumer.receive(subscriberId, wait);
       return msg;
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc                Description of Parameter
-    * @param name              Description of Parameter
-    * @return                  Description of the Returned Value
-    * @exception JMSException  Description of Exception
-    */
    public Queue createQueue(ConnectionToken dc, String name) throws JMSException
    {
+      checkStopped();
       SpyQueue newQueue = new SpyQueue(name);
       if (!destinations.containsKey(newQueue))
-      {
-         throw new JMSException("This destination does not exist !");
-      }
+         throw new JMSException("This destination does not exist !" + newQueue);
       return newQueue;
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc                Description of Parameter
-    * @param name              Description of Parameter
-    * @return                  Description of the Returned Value
-    * @exception JMSException  Description of Exception
-    */
    public Topic createTopic(ConnectionToken dc, String name) throws JMSException
    {
+      checkStopped();
       SpyTopic newTopic = new SpyTopic(name);
       if (!destinations.containsKey(newTopic))
-      {
-         throw new JMSException("This destination does not exist !");
-      }
+         throw new JMSException("This destination does not exist !" + newTopic);
       return newTopic;
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc    Description of Parameter
-    * @param dest  Description of Parameter
-    */
-   public void deleteTemporaryDestination(ConnectionToken dc, SpyDestination dest)
-      throws JMSException
+   public void deleteTemporaryDestination(ConnectionToken dc, SpyDestination dest) throws JMSException
    {
+      checkStopped();
       JMSDestination destination = (JMSDestination) destinations.get(dest);
       if (destination == null)
          throw new InvalidDestinationException("That destination does not exist! " + destination);
 
       if (destination.isInUse())
          throw new JMSException("Cannot delete temporary queue, it is in use.");
-      
+
       destinations.remove(dest);
       deleteTemporaryDestination(dc, destination);
    }
 
-   protected void deleteTemporaryDestination(ConnectionToken dc, JMSDestination destination)
-      throws JMSException
+   protected void deleteTemporaryDestination(ConnectionToken dc, JMSDestination destination) throws JMSException
    {
       try
       {
@@ -722,45 +645,25 @@
       }
       catch (Exception e)
       {
-         log.error("An exception happened while removing all messages from temporary destination " 
-                   + destination.getSpyDestination().getName(), e);
+         log.error("An exception happened while removing all messages from temporary destination "
+               + destination.getSpyDestination().getName(), e);
       }
 
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param userName          Description of Parameter
-    * @param password          Description of Parameter
-    * @return                  Description of the Returned Value
-    * @exception JMSException  Description of Exception
-    */
    public String checkUser(String userName, String password) throws JMSException
    {
+      checkStopped();
       return stateManager.checkUser(userName, password);
    }
-   /**
-    * authenticate user and return a session id. Same as checkID.
-    *
-    * @param ID                Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
+
    public String authenticate(String id, String password) throws JMSException
    {
+      checkStopped();
       // do nothing
       return null;
    }
-   // Administration calls
-   /**
-    * Adds a feature to the Destination attribute of the JMSServer object
-    *
-    * @param topic             The feature to be added to the Destination
-    *      attribute
-    * @param queue             The feature to be added to the Destination
-    *      attribute
-    * @exception JMSException  Description of Exception
-    */
+
    public void addDestination(JMSDestination destination) throws JMSException
    {
       if (destinations.containsKey(destination.getSpyDestination()))
@@ -772,8 +675,7 @@
       // Restore the messages
       if (destination instanceof JMSTopic)
       {
-         Collection durableSubs =
-            getStateManager().getDurableSubscriptionIdsForTopic((SpyTopic) destination.getSpyDestination());
+         Collection durableSubs = getStateManager().getDurableSubscriptionIdsForTopic((SpyTopic) destination.getSpyDestination());
          for (Iterator i = durableSubs.iterator(); i.hasNext();)
          {
             DurableSubscriptionID sub = (DurableSubscriptionID) i.next();
@@ -796,7 +698,7 @@
          throw new InvalidDestinationException("This destination is not open! " + dest);
 
       log.debug("Closing destination " + dest);
-      
+
       // Add it to the closing list
       closingDestinations.put(dest, destination);
       try
@@ -809,25 +711,14 @@
       }
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @return   Description of the Returned Value
-    */
    public String toString()
    {
-      return JBOSS_VESION;
+      return JBOSS_VERSION;
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc                Description of Parameter
-    * @param clientTime        Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void ping(ConnectionToken dc, long clientTime) throws JMSException
    {
+      checkStopped();
       try
       {
          dc.clientIL.pong(System.currentTimeMillis());
@@ -858,11 +749,13 @@
 
    public SpyTopic getDurableTopic(DurableSubscriptionID sub) throws JMSException
    {
+      checkStopped();
       return getStateManager().getDurableTopic(sub);
    }
 
    public Subscription getSubscription(ConnectionToken dc, int subscriberId) throws JMSException
    {
+      checkStopped();
       ClientConsumer clientConsumer = getClientConsumer(dc);
       return clientConsumer.getSubscription(subscriberId);
    }
@@ -887,11 +780,7 @@
          for (int j = 0; j < counter.length; j++)
          {
             // sorting order name + subscription + type
-            String key =
-               counter[j].getDestinationName()
-                  + "-"
-                  + counter[j].getDestinationSubscription()
-                  + "-"
+            String key = counter[j].getDestinationName() + "-" + counter[j].getDestinationSubscription() + "-"
                   + (counter[j].getDestinationTopic() ? "Topic" : "Queue");
 
             map.put(key, counter[j]);
@@ -920,4 +809,9 @@
          }
       }
    }
+
+   public BasicQueueParameters getParameters()
+   {
+      return parameters;
+   }
 }

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/JMSQueue.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/JMSQueue.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/JMSQueue.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBossMQ, the OpenSource JMS implementation
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.server;
 
 import java.util.ArrayList;
@@ -14,6 +29,7 @@
 import org.jboss.mq.SpyJMSException;
 import org.jboss.mq.SpyMessage;
 import org.jboss.mq.Subscription;
+import org.jboss.mq.pm.Tx;
 
 /**
  *  This class is a message queue which is stored (hashed by Destination) on the
@@ -22,6 +38,7 @@
  * @author     Norbert Lataille (Norbert.Lataille at m4x.org)
  * @author     Hiram Chirino (Cojonudo14 at hotmail.com)
  * @author     David Maplesden (David.Maplesden at orion.co.nz)
+ * @author     Adrian Brock (adrian at jboss.com)
  * @created    August 16, 2001
  * @version    $Revision$
  */
@@ -30,7 +47,6 @@
 
    public BasicQueue queue;
 
-   // Constructor ---------------------------------------------------
    public JMSQueue(SpyDestination dest, ClientConsumer temporary, JMSDestinationManager server, BasicQueueParameters parameters) throws JMSException
    {
       super(dest, temporary, server, parameters);
@@ -126,13 +142,13 @@
       }
    }
 
-   public void restoreMessage(SpyMessage message)
+   public void restoreMessage(SpyMessage message, Tx txid, int type)
    {
       try
       {
          updateNextMessageId(message);
          MessageReference messageRef = server.getMessageCache().add(message, queue, MessageReference.STORED);
-         queue.restoreMessage(messageRef);
+         queue.restoreMessage(messageRef, txid, type);
       }
       catch (JMSException e)
       {

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/JMSServerInterceptorSupport.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/JMSServerInterceptorSupport.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/JMSServerInterceptorSupport.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,8 +1,23 @@
 /*
-* JBoss, the OpenSource EJB server
+* 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.
 *
-* Distributable under LGPL license.
-* See terms of license at gnu.org.
+* 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.mq.server;
 
@@ -12,11 +27,13 @@
 import javax.jms.TemporaryQueue;
 import javax.jms.TemporaryTopic;
 import javax.jms.Topic;
+import javax.transaction.xa.Xid;
 
 import org.jboss.logging.Logger;
 import org.jboss.mq.AcknowledgementRequest;
 import org.jboss.mq.ConnectionToken;
 import org.jboss.mq.DurableSubscriptionID;
+import org.jboss.mq.Recoverable;
 import org.jboss.mq.SpyDestination;
 import org.jboss.mq.SpyMessage;
 import org.jboss.mq.SpyTopic;
@@ -27,10 +44,10 @@
  * A pass through JMSServerInvoker.
  *
  * @author <a href="mailto:pra at tim.se">Peter Antman</a>
+ * @author <a href="adrian at jboss.org">Adrian Brock</a>
  * @version $Revision$
  */
-
-public class JMSServerInterceptorSupport implements JMSServerInterceptor
+public class JMSServerInterceptorSupport implements JMSServerInterceptor, Recoverable
 {
    protected Logger log;
    /**
@@ -43,267 +60,117 @@
       log = Logger.getLogger(this.getClass().getName());
    }
 
-   /**
-    * Set next invoker in chain to be called. Is mot often the real JMSServer
-    */
    public void setNext(JMSServerInterceptor server)
    {
       this.nextInterceptor = server;
    }
 
-   /**
-    * @see JMSServerInterceptor#getNext()
-    */
    public JMSServerInterceptor getNext()
    {
       return this.nextInterceptor;
    }
 
-   /**
-    * Get the thread group of the server.
-    */
    public ThreadGroup getThreadGroup()
    {
       return nextInterceptor.getThreadGroup();
    }
-   /**
-    * Gets a clientID from server.
-    *
-    * @return               The ID value
-    * @exception JMSException  Description of Exception
-    */
+
    public String getID() throws JMSException
    {
       String ID = nextInterceptor.getID();
       return ID;
    }
 
-   /**
-    * Gets the TemporaryTopic attribute of the ServerIL object
-    *
-    * @param dc             Description of Parameter
-    * @return               The TemporaryTopic value
-    * @exception JMSException  Description of Exception
-    */
    public TemporaryTopic getTemporaryTopic(ConnectionToken dc) throws JMSException
    {
       return nextInterceptor.getTemporaryTopic(dc);
    }
 
-   /**
-    * Gets the TemporaryQueue attribute of the ServerIL object
-    *
-    * @param dc             Description of Parameter
-    * @return               The TemporaryQueue value
-    * @exception JMSException  Description of Exception
-    */
    public TemporaryQueue getTemporaryQueue(ConnectionToken dc) throws JMSException
    {
       return nextInterceptor.getTemporaryQueue(dc);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void connectionClosing(ConnectionToken dc) throws JMSException
    {
       nextInterceptor.connectionClosing(dc);
    }
 
-   /**
-    * Check id, must not be taken.
-    *
-    * @param ID             a clientID
-    * @exception JMSException if ID is already taken
-    */
    public void checkID(String ID) throws JMSException
    {
       nextInterceptor.checkID(ID);
    }
 
-   /**
-    * Add the message to the destination.
-    *
-    * @param dc             The feature to be added to the Message attribute
-    * @param message        The feature to be added to the Message attribute
-    * @exception JMSException  Description of Exception
-    */
    public void addMessage(ConnectionToken dc, SpyMessage message) throws JMSException
    {
       nextInterceptor.addMessage(dc, message);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param dest           Description of Parameter
-    * @return               Description of the Returned Value
-    * @exception JMSException  Description of Exception
-    */
    public Queue createQueue(ConnectionToken dc, String dest) throws JMSException
    {
       return nextInterceptor.createQueue(dc, dest);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param dest           Description of Parameter
-    * @return               Description of the Returned Value
-    * @exception JMSException  Description of Exception
-    */
    public Topic createTopic(ConnectionToken dc, String dest) throws JMSException
    {
       return nextInterceptor.createTopic(dc, dest);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param dest           Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void deleteTemporaryDestination(ConnectionToken dc, SpyDestination dest) throws JMSException
    {
       nextInterceptor.deleteTemporaryDestination(dc, dest);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param t              Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void transact(ConnectionToken dc, TransactionRequest t) throws JMSException
    {
       nextInterceptor.transact(dc, t);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param item           Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void acknowledge(ConnectionToken dc, AcknowledgementRequest item) throws JMSException
    {
       nextInterceptor.acknowledge(dc, item);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param dest           Description of Parameter
-    * @param selector       Description of Parameter
-    * @return               Description of the Returned Value
-    * @exception JMSException  Description of Exception
-    */
    public SpyMessage[] browse(ConnectionToken dc, Destination dest, String selector) throws JMSException
    {
       return nextInterceptor.browse(dc, dest, selector);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param subscriberId   Description of Parameter
-    * @param wait           Description of Parameter
-    * @return               Description of the Returned Value
-    * @exception JMSException  Description of Exception
-    */
    public SpyMessage receive(ConnectionToken dc, int subscriberId, long wait) throws JMSException
    {
       return nextInterceptor.receive(dc, subscriberId, wait);
    }
 
-   /**
-    * Sets the Enabled attribute of the ServerIL object
-    *
-    * @param dc             The new Enabled value
-    * @param enabled        The new Enabled value
-    * @exception JMSException  Description of Exception
-    */
    public void setEnabled(ConnectionToken dc, boolean enabled) throws JMSException
    {
       nextInterceptor.setEnabled(dc, enabled);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc              Description of Parameter
-    * @param subscriptionId  Description of Parameter
-    * @exception JMSException   Description of Exception
-    */
    public void unsubscribe(ConnectionToken dc, int subscriptionId) throws JMSException
    {
       nextInterceptor.unsubscribe(dc, subscriptionId);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param id             Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void destroySubscription(ConnectionToken dc, DurableSubscriptionID id) throws JMSException
    {
       nextInterceptor.destroySubscription(dc, id);
    }
 
-   /**
-    * Check user for autentication.
-    *
-    * @param userName       Description of Parameter
-    * @param password       Description of Parameter
-    * @return               a clientId.
-    * @exception JMSException  if user was not allowed to login
-    */
    public String checkUser(String userName, String password) throws JMSException
    {
       return nextInterceptor.checkUser(userName, password);
    }
 
-   /**
-    * Check user for autentication.
-    *
-    * @param userName       Description of Parameter
-    * @param password       Description of Parameter
-    * @return               a sessionId
-    * @exception JMSException  if user was not allowed to login
-    */
    public String authenticate(String userName, String password) throws JMSException
    {
       return nextInterceptor.authenticate(userName, password);
    }
 
-   /**
-    * @param dc                       org.jboss.mq.ConnectionToken
-    * @param s                        org.jboss.mq.Subscription
-    * @exception JMSException  The exception description.
-    */
    public void subscribe(org.jboss.mq.ConnectionToken dc, org.jboss.mq.Subscription s) throws JMSException
    {
       nextInterceptor.subscribe(dc, s);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param clientTime     Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void ping(ConnectionToken dc, long clientTime) throws JMSException
    {
       nextInterceptor.ping(dc, clientTime);
@@ -319,4 +186,14 @@
       return nextInterceptor.getSubscription(dc, subscriberId);
    }
 
-} // JMSServerInvokerSupport
+   public Xid[] recover(ConnectionToken dc, int flags) throws Exception
+   {
+      JMSServerInterceptor next = nextInterceptor;
+      while (next != null && next instanceof Recoverable == false)
+         next = next.getNext();
+      if (next == null)
+         throw new IllegalStateException("No interceptor implements " + Recoverable.class.getName());
+      Recoverable recoverable = (Recoverable) next;
+      return recoverable.recover(dc, flags);
+   }
+}

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/JMSServerInvoker.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/JMSServerInvoker.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/JMSServerInvoker.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,8 +1,23 @@
 /*
-* JBoss, the OpenSource EJB server
+* 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.
 *
-* Distributable under LGPL license.
-* See terms of license at gnu.org.
+* 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.mq.server;
 
@@ -12,11 +27,13 @@
 import javax.jms.TemporaryQueue;
 import javax.jms.TemporaryTopic;
 import javax.jms.Topic;
+import javax.transaction.xa.Xid;
 
 import org.jboss.logging.Logger;
 import org.jboss.mq.AcknowledgementRequest;
 import org.jboss.mq.ConnectionToken;
 import org.jboss.mq.DurableSubscriptionID;
+import org.jboss.mq.Recoverable;
 import org.jboss.mq.SpyDestination;
 import org.jboss.mq.SpyMessage;
 import org.jboss.mq.SpyTopic;
@@ -28,10 +45,10 @@
  * A pass through JMSServerInvoker.
  *
  * @author <a href="mailto:pra at tim.se">Peter Antman</a>
+ * @author <a href="adrian at jboss.org">Adrian Brock</a>
  * @version $Revision$
  */
-
-public class JMSServerInvoker implements Invoker
+public class JMSServerInvoker implements Invoker, Recoverable
 {
    protected Logger log;
    /**
@@ -60,250 +77,106 @@
       return this.nextInterceptor;
    }
 
-   /**
-    * Get the thread group of the server.
-    */
    public ThreadGroup getThreadGroup()
    {
       return nextInterceptor.getThreadGroup();
    }
-   /**
-    * Gets a clientID from server.
-    *
-    * @return               The ID value
-    * @exception JMSException  Description of Exception
-    */
+
    public String getID() throws JMSException
    {
       return nextInterceptor.getID();
    }
 
-   /**
-    * Gets the TemporaryTopic attribute of the ServerIL object
-    *
-    * @param dc             Description of Parameter
-    * @return               The TemporaryTopic value
-    * @exception JMSException  Description of Exception
-    */
    public TemporaryTopic getTemporaryTopic(ConnectionToken dc) throws JMSException
    {
       return nextInterceptor.getTemporaryTopic(dc);
    }
 
-   /**
-    * Gets the TemporaryQueue attribute of the ServerIL object
-    *
-    * @param dc             Description of Parameter
-    * @return               The TemporaryQueue value
-    * @exception JMSException  Description of Exception
-    */
    public TemporaryQueue getTemporaryQueue(ConnectionToken dc) throws JMSException
    {
       return nextInterceptor.getTemporaryQueue(dc);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void connectionClosing(ConnectionToken dc) throws JMSException
    {
       nextInterceptor.connectionClosing(dc);
    }
 
-   /**
-    * Check id, must not be taken.
-    *
-    * @param ID             a clientID
-    * @exception JMSException if ID is already taken
-    */
    public void checkID(String ID) throws JMSException
    {
       nextInterceptor.checkID(ID);
    }
 
-   /**
-    * Add the message to the destination.
-    *
-    * @param dc             The feature to be added to the Message attribute
-    * @param message        The feature to be added to the Message attribute
-    * @exception JMSException  Description of Exception
-    */
    public void addMessage(ConnectionToken dc, SpyMessage message) throws JMSException
    {
       nextInterceptor.addMessage(dc, message);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param dest           Description of Parameter
-    * @return               Description of the Returned Value
-    * @exception JMSException  Description of Exception
-    */
    public Queue createQueue(ConnectionToken dc, String dest) throws JMSException
    {
       return nextInterceptor.createQueue(dc, dest);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param dest           Description of Parameter
-    * @return               Description of the Returned Value
-    * @exception JMSException  Description of Exception
-    */
    public Topic createTopic(ConnectionToken dc, String dest) throws JMSException
    {
       return nextInterceptor.createTopic(dc, dest);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param dest           Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void deleteTemporaryDestination(ConnectionToken dc, SpyDestination dest) throws JMSException
    {
       nextInterceptor.deleteTemporaryDestination(dc, dest);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param t              Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void transact(ConnectionToken dc, TransactionRequest t) throws JMSException
    {
       nextInterceptor.transact(dc, t);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param item           Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void acknowledge(ConnectionToken dc, AcknowledgementRequest item) throws JMSException
    {
       nextInterceptor.acknowledge(dc, item);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param dest           Description of Parameter
-    * @param selector       Description of Parameter
-    * @return               Description of the Returned Value
-    * @exception JMSException  Description of Exception
-    */
    public SpyMessage[] browse(ConnectionToken dc, Destination dest, String selector) throws JMSException
    {
       return nextInterceptor.browse(dc, dest, selector);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param subscriberId   Description of Parameter
-    * @param wait           Description of Parameter
-    * @return               Description of the Returned Value
-    * @exception JMSException  Description of Exception
-    */
    public SpyMessage receive(ConnectionToken dc, int subscriberId, long wait) throws JMSException
    {
       return nextInterceptor.receive(dc, subscriberId, wait);
    }
 
-   /**
-    * Sets the Enabled attribute of the ServerIL object
-    *
-    * @param dc             The new Enabled value
-    * @param enabled        The new Enabled value
-    * @exception JMSException  Description of Exception
-    */
    public void setEnabled(ConnectionToken dc, boolean enabled) throws JMSException
    {
       nextInterceptor.setEnabled(dc, enabled);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc              Description of Parameter
-    * @param subscriptionId  Description of Parameter
-    * @exception JMSException   Description of Exception
-    */
    public void unsubscribe(ConnectionToken dc, int subscriptionId) throws JMSException
    {
       nextInterceptor.unsubscribe(dc, subscriptionId);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param id             Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void destroySubscription(ConnectionToken dc, DurableSubscriptionID id) throws JMSException
    {
       nextInterceptor.destroySubscription(dc, id);
    }
 
-   /**
-    * Check user for autentication.
-    *
-    * @param userName       Description of Parameter
-    * @param password       Description of Parameter
-    * @return               a clientId.
-    * @exception JMSException  if user was not allowed to login
-    */
    public String checkUser(String userName, String password) throws JMSException
    {
       return nextInterceptor.checkUser(userName, password);
    }
 
-   /**
-    * Check user for autentication.
-    *
-    * @param userName       Description of Parameter
-    * @param password       Description of Parameter
-    * @return               a sessionId
-    * @exception JMSException  if user was not allowed to login
-    */
    public String authenticate(String userName, String password) throws JMSException
    {
       return nextInterceptor.authenticate(userName, password);
    }
 
-   /**
-    * @param dc                       org.jboss.mq.ConnectionToken
-    * @param s                        org.jboss.mq.Subscription
-    * @exception JMSException  The exception description.
-    */
    public void subscribe(org.jboss.mq.ConnectionToken dc, org.jboss.mq.Subscription s) throws JMSException
    {
       nextInterceptor.subscribe(dc, s);
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param clientTime     Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void ping(ConnectionToken dc, long clientTime) throws JMSException
    {
       nextInterceptor.ping(dc, clientTime);
@@ -319,4 +192,14 @@
       return nextInterceptor.getSubscription(dc, subscriberId);
    }
 
-} // JMSServerInvokerSupport
+   public Xid[] recover(ConnectionToken dc, int flags) throws Exception
+   {
+      JMSServerInterceptor next = nextInterceptor;
+      while (next != null && next instanceof Recoverable == false)
+         next = next.getNext();
+      if (next == null)
+         throw new IllegalStateException("No interceptor implements " + Recoverable.class.getName());
+      Recoverable recoverable = (Recoverable) next;
+      return recoverable.recover(dc, flags);
+   }
+}

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/JMSTopic.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/JMSTopic.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/JMSTopic.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,9 +1,24 @@
 /*
- * JBossMQ, the OpenSource JMS implementation
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.server;
 
 import java.util.ArrayList;
@@ -22,6 +37,7 @@
 import org.jboss.mq.Subscription;
 import org.jboss.mq.pm.NewPersistenceManager;
 import org.jboss.mq.pm.PersistenceManager;
+import org.jboss.mq.pm.Tx;
 
 import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap;
 
@@ -32,6 +48,7 @@
  * @author     Norbert Lataille (Norbert.Lataille at m4x.org)
  * @author     Hiram Chirino (Cojonudo14 at hotmail.com)
  * @author     David Maplesden (David.Maplesden at orion.co.nz)
+ * @author     Adrian Brock (adrian at jboss.com)
  * @created    August 16, 2001
  * @version    $Revision$
  */
@@ -42,7 +59,6 @@
    ConcurrentReaderHashMap durQueues = new ConcurrentReaderHashMap();
    ConcurrentReaderHashMap tempQueues = new ConcurrentReaderHashMap();
 
-   // Constructor ---------------------------------------------------
    public JMSTopic(SpyDestination dest, ClientConsumer temporary, JMSDestinationManager server, BasicQueueParameters parameters) throws JMSException
    {
       super(dest, temporary, server, parameters);
@@ -159,7 +175,14 @@
 
    public void removeReceiver(Subscription sub)
    {
-      getQueue(sub).removeReceiver(sub);
+      try
+      {
+         getQueue(sub).removeReceiver(sub);
+      }
+      catch (JMSException e)
+      {
+         cat.trace("Subscription is not registered: " + sub, e);
+      }
    }
 
    public void restoreMessage(MessageReference messageRef)
@@ -185,7 +208,7 @@
       }
    }
 
-   public void restoreMessage(SpyMessage message)
+   public void restoreMessage(SpyMessage message, Tx txid, int type)
    {
       try
       {
@@ -198,7 +221,7 @@
          {
             BasicQueue queue = (BasicQueue) durQueues.get(message.header.durableSubscriberID);
             MessageReference messageRef = server.getMessageCache().add(message, queue, MessageReference.STORED);
-            queue.restoreMessage(messageRef);
+            queue.restoreMessage(messageRef, txid, type);
          }
       }
       catch (JMSException e)
@@ -480,14 +503,20 @@
       return (PersistentQueue) durQueues.get(id);
    }
 
-   public BasicQueue getQueue(Subscription sub)
+   public BasicQueue getQueue(Subscription sub) throws JMSException
    {
       SpyTopic topic = (SpyTopic) sub.destination;
       DurableSubscriptionID id = topic.getDurableSubscriptionID();
+      BasicQueue queue = null;
       if (id != null)
-         return getDurableSubscription(id);
+         queue = getDurableSubscription(id);
       else
-         return (BasicQueue) tempQueues.get(sub);
+         queue = (BasicQueue) tempQueues.get(sub);
+      
+      if (queue != null)
+         return queue;
+      else
+         throw new JMSException("Subscription not found: " + sub);
    }
 
    // Package protected ---------------------------------------------

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/TracingInterceptor.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/TracingInterceptor.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/TracingInterceptor.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,8 +1,23 @@
 /*
-* JBoss, the OpenSource EJB server
+* 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.
 *
-* Distributable under LGPL license.
-* See terms of license at gnu.org.
+* 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.mq.server;
 
@@ -12,8 +27,8 @@
 import javax.jms.TemporaryQueue;
 import javax.jms.TemporaryTopic;
 import javax.jms.Topic;
+import javax.transaction.xa.Xid;
 
-import org.jboss.logging.Logger;
 import org.jboss.mq.AcknowledgementRequest;
 import org.jboss.mq.ConnectionToken;
 import org.jboss.mq.DurableSubscriptionID;
@@ -29,15 +44,8 @@
  * @author <a href="mailto:pra at tim.se">Peter Antman</a>
  * @version $Revision$
  */
-
 public class TracingInterceptor extends JMSServerInterceptorSupport
 {
-
-   static protected Logger log = Logger.getLogger(TracingInterceptor.class);
-
-   /**
-    * Get the thread group of the server.
-    */
    public ThreadGroup getThreadGroup()
    {
       if (!log.isTraceEnabled())
@@ -56,12 +64,7 @@
       }
    }
 
-   /**
-    * Gets a clientID from server.
-    *
-    * @return               The ID value
-    * @exception JMSException  Description of Exception
-    */
+
    public String getID() throws JMSException
    {
 
@@ -90,13 +93,6 @@
       }
    }
 
-   /**
-    * Gets the TemporaryTopic attribute of the ServerIL object
-    *
-    * @param dc             Description of Parameter
-    * @return               The TemporaryTopic value
-    * @exception JMSException  Description of Exception
-    */
    public TemporaryTopic getTemporaryTopic(ConnectionToken dc) throws JMSException
    {
 
@@ -127,13 +123,6 @@
 
    }
 
-   /**
-    * Gets the TemporaryQueue attribute of the ServerIL object
-    *
-    * @param dc             Description of Parameter
-    * @return               The TemporaryQueue value
-    * @exception JMSException  Description of Exception
-    */
    public TemporaryQueue getTemporaryQueue(ConnectionToken dc) throws JMSException
    {
 
@@ -164,12 +153,6 @@
 
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void connectionClosing(ConnectionToken dc) throws JMSException
    {
 
@@ -202,12 +185,6 @@
 
    }
 
-   /**
-    * Check id, must not be taken.
-    *
-    * @param ID             a clientID
-    * @exception JMSException if ID is already taken
-    */
    public void checkID(String ID) throws JMSException
    {
 
@@ -241,13 +218,6 @@
 
    }
 
-   /**
-    * Add the message to the destination.
-    *
-    * @param dc             The feature to be added to the Message attribute
-    * @param message        The feature to be added to the Message attribute
-    * @exception JMSException  Description of Exception
-    */
    public void addMessage(ConnectionToken dc, SpyMessage message) throws JMSException
    {
 
@@ -281,14 +251,6 @@
 
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param dest           Description of Parameter
-    * @return               Description of the Returned Value
-    * @exception JMSException  Description of Exception
-    */
    public Queue createQueue(ConnectionToken dc, String dest) throws JMSException
    {
 
@@ -320,14 +282,6 @@
 
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param dest           Description of Parameter
-    * @return               Description of the Returned Value
-    * @exception JMSException  Description of Exception
-    */
    public Topic createTopic(ConnectionToken dc, String dest) throws JMSException
    {
 
@@ -358,13 +312,6 @@
       }
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param dest           Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void deleteTemporaryDestination(ConnectionToken dc, SpyDestination dest) throws JMSException
    {
 
@@ -397,13 +344,6 @@
       }
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param t              Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void transact(ConnectionToken dc, TransactionRequest t) throws JMSException
    {
 
@@ -437,13 +377,6 @@
 
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param item           Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void acknowledge(ConnectionToken dc, AcknowledgementRequest item) throws JMSException
    {
 
@@ -477,15 +410,6 @@
 
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param dest           Description of Parameter
-    * @param selector       Description of Parameter
-    * @return               Description of the Returned Value
-    * @exception JMSException  Description of Exception
-    */
    public SpyMessage[] browse(ConnectionToken dc, Destination dest, String selector) throws JMSException
    {
 
@@ -518,15 +442,6 @@
 
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param subscriberId   Description of Parameter
-    * @param wait           Description of Parameter
-    * @return               Description of the Returned Value
-    * @exception JMSException  Description of Exception
-    */
    public SpyMessage receive(ConnectionToken dc, int subscriberId, long wait) throws JMSException
    {
 
@@ -559,13 +474,6 @@
 
    }
 
-   /**
-    * Sets the Enabled attribute of the ServerIL object
-    *
-    * @param dc             The new Enabled value
-    * @param enabled        The new Enabled value
-    * @exception JMSException  Description of Exception
-    */
    public void setEnabled(ConnectionToken dc, boolean enabled) throws JMSException
    {
 
@@ -599,13 +507,6 @@
 
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc              Description of Parameter
-    * @param subscriptionId  Description of Parameter
-    * @exception JMSException   Description of Exception
-    */
    public void unsubscribe(ConnectionToken dc, int subscriptionId) throws JMSException
    {
 
@@ -639,12 +540,6 @@
 
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param id             Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void destroySubscription(ConnectionToken dc, DurableSubscriptionID id) throws JMSException
    {
 
@@ -678,14 +573,6 @@
 
    }
 
-   /**
-    * Check user for autentication.
-    *
-    * @param userName       Description of Parameter
-    * @param password       Description of Parameter
-    * @return               a clientId.
-    * @exception JMSException  if user was not allowed to login
-    */
    public String checkUser(String userName, String password) throws JMSException
    {
 
@@ -718,14 +605,6 @@
 
    }
 
-   /**
-    * Check user for autentication.
-    *
-    * @param userName       Description of Parameter
-    * @param password       Description of Parameter
-    * @return               a sessionId
-    * @exception JMSException  if user was not allowed to login
-    */
    public String authenticate(String userName, String password) throws JMSException
    {
 
@@ -756,11 +635,6 @@
 
    }
 
-   /**
-    * @param dc                       org.jboss.mq.ConnectionToken
-    * @param s                        org.jboss.mq.Subscription
-    * @exception JMSException  The exception description.
-    */
    public void subscribe(org.jboss.mq.ConnectionToken dc, org.jboss.mq.Subscription s) throws JMSException
    {
 
@@ -794,13 +668,6 @@
 
    }
 
-   /**
-    * #Description of the Method
-    *
-    * @param dc             Description of Parameter
-    * @param clientTime     Description of Parameter
-    * @exception JMSException  Description of Exception
-    */
    public void ping(ConnectionToken dc, long clientTime) throws JMSException
    {
 
@@ -895,4 +762,31 @@
       }
 
    }
+
+   public Xid[] recover(ConnectionToken dc, int flags) throws Exception
+   {
+      if (log.isTraceEnabled() == false)
+         return super.recover(dc, flags);
+
+      try
+      {
+         log.trace("CALLED : recover");
+         log.trace("ARG    : " + flags);
+         return super.recover(dc, flags);
+      }
+      catch (JMSException e)
+      {
+         log.trace("EXCEPTION : recover: ", e);
+         throw e;
+      }
+      catch (RuntimeException e)
+      {
+         log.trace("EXCEPTION : recover: ", e);
+         throw e;
+      }
+      finally
+      {
+         log.trace("RETURN : recover");
+      }
+   }
 }

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/jmx/DestinationManager.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/jmx/DestinationManager.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/jmx/DestinationManager.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,13 +1,29 @@
 /*
- * JBoss, the OpenSource J2EE webOS
- * 
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-
+* 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.mq.server.jmx;
 
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
 import java.util.Map;
 import java.util.StringTokenizer;
 
@@ -15,9 +31,11 @@
 import javax.management.MBeanServer;
 import javax.management.MalformedObjectNameException;
 import javax.management.ObjectName;
+import javax.transaction.xa.Xid;
 
 import org.jboss.mq.MessageStatistics;
 import org.jboss.mq.pm.PersistenceManager;
+import org.jboss.mq.pm.TxManager;
 import org.jboss.mq.server.BasicQueueParameters;
 import org.jboss.mq.server.JMSDestinationManager;
 import org.jboss.mq.server.JMSServerInterceptor;
@@ -27,6 +45,10 @@
 import org.jboss.mq.sm.StateManager;
 import org.jboss.mx.util.MBeanProxyExt;
 import org.jboss.system.ServiceControllerMBean;
+import org.jboss.system.ServiceMBeanSupport;
+import org.jboss.util.JBossStringBuilder;
+import org.jboss.util.threadpool.BasicThreadPool;
+import org.jboss.util.threadpool.ThreadPool;
 
 /**
  * JMX MBean implementation for JBossMQ.
@@ -41,14 +63,12 @@
 {
    public String jndiBindLocation = "java:/JBossMQServer";
 
-   // Attributes ----------------------------------------------------
-
    /** A proxy to the service controller. */
    private ServiceControllerMBean serviceController;
    /** The JMX ObjectName of this service MBean */
    private ObjectName mqService;
    /** The JMS server implementation */
-   private JMSDestinationManager jmsServer;
+   protected JMSDestinationManager jmsServer;
    /** The JMX ObjectName of the configured persistence manager */
    private ObjectName persistenceManager;
    /** The JMX ObjectName of the configured state manager */
@@ -56,7 +76,11 @@
    /** The JMX ObjectName of the message cache */
    private ObjectName messageCache;
    /** The temporary topic/queue parameters */
-   private BasicQueueParameters tempParameters = new BasicQueueParameters();
+   protected BasicQueueParameters tempParameters = new BasicQueueParameters();
+   /** Default thread pool */
+   private ObjectName threadPool;
+   /** Default expiry destination */
+   private ObjectName expiryDestination;
 
    /**
     * @jmx:managed-attribute
@@ -219,6 +243,26 @@
       tempParameters.recoveryRetries = retries;
    }
    
+   public ObjectName getThreadPool()
+   {
+      return this.threadPool;
+   }
+
+   public void setThreadPool(ObjectName threadPool)
+   {
+      this.threadPool = threadPool;
+   }
+   
+   public ObjectName getExpiryDestination() 
+   {
+      return expiryDestination;
+   }
+
+   public void setExpiryDestination(ObjectName expiryDestination)
+   {
+      this.expiryDestination = expiryDestination;
+   }
+
    /**
     * @jmx:managed-operation
     */
@@ -359,13 +403,31 @@
 
       // We were either told the message cache or we get it from the
       // persistence manager
-      MessageCache mc = null;
+      MessageCache mc;
       if (messageCache != null)
          mc = (MessageCache) server.getAttribute(messageCache, "Instance");
       else
          mc = pm.getMessageCacheInstance();
       jmsServer.setMessageCache(mc);
 
+      ThreadPool tp;
+      ThreadGroup tg;
+      if (threadPool == null)
+      {
+         tg = new ThreadGroup("JBossMQ Server Threads");
+         tp = new BasicThreadPool("JMSThread", tg);
+      }
+      else
+      {
+         tp = (ThreadPool) server.getAttribute(threadPool, "Instance");
+         if (tp instanceof BasicThreadPool)
+           tg = ((BasicThreadPool)tp).getThreadGroup();
+         else
+           tg = new ThreadGroup("JBossMQ Server Threads");
+      }
+      jmsServer.setThreadPool(tp);
+      jmsServer.setThreadGroup(tg);
+
       jmsServer.startServer();
 
       super.startService();
@@ -614,4 +676,48 @@
       jmsServer.resetMessageCounter();
    }
 
+   public Map retrievePreparedTransactions()
+   {
+      if (jmsServer == null)
+         return null;
+      Map map = jmsServer.getPersistenceManager().getTxManager().getPreparedTransactions();
+      HashMap result = new HashMap();
+      for (Iterator i = map.entrySet().iterator(); i.hasNext();)
+      {
+         Map.Entry entry = (Map.Entry) i.next();
+         Xid xid = (Xid) entry.getKey();
+         TxManager.PreparedInfo info = (TxManager.PreparedInfo) entry.getValue();
+         if (xid != null && info != null)
+            result.put(xid, Boolean.valueOf(info.isInDoubt()));
+      }
+      return result;
+   }
+
+   public String showPreparedTransactions()
+   {
+      if (jmsServer == null)
+         return null;
+      Map map = jmsServer.getPersistenceManager().getTxManager().getPreparedTransactions();
+      JBossStringBuilder buffer = new JBossStringBuilder();
+      buffer.append("<table width=\"100%\" border=\"1\" cellpadding=\"1\" cellspacing=\"1\">");
+      buffer.append("<tr><th>Xid</th><th>In Doubt</th><th>Local TXIDs</th></tr>");
+      for (Iterator i = map.entrySet().iterator(); i.hasNext();)
+      {
+         Map.Entry entry = (Map.Entry) i.next();
+         Xid xid = (Xid) entry.getKey();
+         TxManager.PreparedInfo info = (TxManager.PreparedInfo) entry.getValue();
+         if (xid != null && info != null)
+         {
+            buffer.append("<tr><td>");
+            buffer.append(xid);
+            buffer.append("</td><td>");
+            buffer.append(info.isInDoubt());
+            buffer.append("</td><td>");
+            buffer.append(info.getTxids());
+            buffer.append("</td></tr>");
+         }
+      }
+      buffer.append("</table>");
+      return buffer.toString();
+   }
 }

Modified: branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/jmx/DestinationManagerMBean.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/jmx/DestinationManagerMBean.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/messaging/src/main/org/jboss/mq/server/jmx/DestinationManagerMBean.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,11 +1,30 @@
 /*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.server.jmx;
 
+import java.util.Map;
+
+import javax.management.ObjectName;
+
 /**
  * MBean interface.
  */
@@ -92,6 +111,26 @@
     */
    public void setRecoveryRetries(int retries);
 
+   /**
+    * Returns ThreadPool.
+    */
+   public ObjectName getThreadPool();
+
+   /**
+    * Sets ThreadPool.
+    */
+   public void setThreadPool(ObjectName threadPool);
+
+   /**
+    * Returns the expiry destination.
+    */
+   public ObjectName getExpiryDestination();
+
+   /**
+    * Sets the expiry destination.
+    */
+   public void setExpiryDestination(ObjectName destination);
+
    void createQueue(java.lang.String name) throws java.lang.Exception;
 
    void createTopic(java.lang.String name) throws java.lang.Exception;
@@ -135,5 +174,18 @@
     * Reset message counter of all configured destinations
     */
    void resetMessageCounter();
-
+   
+   /**
+    * Retrieve the prepared transactions
+    * 
+    * @return Map<Xid, indoubt boolean>
+    */
+   Map retrievePreparedTransactions(); 
+   
+   /**
+    * Show the prepared transactions
+    * 
+    * @return Some html
+    */
+   String showPreparedTransactions(); 
 }

Copied: branches/JBoss_4_0_3_SP1_CP/server/src/main/org/jboss/jms/recovery (from rev 55341, branches/JBoss_4_0_3_SP1_JBAS3259/server/src/main/org/jboss/jms/recovery)

Deleted: branches/JBoss_4_0_3_SP1_CP/server/src/main/org/jboss/jms/recovery/XAResourceWrapper.java
===================================================================
--- branches/JBoss_4_0_3_SP1_JBAS3259/server/src/main/org/jboss/jms/recovery/XAResourceWrapper.java	2006-08-05 15:39:32 UTC (rev 55341)
+++ branches/JBoss_4_0_3_SP1_CP/server/src/main/org/jboss/jms/recovery/XAResourceWrapper.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,376 +0,0 @@
-/*
-* JBoss, Home of Professional Open Source
-* Copyright 2006, 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.jms.recovery;
-
-import javax.jms.ExceptionListener;
-import javax.jms.JMSException;
-import javax.jms.XAConnection;
-import javax.jms.XAConnectionFactory;
-import javax.jms.XASession;
-import javax.naming.Context;
-import javax.naming.InitialContext;
-import javax.transaction.xa.XAException;
-import javax.transaction.xa.XAResource;
-import javax.transaction.xa.Xid;
-
-import org.jboss.jms.jndi.JMSProviderAdapter;
-import org.jboss.logging.Logger;
-import org.jboss.util.naming.Util;
-
-/**
- * XAResourceWrapper.
- * 
- * @author <a href="adrian at jboss.com">Adrian Brock</a>
- * @version $Revision$
- */
-public class XAResourceWrapper implements XAResource, ExceptionListener
-{
-   /** The log */
-   private static final Logger log = Logger.getLogger(XAResourceWrapper.class);
-
-   /** The jms provider name */
-   private String providerName;
-   
-   /** The state lock */
-   private static final Object lock = new Object();
-   
-   /** The connection */
-   private XAConnection connection;
-   
-   /** The delegate XAResource */
-   private XAResource delegate;
-
-   /**
-    * Get the providerName.
-    * 
-    * @return the providerName.
-    */
-   public String getProviderName()
-   {
-      return providerName;
-   }
-
-   /**
-    * Set the providerName.
-    * 
-    * @param providerName the providerName.
-    */
-   public void setProviderName(String providerName)
-   {
-      this.providerName = providerName;
-   }
-   
-   public Xid[] recover(int flag) throws XAException
-   {
-      log.debug("Recover " + providerName);
-      XAResource xaResource = getDelegate();
-      try
-      {
-         return xaResource.recover(flag);
-      }
-      catch (XAException e)
-      {
-         throw check(e);
-      }
-   }
-
-   public void commit(Xid xid, boolean onePhase) throws XAException
-   {
-      log.debug("Commit " + providerName + " xid " + " onePhase=" + onePhase);
-      XAResource xaResource = getDelegate();
-      try
-      {
-         xaResource.commit(xid, onePhase);
-      }
-      catch (XAException e)
-      {
-         throw check(e);
-      }
-   }
-
-   public void rollback(Xid xid) throws XAException
-   {
-      log.debug("Rollback " + providerName + " xid ");
-      XAResource xaResource = getDelegate();
-      try
-      {
-         xaResource.rollback(xid);
-      }
-      catch (XAException e)
-      {
-         throw check(e);
-      }
-   }
-
-   public void forget(Xid xid) throws XAException
-   {
-      log.debug("Forget " + providerName + " xid ");
-      XAResource xaResource = getDelegate();
-      try
-      {
-         xaResource.forget(xid);
-      }
-      catch (XAException e)
-      {
-         throw check(e);
-      }
-   }
-
-   public boolean isSameRM(XAResource xaRes) throws XAException
-   {
-      if (xaRes instanceof XAResourceWrapper)
-         xaRes = ((XAResourceWrapper) xaRes).getDelegate();
-
-      XAResource xaResource = getDelegate();
-      try
-      {
-         return xaResource.isSameRM(xaRes);
-      }
-      catch (XAException e)
-      {
-         throw check(e);
-      }
-   }
-
-   public int prepare(Xid xid) throws XAException
-   {
-      XAResource xaResource = getDelegate();
-      try
-      {
-         return xaResource.prepare(xid);
-      }
-      catch (XAException e)
-      {
-         throw check(e);
-      }
-   }
-
-   public void start(Xid xid, int flags) throws XAException
-   {
-      XAResource xaResource = getDelegate();
-      try
-      {
-         xaResource.start(xid, flags);
-      }
-      catch (XAException e)
-      {
-         throw check(e);
-      }
-   }
-
-   public void end(Xid xid, int flags) throws XAException
-   {
-      XAResource xaResource = getDelegate();
-      try
-      {
-         xaResource.end(xid, flags);
-      }
-      catch (XAException e)
-      {
-         throw check(e);
-      }
-   }
-
-   public int getTransactionTimeout() throws XAException
-   {
-      XAResource xaResource = getDelegate();
-      try
-      {
-         return xaResource.getTransactionTimeout();
-      }
-      catch (XAException e)
-      {
-         throw check(e);
-      }
-   }
-
-   public boolean setTransactionTimeout(int seconds) throws XAException
-   {
-      XAResource xaResource = getDelegate();
-      try
-      {
-         return xaResource.setTransactionTimeout(seconds);
-      }
-      catch (XAException e)
-      {
-         throw check(e);
-      }
-   }
-
-   public void onException(JMSException exception)
-   {
-      log.warn("Notified of connection failure in recovery delegate for provider " + providerName, exception);
-      close();
-   }
-   
-   /**
-    * Get the delegate XAResource
-    * 
-    * @return the delegate
-    * @throws XAException for any problem
-    */
-   public XAResource getDelegate() throws XAException
-   {
-      XAResource result = null;
-      Exception error = null;
-      try
-      {
-         result = connect();
-      }
-      catch (Exception e)
-      {
-         error = e;
-      }
-
-      if (result == null)
-      {
-         XAException xae = new XAException("Error trying to connect to provider " + providerName);
-         xae.errorCode = XAException.XAER_RMERR;
-         if (error != null)
-            xae.initCause(error);
-         log.debug("Cannot get delegate XAResource", xae);
-         throw xae;
-      }
-      
-      return result;
-   }
-   
-   /**
-    * Connect to the server if not already done so
-    * 
-    * @return the delegate XAResource
-    * @throws Exception for any problem
-    */
-   protected XAResource connect() throws Exception
-   {
-      // Do we already have a valid delegate?
-      synchronized (lock)
-      {
-         if (delegate != null)
-            return delegate;
-      }
-      
-      // Create the connection
-      XAConnection xaConnection = getConnectionFactory().createXAConnection();
-      synchronized (lock)
-      {
-         connection = xaConnection;
-      }
-
-      // Retrieve the delegate XAResource
-      try
-      {
-         XASession session = connection.createXASession();
-         XAResource result = session.getXAResource();
-         synchronized (lock)
-         {
-            delegate = result;
-         }
-         return delegate;
-      }
-      catch (Exception e)
-      {
-         close();
-         throw e;
-      }
-   }
-
-   /**
-    * Get the XAConnectionFactory
-    * 
-    * @return the connection
-    * @throws Exception for any problem
-    */
-   protected XAConnectionFactory getConnectionFactory() throws Exception
-   {
-      // Get the JMS Provider Adapter
-      if (providerName == null)
-         throw new IllegalArgumentException("Null provider name");
-      String providerAdapterJNDI = providerName;
-      if (providerAdapterJNDI.startsWith("java:") == false)
-         providerAdapterJNDI = "java:" + providerAdapterJNDI;
-      Context ctx = new InitialContext();
-      JMSProviderAdapter adapter = (JMSProviderAdapter) Util.lookup(providerAdapterJNDI, JMSProviderAdapter.class);
-
-      // Determine the XAConnectionFactory name
-      String connectionFactoryRef = adapter.getFactoryRef();
-      if (connectionFactoryRef == null)
-         throw new IllegalStateException("Provider '" + providerName + "' has no FactoryRef");
-      
-      // Lookup the connection factory
-      ctx = adapter.getInitialContext();
-      try
-      {
-         return (XAConnectionFactory) Util.lookup(ctx, connectionFactoryRef, XAConnectionFactory.class);
-      }
-      finally
-      {
-         ctx.close();
-      }
-   }
-   
-   /**
-    * Close the connection
-    */
-   public void close()
-   {
-      try
-      {
-         XAConnection oldConnection = null;
-         synchronized (lock)
-         {
-            oldConnection = connection;
-            connection = null;
-            delegate = null;
-         }
-         if (oldConnection != null)
-            oldConnection.close();
-      }
-      catch (Exception ignored)
-      {
-         log.trace("Ignored error during close", ignored);
-      }
-   }
-
-   /**
-    * Check whether an XAException is fatal. If it is an RM problem
-    * we close the connection so the next call will reconnect.
-    * 
-    * @param e the xa exception
-    * @return never
-    * @throws XAException always
-    */
-   protected XAException check(XAException e) throws XAException
-   {
-      if (e.errorCode == XAException.XAER_RMERR || e.errorCode == XAException.XAER_RMFAIL)
-      {
-         log.debug("Fatal error in provider " + providerName, e);
-         close();
-      }
-      throw e;
-   }
-
-   protected void finalize() throws Throwable
-   {
-      close();
-   }
-}

Copied: branches/JBoss_4_0_3_SP1_CP/server/src/main/org/jboss/jms/recovery/XAResourceWrapper.java (from rev 55341, branches/JBoss_4_0_3_SP1_JBAS3259/server/src/main/org/jboss/jms/recovery/XAResourceWrapper.java)

Modified: branches/JBoss_4_0_3_SP1_CP/testsuite/imports/test-jars.xml
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/testsuite/imports/test-jars.xml	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/testsuite/imports/test-jars.xml	2006-08-05 15:50:23 UTC (rev 55343)
@@ -2476,6 +2476,9 @@
       </fileset>
     </jar>
 
+     <copy tofile="${build.lib}/jbossmq-recovery-service.xml"
+           file="${build.resources}/jbossmq/jbossmq-recovery-service.xml"/>
+
      <copy tofile="${build.lib}/overridden-uil2-service.xml"
            file="${build.resources}/jbossmq/overridden-uil2-service.xml"/>
 

Copied: branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/jbossmq/test/RecoveryDurableTopicReceiveUnitTestCase.java (from rev 55341, branches/JBoss_4_0_3_SP1_JBAS3259/testsuite/src/main/org/jboss/test/jbossmq/test/RecoveryDurableTopicReceiveUnitTestCase.java)

Copied: branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/jbossmq/test/RecoveryDurableTopicSendUnitTestCase.java (from rev 55341, branches/JBoss_4_0_3_SP1_JBAS3259/testsuite/src/main/org/jboss/test/jbossmq/test/RecoveryDurableTopicSendUnitTestCase.java)

Copied: branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/jbossmq/test/RecoveryQueueReceiveUnitTestCase.java (from rev 55341, branches/JBoss_4_0_3_SP1_JBAS3259/testsuite/src/main/org/jboss/test/jbossmq/test/RecoveryQueueReceiveUnitTestCase.java)

Copied: branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/jbossmq/test/RecoveryQueueSendUnitTestCase.java (from rev 55341, branches/JBoss_4_0_3_SP1_JBAS3259/testsuite/src/main/org/jboss/test/jbossmq/test/RecoveryQueueSendUnitTestCase.java)

Copied: branches/JBoss_4_0_3_SP1_CP/testsuite/src/main/org/jboss/test/jbossmq/test/RecoveryTest.java (from rev 55341, branches/JBoss_4_0_3_SP1_JBAS3259/testsuite/src/main/org/jboss/test/jbossmq/test/RecoveryTest.java)

Copied: branches/JBoss_4_0_3_SP1_CP/testsuite/src/resources/jbossmq/jbossmq-recovery-service.xml (from rev 55341, branches/JBoss_4_0_3_SP1_JBAS3259/testsuite/src/resources/jbossmq/jbossmq-recovery-service.xml)

Modified: branches/JBoss_4_0_3_SP1_CP/varia/src/main/org/jboss/mq/il/http/servlet/HTTPServerILServlet.java
===================================================================
--- branches/JBoss_4_0_3_SP1_CP/varia/src/main/org/jboss/mq/il/http/servlet/HTTPServerILServlet.java	2006-08-05 15:47:42 UTC (rev 55342)
+++ branches/JBoss_4_0_3_SP1_CP/varia/src/main/org/jboss/mq/il/http/servlet/HTTPServerILServlet.java	2006-08-05 15:50:23 UTC (rev 55343)
@@ -1,50 +1,49 @@
 /*
- * JBoss, the OpenSource J2EE webOS
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
+* 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.mq.il.http.servlet;
 
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-
-import javax.naming.InitialContext;
-
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
 import javax.servlet.ServletConfig;
 import javax.servlet.ServletException;
-
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import javax.transaction.xa.Xid;
 
-import javax.management.MBeanServer;
-import javax.management.AttributeNotFoundException;
-import javax.management.ObjectName;
-import javax.management.MalformedObjectNameException;
-import javax.management.MBeanException;
-import javax.management.InstanceNotFoundException;
-import javax.management.ReflectionException;
-
 import org.jboss.logging.Logger;
-
 import org.jboss.mq.ConnectionToken;
+import org.jboss.mq.SpyMessage;
+import org.jboss.mq.il.http.HTTPClientILStorageQueue;
 import org.jboss.mq.il.http.HTTPILRequest;
 import org.jboss.mq.il.http.HTTPILResponse;
-import org.jboss.mq.il.http.HTTPClientIL;
-import org.jboss.mq.il.http.HTTPClientILStorageQueue;
-
+import org.jboss.mq.server.JMSServerInvoker;
 import org.jboss.mx.util.MBeanServerLocator;
-import org.jboss.mq.server.JMSServerInvoker;
-import org.jboss.mq.SpyMessage;
 
 /**
  * This Servlet acts as a proxy to the JMS Server for the HTTP IL clients.
@@ -230,6 +229,15 @@
                 this.invoker.unsubscribe(connectionToken, subscriberId);
                 outputStream.writeObject(new HTTPILResponse());
             }
+            else if (methodName.equals("recover"))
+            {
+                if (log.isTraceEnabled())
+                    log.trace("recover(HTTPILRequest " + httpIlRequest.toString() + ")");
+                ConnectionToken connectionToken = (ConnectionToken)httpIlRequest.getArguments()[0];
+                int flags = ((Integer)httpIlRequest.getArguments()[1]).intValue();
+                Xid[] xids = this.invoker.recover(connectionToken, flags);
+                outputStream.writeObject(new HTTPILResponse(xids));
+            }
             else
             {
                 if (log.isTraceEnabled())




More information about the jboss-cvs-commits mailing list