[Jboss-cvs] JBoss Messaging SVN: r1270 - in trunk: . src/etc/server/default/deploy src/etc/xmdesc src/main/org/jboss/jms/client/state src/main/org/jboss/jms/destination src/main/org/jboss/jms/server src/main/org/jboss/jms/server/connectionfactory src/main/org/jboss/jms/server/connectionmanager src/main/org/jboss/jms/server/connectormanager src/main/org/jboss/jms/server/destination src/main/org/jboss/jms/server/endpoint src/main/org/jboss/jms/server/plugin src/main/org/jboss/jms/server/plugin/contract src/main/org/jboss/messaging/core src/main/org/jboss/messaging/core/local src/main/org/jboss/messaging/core/memory src/main/org/jboss/messaging/core/plugin src/main/org/jboss/messaging/core/plugin/contract src/main/org/jboss/messaging/core/plugin/postoffice src/main/org/jboss/messaging/core/plugin/postoffice/cluster src/main/org/jboss/messaging/core/tx tests/src/org/jboss/test/messaging/core tests/src/org/jboss/test/messaging/core/base tests/src/org/jboss/test/messaging/core/local! tests/src/org/jboss/test/messaging/core/paging tests/src/org/jboss/test/messaging/core/plugin tests/src/org/jboss/test/messaging/core/plugin/base tests/src/org/jboss/test/messaging/jms tests/src/org/jboss/test/messaging/jms/persistence tests/src/org/jboss/test/messaging/jms/server/destination/base tests/src/org/jboss/test/messaging/tools/jmx/rmi

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Sat Sep 9 07:49:53 EDT 2006


Author: timfox
Date: 2006-09-09 07:48:48 -0400 (Sat, 09 Sep 2006)
New Revision: 1270

Added:
   trunk/src/etc/xmdesc/ClusteredPostOffice-xmbean.xml
   trunk/src/etc/xmdesc/SimplePostOffice-xmbean.xml
   trunk/src/main/org/jboss/jms/server/destination/ManagedDestination.java
   trunk/src/main/org/jboss/jms/server/destination/ManagedQueue.java
   trunk/src/main/org/jboss/jms/server/destination/ManagedTopic.java
   trunk/src/main/org/jboss/jms/server/destination/QueueService.java
   trunk/src/main/org/jboss/jms/server/destination/TopicService.java
   trunk/src/main/org/jboss/jms/server/plugin/JDBCJMSUserManagerService.java
   trunk/src/main/org/jboss/messaging/core/local/Queue.java
   trunk/src/main/org/jboss/messaging/core/plugin/ClusteredPostOfficeService.java
   trunk/src/main/org/jboss/messaging/core/plugin/JDBCMBeanSupport.java
   trunk/src/main/org/jboss/messaging/core/plugin/JDBCPersistenceManagerService.java
   trunk/src/main/org/jboss/messaging/core/plugin/JDBCShutdownLoggerService.java
   trunk/src/main/org/jboss/messaging/core/plugin/JDBCSupport.java
   trunk/src/main/org/jboss/messaging/core/plugin/SimplePostOfficeService.java
   trunk/src/main/org/jboss/messaging/core/plugin/contract/Binding.java
   trunk/src/main/org/jboss/messaging/core/plugin/contract/ClusteredPostOffice.java
   trunk/src/main/org/jboss/messaging/core/plugin/contract/MessagingComponent.java
   trunk/src/main/org/jboss/messaging/core/plugin/contract/MessagingService.java
   trunk/src/main/org/jboss/messaging/core/plugin/contract/PostOffice.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/BindingImpl.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/PostOfficeImpl.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/BindRequest.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/CastMessagesCallback.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/CheckMessage.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusterRequest.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredPostOfficeImpl.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ExchangeInternal.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/MessageHolder.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/MessageRequest.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/MessagesRequest.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/SendNodeIdRequest.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/SharedState.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/TransactionId.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/TransactionRequest.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/UnbindRequest.java
   trunk/tests/src/org/jboss/test/messaging/core/base/QueueTestBase.java
   trunk/tests/src/org/jboss/test/messaging/core/local/NonRecoverableQueueTest.java
   trunk/tests/src/org/jboss/test/messaging/core/local/QueueWithFilterTest.java
   trunk/tests/src/org/jboss/test/messaging/core/local/RecoverableQueueTest.java
   trunk/tests/src/org/jboss/test/messaging/core/plugin/ClusteredPostOfficeTest.java
   trunk/tests/src/org/jboss/test/messaging/core/plugin/SimplePostOfficeTest.java
Removed:
   trunk/src/etc/xmdesc/Exchange-xmbean.xml
   trunk/src/main/org/jboss/jms/server/destination/Queue.java
   trunk/src/main/org/jboss/jms/server/destination/Topic.java
   trunk/src/main/org/jboss/messaging/core/local/MessageQueue.java
   trunk/src/main/org/jboss/messaging/core/plugin/contract/Exchange.java
   trunk/src/main/org/jboss/messaging/core/plugin/exchange/
   trunk/tests/src/org/jboss/test/messaging/core/base/MessageQueueTestBase.java
   trunk/tests/src/org/jboss/test/messaging/core/local/MessageQueueWithFilterTest.java
   trunk/tests/src/org/jboss/test/messaging/core/local/NonRecoverableMessageQueueTest.java
   trunk/tests/src/org/jboss/test/messaging/core/local/RecoverableMessageQueueTest.java
   trunk/tests/src/org/jboss/test/messaging/core/plugin/ClusteredTopicExchangeTest.java
   trunk/tests/src/org/jboss/test/messaging/core/plugin/DirectExchangeTest.java
   trunk/tests/src/org/jboss/test/messaging/core/plugin/TopicExchangeTest.java
   trunk/tests/src/org/jboss/test/messaging/core/plugin/base/ExchangeTestBase.java
Modified:
   trunk/.classpath
   trunk/src/etc/server/default/deploy/destinations-service.xml
   trunk/src/etc/server/default/deploy/hsqldb-persistence-service.xml
   trunk/src/etc/server/default/deploy/messaging-service.xml
   trunk/src/etc/xmdesc/JDBCPersistenceManager-xmbean.xml
   trunk/src/etc/xmdesc/JDBCShutdownLogger-xmbean.xml
   trunk/src/etc/xmdesc/JMSUserManager-xmbean.xml
   trunk/src/etc/xmdesc/Queue-xmbean.xml
   trunk/src/etc/xmdesc/ServerPeer-xmbean.xml
   trunk/src/etc/xmdesc/Topic-xmbean.xml
   trunk/src/main/org/jboss/jms/client/state/ConsumerState.java
   trunk/src/main/org/jboss/jms/destination/JBossDestination.java
   trunk/src/main/org/jboss/jms/destination/JBossQueue.java
   trunk/src/main/org/jboss/jms/destination/JBossTemporaryTopic.java
   trunk/src/main/org/jboss/jms/destination/JBossTopic.java
   trunk/src/main/org/jboss/jms/server/ConnectionFactoryManager.java
   trunk/src/main/org/jboss/jms/server/ConnectionManager.java
   trunk/src/main/org/jboss/jms/server/ConnectorManager.java
   trunk/src/main/org/jboss/jms/server/DestinationJNDIMapper.java
   trunk/src/main/org/jboss/jms/server/DestinationManager.java
   trunk/src/main/org/jboss/jms/server/ServerPeer.java
   trunk/src/main/org/jboss/jms/server/connectionfactory/ConnectionFactoryJNDIMapper.java
   trunk/src/main/org/jboss/jms/server/connectionmanager/SimpleConnectionManager.java
   trunk/src/main/org/jboss/jms/server/connectormanager/SimpleConnectorManager.java
   trunk/src/main/org/jboss/jms/server/destination/DestinationServiceSupport.java
   trunk/src/main/org/jboss/jms/server/endpoint/ServerBrowserEndpoint.java
   trunk/src/main/org/jboss/jms/server/endpoint/ServerConnectionEndpoint.java
   trunk/src/main/org/jboss/jms/server/endpoint/ServerConnectionFactoryEndpoint.java
   trunk/src/main/org/jboss/jms/server/endpoint/ServerConsumerEndpoint.java
   trunk/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java
   trunk/src/main/org/jboss/jms/server/plugin/JDBCJMSUserManager.java
   trunk/src/main/org/jboss/jms/server/plugin/contract/JMSUserManager.java
   trunk/src/main/org/jboss/messaging/core/Channel.java
   trunk/src/main/org/jboss/messaging/core/ChannelSupport.java
   trunk/src/main/org/jboss/messaging/core/Distributor.java
   trunk/src/main/org/jboss/messaging/core/Filter.java
   trunk/src/main/org/jboss/messaging/core/MessageReference.java
   trunk/src/main/org/jboss/messaging/core/Receiver.java
   trunk/src/main/org/jboss/messaging/core/Router.java
   trunk/src/main/org/jboss/messaging/core/local/FirstReceiverPointToPointRouter.java
   trunk/src/main/org/jboss/messaging/core/local/RoundRobinPointToPointRouter.java
   trunk/src/main/org/jboss/messaging/core/memory/MemoryManager.java
   trunk/src/main/org/jboss/messaging/core/plugin/IdManager.java
   trunk/src/main/org/jboss/messaging/core/plugin/JDBCPersistenceManager.java
   trunk/src/main/org/jboss/messaging/core/plugin/JDBCServiceSupport.java
   trunk/src/main/org/jboss/messaging/core/plugin/JDBCShutdownLogger.java
   trunk/src/main/org/jboss/messaging/core/plugin/SimpleMessageStore.java
   trunk/src/main/org/jboss/messaging/core/plugin/contract/MessageStore.java
   trunk/src/main/org/jboss/messaging/core/plugin/contract/PersistenceManager.java
   trunk/src/main/org/jboss/messaging/core/plugin/contract/ServerPlugin.java
   trunk/src/main/org/jboss/messaging/core/plugin/contract/ShutdownLogger.java
   trunk/src/main/org/jboss/messaging/core/tx/TransactionRepository.java
   trunk/tests/src/org/jboss/test/messaging/core/BrokenReceiver.java
   trunk/tests/src/org/jboss/test/messaging/core/SimpleChannel.java
   trunk/tests/src/org/jboss/test/messaging/core/SimpleDeliveryTest.java
   trunk/tests/src/org/jboss/test/messaging/core/SimpleReceiver.java
   trunk/tests/src/org/jboss/test/messaging/core/local/RoundRobinPointToPointRouterTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_2PCTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_NTTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_TTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_2PCTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_NTTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_TTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/PagingStateTestBase.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/PagingTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_2PCTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_NTTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_TTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_2PCTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_NTTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_TTest.java
   trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_ReloadTest.java
   trunk/tests/src/org/jboss/test/messaging/core/plugin/IdManagerTest.java
   trunk/tests/src/org/jboss/test/messaging/core/plugin/JDBCPersistenceManagerTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/AcknowledgementTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/persistence/MessagePersistenceManagerTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/server/destination/base/DestinationManagementTestBase.java
   trunk/tests/src/org/jboss/test/messaging/tools/jmx/rmi/LocalTestServer.java
   trunk/tests/src/org/jboss/test/messaging/tools/jmx/rmi/RMITestServer.java
   trunk/tests/src/org/jboss/test/messaging/tools/jmx/rmi/RemoteTestServer.java
   trunk/tests/src/org/jboss/test/messaging/tools/jmx/rmi/Server.java
Log:
More clustering work



Modified: trunk/.classpath
===================================================================
--- trunk/.classpath	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/.classpath	2006-09-09 11:48:48 UTC (rev 1270)
@@ -27,13 +27,13 @@
 	<classpathentry kind="lib" path="perf/resources/jcommon-1.0.0-rc1.jar"/>
 	<classpathentry kind="lib" path="perf/resources/jfreechart-1.0.0-rc1.jar"/>
 	<classpathentry kind="lib" path="thirdparty/apache-log4j/lib/log4j.jar"/>
-	<classpathentry kind="lib" path="C:/dev/messaging/trunk/thirdparty/jboss/remoting/lib/jboss-remoting.jar"/>
 	<classpathentry kind="lib" path="thirdparty/jboss/aop/lib/jboss-aop.jar"/>
-	<classpathentry kind="lib" path="C:/dev/messaging/trunk/thirdparty/jboss/serialization/lib/jboss-serialization.jar"/>
 	<classpathentry kind="lib" path="thirdparty/junit/lib/junit.jar"/>
 	<classpathentry kind="lib" path="thirdparty/jboss/profiler/jvmti/lib/jboss-profiler-jvmti.jar"/>
 	<classpathentry kind="lib" path="thirdparty/hsqldb/lib/hsqldb.jar"/>
 	<classpathentry kind="lib" path="C:/tools/apache-ant-1.6.5/lib/ant-junit.jar"/>
 	<classpathentry kind="lib" path="thirdparty/apache-logging/lib/commons-logging.jar"/>
+	<classpathentry kind="lib" path="thirdparty/jboss/remoting/lib/jboss-remoting.jar"/>
+	<classpathentry kind="lib" path="thirdparty/jboss/serialization/lib/jboss-serialization.jar"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>

Modified: trunk/src/etc/server/default/deploy/destinations-service.xml
===================================================================
--- trunk/src/etc/server/default/deploy/destinations-service.xml	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/etc/server/default/deploy/destinations-service.xml	2006-09-09 11:48:48 UTC (rev 1270)
@@ -12,7 +12,7 @@
       The Dead Letter Queue. This destination is a dependency of an EJB MDB container.
    -->
 
-   <mbean code="org.jboss.jms.server.destination.Queue"
+   <mbean code="org.jboss.jms.server.destination.QueueService"
       name="jboss.messaging.destination:service=Queue,name=DLQ"
       xmbean-dd="xmdesc/Queue-xmbean.xml">
       <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
@@ -22,7 +22,7 @@
       Example destinations.
    -->
 
-   <mbean code="org.jboss.jms.server.destination.Topic"
+   <mbean code="org.jboss.jms.server.destination.TopicService"
       name="jboss.messaging.destination:service=Topic,name=testTopic"
       xmbean-dd="xmdesc/Topic-xmbean.xml">
       <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
@@ -35,7 +35,7 @@
       </attribute>
    </mbean>
 
-   <mbean code="org.jboss.jms.server.destination.Topic"
+   <mbean code="org.jboss.jms.server.destination.TopicService"
       name="jboss.messaging.destination:service=Topic,name=securedTopic"
       xmbean-dd="xmdesc/Topic-xmbean.xml">
       <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
@@ -46,7 +46,7 @@
       </attribute>
    </mbean>
 
-   <mbean code="org.jboss.jms.server.destination.Topic"
+   <mbean code="org.jboss.jms.server.destination.TopicService"
       name="jboss.messaging.destination:service=Topic,name=testDurableTopic"
       xmbean-dd="xmdesc/Topic-xmbean.xml">
       <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
@@ -59,7 +59,7 @@
       </attribute>
    </mbean>
 
-   <mbean code="org.jboss.jms.server.destination.Queue"
+   <mbean code="org.jboss.jms.server.destination.QueueService"
       name="jboss.messaging.destination:service=Queue,name=testQueue"
       xmbean-dd="xmdesc/Queue-xmbean.xml">
       <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
@@ -72,37 +72,37 @@
       </attribute>
    </mbean>
 
-   <mbean code="org.jboss.jms.server.destination.Queue"
+   <mbean code="org.jboss.jms.server.destination.QueueService"
       name="jboss.messaging.destination:service=Queue,name=A"
       xmbean-dd="xmdesc/Queue-xmbean.xml">
       <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
    </mbean>
 
-   <mbean code="org.jboss.jms.server.destination.Queue"
+   <mbean code="org.jboss.jms.server.destination.QueueService"
       name="jboss.messaging.destination:service=Queue,name=B"
       xmbean-dd="xmdesc/Queue-xmbean.xml">
       <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
    </mbean>
 
-   <mbean code="org.jboss.jms.server.destination.Queue"
+   <mbean code="org.jboss.jms.server.destination.QueueService"
       name="jboss.messaging.destination:service=Queue,name=C"
       xmbean-dd="xmdesc/Queue-xmbean.xml">
       <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
    </mbean>
 
-   <mbean code="org.jboss.jms.server.destination.Queue"
+   <mbean code="org.jboss.jms.server.destination.QueueService"
       name="jboss.messaging.destination:service=Queue,name=D"
       xmbean-dd="xmdesc/Queue-xmbean.xml">
       <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
    </mbean>
 
-   <mbean code="org.jboss.jms.server.destination.Queue"
+   <mbean code="org.jboss.jms.server.destination.QueueService"
       name="jboss.messaging.destination:service=Queue,name=ex"
       xmbean-dd="xmdesc/Queue-xmbean.xml">
       <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
    </mbean>
    
-   <mbean code="org.jboss.jms.server.destination.Topic"
+   <mbean code="org.jboss.jms.server.destination.QueueService"
       name="jboss.messaging.destination:service=Queue,name=openTopic"
       xmbean-dd="xmdesc/Topic-xmbean.xml">
       <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
@@ -112,5 +112,21 @@
          </security>
       </attribute>
    </mbean>
+   
+   <!-- Example clustered destinations -->
+   
+   <mbean code="org.jboss.jms.server.destination.QueueService"
+      name="jboss.messaging.destination:service=Queue,name=ClusteredQueue1"
+      xmbean-dd="xmdesc/Queue-xmbean.xml">
+      <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
+      <attribute name="Clustered">true</attribute>
+   </mbean>   
+   
+   <mbean code="org.jboss.jms.server.destination.TopicService"
+      name="jboss.messaging.destination:service=Topic,name=ClusteredTopic1"
+      xmbean-dd="xmdesc/Topic-xmbean.xml">
+      <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
+      <attribute name="Clustered">true</attribute>
+   </mbean>   
 
 </server>
\ No newline at end of file

Modified: trunk/src/etc/server/default/deploy/hsqldb-persistence-service.xml
===================================================================
--- trunk/src/etc/server/default/deploy/hsqldb-persistence-service.xml	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/etc/server/default/deploy/hsqldb-persistence-service.xml	2006-09-09 11:48:48 UTC (rev 1270)
@@ -8,7 +8,7 @@
 
 <server>
 
-   <mbean code="org.jboss.messaging.core.plugin.JDBCPersistenceManager"
+   <mbean code="org.jboss.messaging.core.plugin.JDBCPersistenceManagerService"
       name="jboss.messaging:service=PersistenceManager"
       xmbean-dd="xmdesc/JDBCPersistenceManager-xmbean.xml">
       <!-- TODO this insures the fact that dependency exists. However I need to redundantly specifiy
@@ -21,40 +21,115 @@
       <attribute name="UsingBatchUpdates">true</attribute>
    </mbean>
 
-   <mbean code="org.jboss.messaging.core.plugin.exchange.DirectExchange"
-      name="jboss.messaging:service=DirectExchange"
-      xmbean-dd="xmdesc/Exchange-xmbean.xml">
-      <!-- TODO this insures the fact that dependency exists. However I need to redundantly specifiy
-           the DataSource JNDI name in order to actually get a reference to it. Fix this.
-      -->   
+   <mbean code="org.jboss.messaging.core.plugin.SimplePostOfficeService"
+      name="jboss.messaging:service=QueuePostOffice"
+      xmbean-dd="xmdesc/SimplePostOffice-xmbean.xml"> 
+      <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends> 
       <depends>jboss.jca:service=DataSourceBinding,name=DefaultDS</depends>
       <depends optional-attribute-name="TransactionManager">jboss:service=TransactionManager</depends>
+      <attribute name="PostOfficeName">Queue</attribute>
       <attribute name="DataSource">java:/DefaultDS</attribute>
       <attribute name="CreateTablesOnStartup">true</attribute>
    </mbean>
    
-	<mbean code="org.jboss.messaging.core.plugin.exchange.TopicExchange"
-      name="jboss.messaging:service=TopicExchange"
-      xmbean-dd="xmdesc/Exchange-xmbean.xml">
-      <!-- TODO this insures the fact that dependency exists. However I need to redundantly specifiy
-           the DataSource JNDI name in order to actually get a reference to it. Fix this.
-      -->   
+   <mbean code="org.jboss.messaging.core.plugin.SimplePostOfficeService"
+      name="jboss.messaging:service=TopicPostOffice"
+      xmbean-dd="xmdesc/SimplePostOffice-xmbean.xml"> 
+      <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
       <depends>jboss.jca:service=DataSourceBinding,name=DefaultDS</depends>
       <depends optional-attribute-name="TransactionManager">jboss:service=TransactionManager</depends>
+      <attribute name="PostOfficeName">Topic</attribute>
       <attribute name="DataSource">java:/DefaultDS</attribute>
       <attribute name="CreateTablesOnStartup">true</attribute>
    </mbean> 
    
-   <mbean code="org.jboss.jms.server.plugin.JDBCJMSUserManager"
+   <!--
+   
+   Uncomment this and comment out the one above to enable clustered topics
+   
+   <mbean code="org.jboss.messaging.core.plugin.ClusteredTopicPostOfficeService"
+      name="jboss.messaging:service=TopicPostOffice"
+      xmbean-dd="xmdesc/ClusteredTopicPostOffice-xmbean.xml"> 
+      <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
+      <depends>jboss.jca:service=DataSourceBinding,name=DefaultDS</depends>
+      <depends optional-attribute-name="TransactionManager">jboss:service=TransactionManager</depends>
+      <attribute name="PostOfficeName">Clustered Topic</attribute>
+      <attribute name="DataSource">java:/DefaultDS</attribute>
+      <attribute name="CreateTablesOnStartup">true</attribute>      
+      <attribute name="GroupName">cluster1</attribute>
+      <attribute name="StateTimeout">5000</attribute>
+      <attribute name="CastTimeout">5000</attribute>
+      <attribute name="SyncChannelConfig">
+         <UDP mcast_addr="228.8.8.8" mcast_port="45568"
+              ip_ttl="8" ip_mcast="true"
+              mcast_send_buf_size="800000" mcast_recv_buf_size="150000"
+              ucast_send_buf_size="800000" ucast_recv_buf_size="150000"
+              loopback="false"/>
+         <PING timeout="2000" num_initial_members="3"
+              up_thread="true" down_thread="true"/>
+         <MERGE2 min_interval="10000" max_interval="20000"/>
+         <FD shun="true" up_thread="true" down_thread="true"
+              timeout="2500" max_tries="5"/>
+         <VERIFY_SUSPECT timeout="3000" num_msgs="3"
+              up_thread="true" down_thread="true"/>
+         <pbcast.NAKACK gc_lag="50" retransmit_timeout="300,600,1200,2400,4800"
+              max_xmit_size="8192"
+              up_thread="true" down_thread="true"/>
+         <pbcast.STABLE desired_avg_gossip="20000"
+              up_thread="true" down_thread="true"/>
+         <FRAG frag_size="8192"
+              down_thread="true" up_thread="true"/>
+         <pbcast.GMS join_timeout="5000" join_retry_timeout="2000"
+              shun="true" print_local_addr="true"/>
+         <pbcast.STATE_TRANSFER up_thread="true" down_thread="true"/>
+      </attribute>      
+      
+      TODO
+      Do we need failure detection and group management in this stack ?? 
+      
+      <attribute name="AsyncChannelConfig">
+         <UDP mcast_addr="228.8.8.8" mcast_port="45569"
+              ip_ttl="8" ip_mcast="true"
+              mcast_send_buf_size="800000" mcast_recv_buf_size="150000"
+              ucast_send_buf_size="800000" ucast_recv_buf_size="150000"
+              loopback="false"/>
+         <PING timeout="2000" num_initial_members="3"
+              up_thread="true" down_thread="true"/>
+         <MERGE2 min_interval="10000" max_interval="20000"/>
+         <FD shun="true" up_thread="true" down_thread="true"
+              timeout="2500" max_tries="5"/>
+         <VERIFY_SUSPECT timeout="3000" num_msgs="3"
+              up_thread="true" down_thread="true"/>
+         <pbcast.NAKACK gc_lag="50" retransmit_timeout="300,600,1200,2400,4800"
+              max_xmit_size="8192"
+              up_thread="true" down_thread="true"/>
+         <pbcast.STABLE desired_avg_gossip="20000"
+              up_thread="true" down_thread="true"/>
+         <FRAG frag_size="8192"
+              down_thread="true" up_thread="true"/>
+         <pbcast.GMS join_timeout="5000" join_retry_timeout="2000"
+              shun="true" print_local_addr="true"/>
+      </attribute>      
+   </mbean>
+   
+   -->
+   
+   <mbean code="org.jboss.jms.server.plugin.JDBCJMSUserManagerService"
       name="jboss.messaging:service=JMSUserManager"
       xmbean-dd="xmdesc/JMSUserManager-xmbean.xml">
-      <!-- TODO this insures the fact that dependency exists. However I need to redundantly specifiy
-           the DataSource JNDI name in order to actually get a reference to it. Fix this.
-      -->   
       <depends>jboss.jca:service=DataSourceBinding,name=DefaultDS</depends>
       <depends optional-attribute-name="TransactionManager">jboss:service=TransactionManager</depends>
       <attribute name="DataSource">java:/DefaultDS</attribute>
       <attribute name="CreateTablesOnStartup">true</attribute>
+   </mbean>    
+   
+	<mbean code="org.jboss.messaging.core.plugin.JDBCShutdownLoggerService"
+      name="jboss.messaging:service=ShutdownLogger"
+      xmbean-dd="xmdesc/JDBCShutdownLogger-xmbean.xml">
+      <depends>jboss.jca:service=DataSourceBinding,name=DefaultDS</depends>
+      <depends optional-attribute-name="TransactionManager">jboss:service=TransactionManager</depends>
+      <attribute name="DataSource">java:/DefaultDS</attribute>
+      <attribute name="CreateTablesOnStartup">true</attribute>
    </mbean>              
    
 </server>
\ No newline at end of file

Modified: trunk/src/etc/server/default/deploy/messaging-service.xml
===================================================================
--- trunk/src/etc/server/default/deploy/messaging-service.xml	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/etc/server/default/deploy/messaging-service.xml	2006-09-09 11:48:48 UTC (rev 1270)
@@ -22,8 +22,8 @@
       </constructor>
 
       <depends optional-attribute-name="PersistenceManager">jboss.messaging:service=PersistenceManager</depends>
-      <depends optional-attribute-name="DirectExchange">jboss.messaging:service=DirectExchange</depends>
-      <depends optional-attribute-name="TopicExchange">jboss.messaging:service=TopicExchange</depends>
+      <depends optional-attribute-name="QueuePostOffice">jboss.messaging:service=QueuePostOffice</depends>
+      <depends optional-attribute-name="TopicPostOffice">jboss.messaging:service=TopicPostOffice</depends>     
       <depends optional-attribute-name="JMSUserManager">jboss.messaging:service=JMSUserManager</depends>
 	   <depends optional-attribute-name="ShutdownLogger">jboss.messaging:service=ShutdownLogger</depends>
 

Added: trunk/src/etc/xmdesc/ClusteredPostOffice-xmbean.xml
===================================================================
--- trunk/src/etc/xmdesc/ClusteredPostOffice-xmbean.xml	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/etc/xmdesc/ClusteredPostOffice-xmbean.xml	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+   <!DOCTYPE mbean PUBLIC
+      "-//JBoss//DTD JBOSS XMBEAN 1.2//EN"
+      "http://www.jboss.org/j2ee/dtd/jboss_xmbean_1_2.dtd">
+
+<mbean>
+   <description>An clustered post-office</description>
+   <class>org.jboss.messaging.core.plugin.ClusteredPostOfficeService</class>
+
+   <!-- Managed constructors -->
+
+   <!-- Managed attributes -->
+
+   <attribute access="read-only" getMethod="getInstance">
+      <description>The instance to plug into the server peer</description>
+      <name>Instance</name>
+      <type>org.jboss.messaging.core.plugin.contract.MessagingComponent</type>
+   </attribute>
+
+   <attribute access="read-write" getMethod="getDataSource" setMethod="setDataSource">
+      <description>The JNDI name of the DataSource used by this ChannelMapper instance</description>
+      <name>DataSource</name>
+      <type>java.lang.String</type>
+   </attribute>
+
+   <attribute access="read-write" getMethod="getTransactionManager" setMethod="setTransactionManager">
+      <description>The ObjectName of the TransactionManager used by this ChannelMaper instance</description>
+      <name>TransactionManager</name>
+      <type>javax.management.ObjectName</type>
+   </attribute>
+   
+   <attribute access="read-write" getMethod="getSqlProperties" setMethod="setSqlProperties">
+      <description>DML and DDL overrides</description>
+      <name>SqlProperties</name>
+      <type>java.lang.String</type>
+   </attribute>
+
+   <attribute access="read-write" getMethod="isCreateTablesOnStartup" setMethod="setCreateTablesOnStartup">
+      <description>Should database tables be created on startup?</description>
+      <name>CreateTablesOnStartup</name>
+      <type>boolean</type>
+   </attribute>
+   
+   <attribute access="read-write" getMethod="getGroupName" setMethod="setGroupName">
+      <description>The name of the JGroups group to use</description>
+      <name>GroupName</name>
+      <type>java.lang.String</type>
+   </attribute>   
+   
+   <attribute access="read-write" getMethod="getStateTimeout" setMethod="setStateTimeout">
+      <description>Timeout for getState()</description>
+      <name>StateTimeout</name>
+      <type>long</type>
+   </attribute>
+   
+   <attribute access="read-write" getMethod="getCastTimeout" setMethod="setCastTimeout">
+      <description>Timeout for getState()</description>
+      <name>Timeout when waiting for synchronous responses when sending synchronous requests</name>
+      <type>long</type>
+   </attribute>   
+   
+   <attribute access="read-write" getMethod="getSyncChannelConfig" setMethod="setSyncChannelConfig">
+      <description>The JGroups stack configuration for the synchronous channel</description>
+      <name>SyncChannelConfig</name>
+      <type>org.w3c.dom.Element</type>
+   </attribute>
+   
+   <attribute access="read-write" getMethod="getAsyncChannelConfig" setMethod="setAsyncChannelConfig">
+      <description>The JGroups stack configuration for the asynchronous channel</description>
+      <name>AsyncChannelConfig</name>
+      <type>org.w3c.dom.Element</type>
+   </attribute>   
+   
+   <attribute access="read-write" getMethod="getServerPeer" setMethod="setServerPeer">
+      <description>The ObjectName of the server peer this destination was deployed on</description>
+      <name>ServerPeer</name>
+      <type>javax.management.ObjectName</type>
+   </attribute>   
+
+   <!-- Managed operations -->
+
+   <operation>
+      <description>JBoss Service lifecycle operation</description>
+      <name>create</name>
+   </operation>
+
+   <operation>
+      <description>JBoss Service lifecycle operation</description>
+      <name>start</name>
+   </operation>
+
+   <operation>
+      <description>JBoss Service lifecycle operation</description>
+      <name>stop</name>
+   </operation>
+
+   <operation>
+      <description>JBoss Service lifecycle operation</description>
+      <name>destroy</name>
+   </operation>
+     
+</mbean>
\ No newline at end of file

Deleted: trunk/src/etc/xmdesc/Exchange-xmbean.xml
===================================================================
--- trunk/src/etc/xmdesc/Exchange-xmbean.xml	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/etc/xmdesc/Exchange-xmbean.xml	2006-09-09 11:48:48 UTC (rev 1270)
@@ -1,80 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-   <!DOCTYPE mbean PUBLIC
-      "-//JBoss//DTD JBOSS XMBEAN 1.2//EN"
-      "http://www.jboss.org/j2ee/dtd/jboss_xmbean_1_2.dtd">
-
-<mbean>
-   <description>An exchange</description>
-   <class>org.jboss.messaging.core.plugin.exchange.ExchangeSupport</class>
-
-   <!-- Managed constructors -->
-
-   <!-- Managed attributes -->
-
-   <attribute access="read-only" getMethod="getInstance">
-      <description>The instance to plug into the server peer</description>
-      <name>Instance</name>
-      <type>java.lang.Object</type>
-   </attribute>
-
-   <attribute access="read-write" getMethod="getDataSource" setMethod="setDataSource">
-      <description>The JNDI name of the DataSource used by this ChannelMapper instance</description>
-      <name>DataSource</name>
-      <type>java.lang.String</type>
-   </attribute>
-
-   <attribute access="read-write" getMethod="getTransactionManager" setMethod="setTransactionManager">
-      <description>The ObjectName of the TransactionManager used by this ChannelMaper instance</description>
-      <name>TransactionManager</name>
-      <type>javax.management.ObjectName</type>
-   </attribute>
-   
-   <attribute access="read-write" getMethod="getSqlProperties" setMethod="setSqlProperties">
-      <description>DML and DDL overrides</description>
-      <name>SqlProperties</name>
-      <type>java.lang.String</type>
-   </attribute>
-
-   <attribute access="read-write" getMethod="isCreateTablesOnStartup" setMethod="setCreateTablesOnStartup">
-      <description>Should database tables be created on startup?</description>
-      <name>CreateTablesOnStartup</name>
-      <type>boolean</type>
-   </attribute>
-
-   <!-- Managed operations -->
-
-   <operation>
-      <description>JBoss Service lifecycle operation</description>
-      <name>create</name>
-   </operation>
-
-   <operation>
-      <description>JBoss Service lifecycle operation</description>
-      <name>start</name>
-   </operation>
-
-   <operation>
-      <description>JBoss Service lifecycle operation</description>
-      <name>stop</name>
-   </operation>
-
-   <operation>
-      <description>JBoss Service lifecycle operation</description>
-      <name>destroy</name>
-   </operation>
-
-   <!-- This operation was introduced for testing purposes. If more useful operations with a
-        similar semantics are added here, use those instead of this one
-   -->
-   
-   <operation>
-      <description>Returns the set of durable subscription names corresponding to the given clientID</description>
-      <name>getSubscriptions</name>
-      <parameter>
-         <name>clientID</name>
-         <type>java.lang.String</type>
-      </parameter>
-      <return-type>java.util.Set</return-type>
-   </operation>
-      
-</mbean>
\ No newline at end of file

Modified: trunk/src/etc/xmdesc/JDBCPersistenceManager-xmbean.xml
===================================================================
--- trunk/src/etc/xmdesc/JDBCPersistenceManager-xmbean.xml	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/etc/xmdesc/JDBCPersistenceManager-xmbean.xml	2006-09-09 11:48:48 UTC (rev 1270)
@@ -3,11 +3,9 @@
       "-//JBoss//DTD JBOSS XMBEAN 1.2//EN"
       "http://www.jboss.org/j2ee/dtd/jboss_xmbean_1_2.dtd">
 
-
-
 <mbean>
    <description>A JDBC persistence manager</description>
-   <class>org.jboss.messaging.core.plugin.JDBCPersistenceManager</class>
+   <class>org.jboss.messaging.core.plugin.JDBCPersistenceManagerService</class>
 
    <!-- Managed constructors -->
 
@@ -16,7 +14,7 @@
    <attribute access="read-only" getMethod="getInstance">
       <description>The instance to plug into the server peer</description>
       <name>Instance</name>
-      <type>java.lang.Object</type>
+      <type>org.jboss.messaging.core.plugin.contract.MessagingComponent</type>
    </attribute>
 
    <attribute access="read-write" getMethod="getDataSource" setMethod="setDataSource">

Modified: trunk/src/etc/xmdesc/JDBCShutdownLogger-xmbean.xml
===================================================================
--- trunk/src/etc/xmdesc/JDBCShutdownLogger-xmbean.xml	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/etc/xmdesc/JDBCShutdownLogger-xmbean.xml	2006-09-09 11:48:48 UTC (rev 1270)
@@ -5,7 +5,7 @@
 
 <mbean>
    <description>A JDBC Shutdown Logger</description>
-   <class>org.jboss.server.plugin.JDBCShutdownLogger</class>
+   <class>org.jboss.server.plugin.JDBCShutdownLoggerService</class>
 
    <!-- Managed constructors -->
 
@@ -14,7 +14,7 @@
    <attribute access="read-only" getMethod="getInstance">
       <description>The instance to plug into the server peer</description>
       <name>Instance</name>
-      <type>java.lang.Object</type>
+      <type>org.jboss.messaging.core.plugin.contract.MessagingComponent</type>
    </attribute>
 
    <attribute access="read-write" getMethod="getDataSource" setMethod="setDataSource">

Modified: trunk/src/etc/xmdesc/JMSUserManager-xmbean.xml
===================================================================
--- trunk/src/etc/xmdesc/JMSUserManager-xmbean.xml	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/etc/xmdesc/JMSUserManager-xmbean.xml	2006-09-09 11:48:48 UTC (rev 1270)
@@ -5,7 +5,7 @@
 
 <mbean>
    <description>An JMS User Manager</description>
-   <class>org.jboss.server.plugin.JDBCJMSUserManager</class>
+   <class>org.jboss.server.plugin.JDBCJMSUserManagerService</class>
 
    <!-- Managed constructors -->
 
@@ -14,7 +14,7 @@
    <attribute access="read-only" getMethod="getInstance">
       <description>The instance to plug into the server peer</description>
       <name>Instance</name>
-      <type>java.lang.Object</type>
+      <type>org.jboss.messaging.core.plugin.contract.MessagingComponent</type>
    </attribute>
 
    <attribute access="read-write" getMethod="getDataSource" setMethod="setDataSource">

Modified: trunk/src/etc/xmdesc/Queue-xmbean.xml
===================================================================
--- trunk/src/etc/xmdesc/Queue-xmbean.xml	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/etc/xmdesc/Queue-xmbean.xml	2006-09-09 11:48:48 UTC (rev 1270)
@@ -7,7 +7,7 @@
 
 <mbean>
    <description>A deployable JBoss Messaging Queue</description>
-   <class>org.jboss.jms.server.destination.Queue</class>
+   <class>org.jboss.jms.server.destination.QueueService</class>
 
    <!-- Managed constructors -->
 
@@ -96,6 +96,12 @@
       <type>int</type>
    </attribute>
    
+   <attribute access="read-write" getMethod="isClustered" setMethod="setClustered">
+      <description>Is this a clustered destination?</description>
+      <name>Clustered</name>
+      <type>boolean</type>
+   </attribute>   
+   
    <!-- Managed operations -->
 
    <operation>

Modified: trunk/src/etc/xmdesc/ServerPeer-xmbean.xml
===================================================================
--- trunk/src/etc/xmdesc/ServerPeer-xmbean.xml	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/etc/xmdesc/ServerPeer-xmbean.xml	2006-09-09 11:48:48 UTC (rev 1270)
@@ -34,23 +34,35 @@
       <type>javax.management.ObjectName</type>
    </attribute>
 
-   <attribute access="read-write" getMethod="getDirectExchange" setMethod="setDirectExchange">
-      <description>The ObjectName of the direct exchange</description>
-      <name>DirectExchange</name>
+   <attribute access="read-write" getMethod="getQueuePostOffice" setMethod="setQueuePostOffice">
+      <description>The ObjectName of the queue post office</description>
+      <name>QueuePostOffice</name>
       <type>javax.management.ObjectName</type>
    </attribute>
    
-   <attribute access="read-write" getMethod="getTopicExchange" setMethod="setTopicExchange">
-      <description>The ObjectName of the topic exchange</description>
-      <name>TopicExchange</name>
+   <attribute access="read-write" getMethod="getTopicPostOffice" setMethod="setTopicPostOffice">
+      <description>The ObjectName of the topic post office</description>
+      <name>TopicPostOffice</name>
       <type>javax.management.ObjectName</type>
    </attribute>   
    
+   <attribute access="read-write" getMethod="getClusteredTopicPostOffice" setMethod="setClusteredTopicPostOffice">
+      <description>The ObjectName of the clustered topic post office</description>
+      <name>ClusteredTopicPostOffice</name>
+      <type>javax.management.ObjectName</type>
+   </attribute>    
+   
    <attribute access="read-write" getMethod="getJMSUserManager" setMethod="setJMSUserManager">
       <description>The ObjectName of the jms user manager</description>
       <name>JMSUserManager</name>
       <type>javax.management.ObjectName</type>
    </attribute>   
+   
+   <attribute access="read-write" getMethod="getShutdownLogger" setMethod="setShutdownLogger">
+      <description>The ObjectName of the shutdown logger</description>
+      <name>ShutdownLogger</name>
+      <type>javax.management.ObjectName</type>
+   </attribute>    
 
    <!-- instance access -->
 

Added: trunk/src/etc/xmdesc/SimplePostOffice-xmbean.xml
===================================================================
--- trunk/src/etc/xmdesc/SimplePostOffice-xmbean.xml	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/etc/xmdesc/SimplePostOffice-xmbean.xml	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+   <!DOCTYPE mbean PUBLIC
+      "-//JBoss//DTD JBOSS XMBEAN 1.2//EN"
+      "http://www.jboss.org/j2ee/dtd/jboss_xmbean_1_2.dtd">
+
+<mbean>
+   <description>An simple non-clustered post-office</description>
+   <class>org.jboss.messaging.core.plugin.SimplePostOfficeService</class>
+
+   <!-- Managed constructors -->
+
+   <!-- Managed attributes -->
+
+   <attribute access="read-only" getMethod="getInstance">
+      <description>The instance to plug into the server peer</description>
+      <name>Instance</name>
+      <type>org.jboss.messaging.core.plugin.contract.MessagingComponent</type>
+   </attribute>
+
+   <attribute access="read-write" getMethod="getDataSource" setMethod="setDataSource">
+      <description>The JNDI name of the DataSource used by this ChannelMapper instance</description>
+      <name>DataSource</name>
+      <type>java.lang.String</type>
+   </attribute>
+
+   <attribute access="read-write" getMethod="getTransactionManager" setMethod="setTransactionManager">
+      <description>The ObjectName of the TransactionManager used by this ChannelMaper instance</description>
+      <name>TransactionManager</name>
+      <type>javax.management.ObjectName</type>
+   </attribute>
+   
+   <attribute access="read-write" getMethod="getSqlProperties" setMethod="setSqlProperties">
+      <description>DML and DDL overrides</description>
+      <name>SqlProperties</name>
+      <type>java.lang.String</type>
+   </attribute>
+
+   <attribute access="read-write" getMethod="isCreateTablesOnStartup" setMethod="setCreateTablesOnStartup">
+      <description>Should database tables be created on startup?</description>
+      <name>CreateTablesOnStartup</name>
+      <type>boolean</type>
+   </attribute>
+   
+   <attribute access="read-write" getMethod="getPostOfficeName" setMethod="setPostOfficeName">
+      <description>The name of the post office</description>
+      <name>PostOfficeName</name>
+      <type>java.lang.String</type>
+   </attribute> 
+   
+   <attribute access="read-write" getMethod="getServerPeer" setMethod="setServerPeer">
+      <description>The ObjectName of the server peer this destination was deployed on</description>
+      <name>ServerPeer</name>
+      <type>javax.management.ObjectName</type>
+   </attribute>   
+   
+   <attribute access="read-write" getMethod="getServerPeer" setMethod="setServerPeer">
+      <description>The ObjectName of the server peer this destination was deployed on</description>
+      <name>ServerPeer</name>
+      <type>javax.management.ObjectName</type>
+   </attribute>  
+
+   <!-- Managed operations -->
+
+   <operation>
+      <description>JBoss Service lifecycle operation</description>
+      <name>create</name>
+   </operation>
+
+   <operation>
+      <description>JBoss Service lifecycle operation</description>
+      <name>start</name>
+   </operation>
+
+   <operation>
+      <description>JBoss Service lifecycle operation</description>
+      <name>stop</name>
+   </operation>
+
+   <operation>
+      <description>JBoss Service lifecycle operation</description>
+      <name>destroy</name>
+   </operation>
+     
+</mbean>
\ No newline at end of file

Modified: trunk/src/etc/xmdesc/Topic-xmbean.xml
===================================================================
--- trunk/src/etc/xmdesc/Topic-xmbean.xml	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/etc/xmdesc/Topic-xmbean.xml	2006-09-09 11:48:48 UTC (rev 1270)
@@ -5,7 +5,7 @@
 
 <mbean>
    <description>A deployable JBoss Messaging Topic</description>
-   <class>org.jboss.jms.server.destination.Topic</class>
+   <class>org.jboss.jms.server.destination.TopicService</class>
 
    <!-- Managed constructors -->
 
@@ -87,6 +87,12 @@
       <name>DownCacheSize</name>
       <type>int</type>
    </attribute>
+   
+   <attribute access="read-write" getMethod="isClustered" setMethod="setClustered">
+      <description>Is this a clustered destination?</description>
+      <name>Clustered</name>
+      <type>boolean</type>
+   </attribute>
 
    <!-- Managed operations -->
 

Modified: trunk/src/main/org/jboss/jms/client/state/ConsumerState.java
===================================================================
--- trunk/src/main/org/jboss/jms/client/state/ConsumerState.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/client/state/ConsumerState.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -28,7 +28,6 @@
 import org.jboss.jms.client.remoting.MessageCallbackHandler;
 import org.jboss.jms.delegate.ConsumerDelegate;
 import org.jboss.jms.server.Version;
-import org.jboss.logging.Logger;
 
 /**
  * State corresponding to a Consumer. This state is acessible inside aspects/interceptors.
@@ -40,9 +39,6 @@
  */
 public class ConsumerState extends HierarchicalStateSupport
 {
-   private static final Logger log = Logger.getLogger(ConsumerState.class);
-   
-   
    private Destination destination;
    
    private String selector;

Modified: trunk/src/main/org/jboss/jms/destination/JBossDestination.java
===================================================================
--- trunk/src/main/org/jboss/jms/destination/JBossDestination.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/destination/JBossDestination.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -48,23 +48,8 @@
 
    protected String name;
    
-   //TODO There is probably a better place to put these
-   protected transient int fullSize;
-   
-   protected transient int pageSize;
-   
-   protected transient int downCacheSize;
-
    // Constructors --------------------------------------------------
 
-   public JBossDestination(String name, int fullSize, int pageSize, int downCacheSize)
-   {
-      this(name);
-      this.fullSize = fullSize;
-      this.pageSize = pageSize;
-      this.downCacheSize = downCacheSize;
-   }
-   
    public JBossDestination(String name)
    {
       this.name = name;
@@ -133,21 +118,6 @@
       }           
    }
    
-   public int getFullSize()
-   {
-      return fullSize;
-   }
-   
-   public int getPageSize()
-   {
-      return pageSize;
-   }
-   
-   public int getDownCacheSize()
-   {
-      return downCacheSize;
-   }
-
    // Package protected ---------------------------------------------
    
    // Protected -----------------------------------------------------

Modified: trunk/src/main/org/jboss/jms/destination/JBossQueue.java
===================================================================
--- trunk/src/main/org/jboss/jms/destination/JBossQueue.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/destination/JBossQueue.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -42,11 +42,6 @@
    
    // Constructors --------------------------------------------------
 
-   public JBossQueue(String name, int fullSize, int pageSize, int downCacheSize)
-   {
-      super(name, fullSize, pageSize, downCacheSize);
-   }
-   
    public JBossQueue(String name)
    {
       super(name);

Modified: trunk/src/main/org/jboss/jms/destination/JBossTemporaryTopic.java
===================================================================
--- trunk/src/main/org/jboss/jms/destination/JBossTemporaryTopic.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/destination/JBossTemporaryTopic.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -52,12 +52,7 @@
       super(new GUID().toString());
       this.delegate = delegate;
    }
-   
-   public JBossTemporaryTopic(String name, int fullSize, int pageSize, int downCacheSize)
-   {
-      super(name, fullSize, pageSize, downCacheSize);
-   }
-   
+    
    public JBossTemporaryTopic(String name)
    {
       super(name);

Modified: trunk/src/main/org/jboss/jms/destination/JBossTopic.java
===================================================================
--- trunk/src/main/org/jboss/jms/destination/JBossTopic.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/destination/JBossTopic.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -42,15 +42,11 @@
    
    // Constructors --------------------------------------------------
 
-   public JBossTopic(String name, int fullSize, int pageSize, int downCacheSize)
-   {
-      super(name, fullSize, pageSize, downCacheSize);
-   }
-   
    public JBossTopic(String name)
    {
       super(name);
    }
+   
 
    // JBossDestination overrides ------------------------------------
 

Modified: trunk/src/main/org/jboss/jms/server/ConnectionFactoryManager.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/ConnectionFactoryManager.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/ConnectionFactoryManager.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -22,6 +22,7 @@
 package org.jboss.jms.server;
 
 import org.jboss.jms.server.connectionfactory.JNDIBindings;
+import org.jboss.messaging.core.plugin.contract.MessagingComponent;
 
 /**
  * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
@@ -30,7 +31,7 @@
  *
  * $Id$
  */
-public interface ConnectionFactoryManager
+public interface ConnectionFactoryManager extends MessagingComponent
 {
    /**
     * @param jndiBindings - if null, the connection factory will be created and registered with the

Modified: trunk/src/main/org/jboss/jms/server/ConnectionManager.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/ConnectionManager.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/ConnectionManager.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -22,6 +22,7 @@
 package org.jboss.jms.server;
 
 import org.jboss.jms.server.endpoint.ConnectionEndpoint;
+import org.jboss.messaging.core.plugin.contract.MessagingComponent;
 
 
 /**
@@ -31,7 +32,7 @@
  *
  * $Id$
  */
-public interface ConnectionManager
+public interface ConnectionManager extends MessagingComponent
 {
    void registerConnection(String jmsClientVMId, String remotingClientSessionID, ConnectionEndpoint endpoint);
 

Modified: trunk/src/main/org/jboss/jms/server/ConnectorManager.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/ConnectorManager.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/ConnectorManager.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -21,6 +21,7 @@
   */
 package org.jboss.jms.server;
 
+import org.jboss.messaging.core.plugin.contract.MessagingComponent;
 
 /**
  * 
@@ -31,10 +32,9 @@
  *
  * ConnectorManager.java,v 1.1 2006/04/13 19:43:05 timfox Exp
  */
-public interface ConnectorManager
+public interface ConnectorManager extends MessagingComponent
 {
    int registerConnector(String connectorName) throws Exception;
    
    void unregisterConnector(String connectorName) throws Exception;
-   
 }

Modified: trunk/src/main/org/jboss/jms/server/DestinationJNDIMapper.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/DestinationJNDIMapper.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/DestinationJNDIMapper.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -34,11 +34,13 @@
 
 import org.jboss.jms.destination.JBossDestination;
 import org.jboss.jms.destination.JBossQueue;
+import org.jboss.jms.destination.JBossTemporaryQueue;
+import org.jboss.jms.destination.JBossTemporaryTopic;
 import org.jboss.jms.destination.JBossTopic;
+import org.jboss.jms.server.destination.ManagedDestination;
 import org.jboss.jms.util.JNDIUtil;
 import org.jboss.jms.util.MessagingJMSException;
 import org.jboss.logging.Logger;
-import org.w3c.dom.Element;
 
 /**
  * Keeps track of destinations - including temporary destinations
@@ -60,32 +62,37 @@
    
    // Attributes ----------------------------------------------------
 
-   protected ServerPeer serverPeer;
-   protected Context initialContext;
+   private Context initialContext;
 
    // Map <name , destination holder>
-   protected Map queueMap;
-   protected Map topicMap;
-      
+   private Map queueMap;
+   private Map topicMap;
+   
+   private ServerPeer serverPeer;
+         
    // Constructors --------------------------------------------------
 
    public DestinationJNDIMapper(ServerPeer serverPeer) throws Exception
    {
-      this.serverPeer = serverPeer;
+     // this.serverPeer = serverPeer;
       queueMap = new HashMap();
       topicMap = new HashMap();
+      this.serverPeer = serverPeer;
    }
    
    // DestinationManager implementation -----------------------------
    
-   public synchronized String registerDestination(JBossDestination destination, String jndiName,
-                                                  Element securityConfiguration) throws Exception
-   {            
+   public synchronized void registerDestination(ManagedDestination destination) throws Exception
+   {        
+      log.info("^^^ REGISTERING DESTINATION: " + destination.getName());
+      
+      String jndiName = destination.getJndiName();
+      
       if (!destination.isTemporary())
       {
          String parentContext;
          String jndiNameInContext;
-   
+            
          if (jndiName == null)
          {
             parentContext = destination.isQueue() ?
@@ -108,6 +115,10 @@
             }
             jndiNameInContext = jndiName.substring(sepIndex + 1);
          }
+         
+         destination.setJndiName(jndiName);
+         
+         log.info("JNDI NAME:" + jndiName);
    
          try
          {
@@ -119,53 +130,67 @@
             // OK
          }      
 
-         Context c = JNDIUtil.createContext(initialContext, parentContext);
+         Context c = JNDIUtil.createContext(initialContext, parentContext);         
          
-         c.rebind(jndiNameInContext, destination);
+         JBossDestination jbDest;
          
-         //if the destination has no security configuration, then the security manager will always
-         // use its current default security configuration when requested to authorize requests for
-         // that destination
-         if (securityConfiguration != null)
+         if (destination.isQueue())
          {
-            serverPeer.getSecurityManager().setSecurityConfig(destination.isQueue(),
-                                                              destination.getName(),
-                                                              securityConfiguration);
+            if (destination.isTemporary())
+            {
+               jbDest = new JBossTemporaryQueue(destination.getName());
+            }
+            else
+            {
+               jbDest = new JBossQueue(destination.getName());
+            }
          }
+         else
+         {
+            if (destination.isTemporary())
+            {
+               jbDest = new JBossTemporaryTopic(destination.getName());
+            }
+            else
+            {
+               jbDest = new JBossTopic(destination.getName());
+            }
+         }
+         
+         c.rebind(jndiNameInContext, jbDest);         
+         log.info("Bound it in jndi");
       }
             
       if (destination.isQueue())
       {
-         queueMap.put(destination.getName(), new DestinationHolder(destination, jndiName));
+         queueMap.put(destination.getName(), destination);
       }
       else
       {
-         topicMap.put(destination.getName(), new DestinationHolder(destination, jndiName));
+         topicMap.put(destination.getName(), destination);
       }      
       
       log.debug((destination.isQueue() ? "queue" : "topic") + " " + destination.getName() + " registered ");
       log.debug((destination.isQueue() ? "queue" : "topic") + " bound in JNDI as " + jndiName);
-      
-      return jndiName;
    }
 
-   public synchronized void unregisterDestination(JBossDestination destination) throws Exception
+   public synchronized void unregisterDestination(ManagedDestination destination) throws Exception
    {
       String jndiName = null;
       if (destination.isQueue())
       {
-         DestinationHolder holder = (DestinationHolder)queueMap.remove(destination.getName());
-         if (holder != null)
+         ManagedDestination dest = (ManagedDestination)queueMap.remove(destination.getName());
+         if (dest != null)
          {
-            jndiName = holder.jndiName;
+            jndiName = dest.getJndiName();
          }
       }
       else
       {
-         DestinationHolder holder = (DestinationHolder)topicMap.remove(destination.getName());
-         if (holder != null)
+         ManagedDestination dest = (ManagedDestination)topicMap.remove(destination.getName());
+         if (dest != null)
          {
-            jndiName = holder.jndiName;
+            jndiName = dest.getJndiName();
          }
       }
       if (jndiName == null)
@@ -183,43 +208,29 @@
       log.debug("unregistered " + (destination.isQueue() ? "queue " : "topic ") + destination.getName());
    }
    
-   public synchronized boolean destinationExists(JBossDestination dest)
+   public synchronized ManagedDestination getDestination(String name, boolean isQueue)
    {
-      return getDestination(dest) != null;
-   }
-   
-   public synchronized JBossDestination getDestination(JBossDestination dest)
-   {
-      Map m = dest.isTopic() ? topicMap : queueMap;
+      Map m = isQueue ? queueMap : topicMap;
       
-      DestinationHolder holder = (DestinationHolder)m.get(dest.getName());
+      ManagedDestination holder = (ManagedDestination)m.get(name);
       
-      return holder == null ? null : holder.destination;
+      return holder;
    }
    
    public synchronized Set getDestinations()
    {
       Set destinations = new HashSet();
       
-      for(Iterator i = queueMap.values().iterator(); i.hasNext(); )
-      {
-         DestinationHolder holder = (DestinationHolder)i.next();
-         destinations.add(holder.destination);
-      }
-      for(Iterator i = topicMap.values().iterator(); i.hasNext(); )
-      {
-         DestinationHolder holder = (DestinationHolder)i.next();
-         destinations.add(holder.destination);
-      }
+      destinations.addAll(queueMap.values());
+      
+      destinations.addAll(topicMap.values());
+      
       return destinations;
    }
    
-
-   // Public --------------------------------------------------------
-
-   // Package protected ---------------------------------------------
-
-   void start() throws Exception
+   // MessagingComponent implementation -----------------------------
+   
+   public void start() throws Exception
    {
       initialContext = new InitialContext();
 
@@ -228,7 +239,7 @@
       createContext(serverPeer.getDefaultTopicJNDIContext());
    }
 
-   void stop() throws Exception
+   public void stop() throws Exception
    {
       Set queues = new HashSet(queueMap.keySet());
       
@@ -237,12 +248,12 @@
       // remove all destinations from JNDI
       for(Iterator i = queues.iterator(); i.hasNext(); )
       {
-         unregisterDestination(new JBossQueue((String)i.next()));         
+         unregisterDestination((ManagedDestination)i.next());         
       }
 
       for(Iterator i = topics.iterator(); i.hasNext(); )
       {
-         unregisterDestination(new JBossTopic((String)i.next()));
+         unregisterDestination((ManagedDestination)i.next());
       }
 
       initialContext.unbind(serverPeer.getDefaultQueueJNDIContext());
@@ -250,8 +261,11 @@
 
       initialContext.close();
    }
+  
+   // Public --------------------------------------------------------
 
-
+   // Package protected ---------------------------------------------
+  
    // Protected -----------------------------------------------------
 
    // Private -------------------------------------------------------
@@ -278,16 +292,4 @@
 
    // Inner classes -------------------------------------------------
    
-   private class DestinationHolder
-   {
-      DestinationHolder(JBossDestination destination, String jndiName)
-      {
-         this.destination = destination;
-         this.jndiName = jndiName;
-      }
-      
-      JBossDestination destination;
-      
-      String jndiName;
-   }
 }

Modified: trunk/src/main/org/jboss/jms/server/DestinationManager.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/DestinationManager.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/DestinationManager.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -23,8 +23,8 @@
 
 import java.util.Set;
 
-import org.jboss.jms.destination.JBossDestination;
-import org.w3c.dom.Element;
+import org.jboss.jms.server.destination.ManagedDestination;
+import org.jboss.messaging.core.plugin.contract.MessagingComponent;
 
 /**
  * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
@@ -33,7 +33,7 @@
  *
  * $Id$
  */
-public interface DestinationManager
+public interface DestinationManager extends MessagingComponent
 {
    /**
     * Method called by a destination service to register itself with the server peer. The server
@@ -42,19 +42,15 @@
     *
     * @return the name under which the destination was bound in JNDI.
     */
-   String registerDestination(JBossDestination destination,
-                              String jndiName, Element securityConfig) throws Exception;
+   void registerDestination(ManagedDestination destination) throws Exception;
 
    /**
     * Method called by a destination service to unregister itself from the server peer. The server
     * peer is supposed to clean up the state maintained on behalf of the unregistered destination.
     */
-   void unregisterDestination(JBossDestination destination) throws Exception;
+   void unregisterDestination(ManagedDestination destination) throws Exception;
    
-   boolean destinationExists(JBossDestination destination);
+   ManagedDestination getDestination(String name, boolean isQueue);
    
-   //TODO There is probably a better way of doing this
-   JBossDestination getDestination(JBossDestination dest);
-   
    Set getDestinations();   
 }

Modified: trunk/src/main/org/jboss/jms/server/ServerPeer.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/ServerPeer.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/ServerPeer.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -49,13 +49,11 @@
 import org.jboss.messaging.core.memory.SimpleMemoryManager;
 import org.jboss.messaging.core.plugin.IdManager;
 import org.jboss.messaging.core.plugin.SimpleMessageStore;
-import org.jboss.messaging.core.plugin.contract.Exchange;
 import org.jboss.messaging.core.plugin.contract.MessageStore;
 import org.jboss.messaging.core.plugin.contract.PersistenceManager;
+import org.jboss.messaging.core.plugin.contract.PostOffice;
 import org.jboss.messaging.core.plugin.contract.ShutdownLogger;
-import org.jboss.messaging.core.plugin.exchange.DirectExchange;
-import org.jboss.messaging.core.plugin.exchange.TopicExchange;
-import org.jboss.messaging.core.plugin.exchange.cluster.ClusteredTopicExchange;
+import org.jboss.messaging.core.plugin.postoffice.PostOfficeImpl;
 import org.jboss.messaging.core.tx.TransactionRepository;
 import org.jboss.messaging.util.Util;
 import org.jboss.mx.loading.UnifiedClassLoader3;
@@ -126,16 +124,22 @@
    // plugins
 
    protected ObjectName persistenceManagerObjectName;
-   protected PersistenceManager persistenceManagerDelegate;
-   protected ObjectName directExchangeObjectName;
-   protected ObjectName topicExchangeObjectName;
-   protected Exchange directExchangeDelegate;
-   protected Exchange topicExchangeDelegate;
-   protected ObjectName JMSUserManagerObjectName;
-   protected JMSUserManager JMSUserManagerDelegate;
+   protected PersistenceManager persistenceManager;
+   
+   protected ObjectName queuePostOfficeObjectName;
+   protected PostOfficeImpl queuePostOffice;
+   
+   protected ObjectName topicPostOfficeObjectName;
+   protected PostOfficeImpl topicPostOffice;
+     
+   protected ObjectName jmsUserManagerObjectName;
+   protected JMSUserManager jmsUserManager;
+   
    protected ObjectName shutdownLoggerObjectName;
-   protected ShutdownLogger shutdownLoggerDelegate;
+   protected ShutdownLogger shutdownLogger;
 
+   //Other stuff
+   
    private JMSServerInvocationHandler handler;
 
    // We keep a map of consumers to prevent us to recurse through the attached session in order to
@@ -156,16 +160,9 @@
       this.defaultQueueJNDIContext = defaultQueueJNDIContext;
       this.defaultTopicJNDIContext = defaultTopicJNDIContext;
 
+      // Some wired components need to be started here
       securityStore = new SecurityMetadataStore();
-      txRepository = new TransactionRepository();
-
-      destinationJNDIMapper = new DestinationJNDIMapper(this);
-      connFactoryJNDIMapper = new ConnectionFactoryJNDIMapper(this);
-      connectionManager = new SimpleConnectionManager();
-      connectorManager = new SimpleConnectorManager();
-      memoryManager = new SimpleMemoryManager();
-      messageStore = new SimpleMessageStore();
-
+      
       consumers = new ConcurrentReaderHashMap();
 
       version = Version.instance();
@@ -183,6 +180,8 @@
          {
             return;
          }
+         
+         log.info("******** STARTING SERVER PEER");
    
          log.debug(this + " starting");
          
@@ -191,8 +190,7 @@
             throw new IllegalArgumentException("queuedExecutorPoolSize must be > 0");
          }
          queuedExecutorPool = new QueuedExecutorPool(queuedExecutorPoolSize);
-         
-   
+            
          loadClientAOPConfig();
    
          loadServerAOPConfig();
@@ -203,64 +201,51 @@
          // circumventing the MBeanServer. However, they are installed as services to take advantage
          // of their automatically-creating management interface.
    
-         //FIXME - Why are these called xxxDelegate ??
-         //They're not delegates - this is confusing
-         persistenceManagerDelegate =
-            (PersistenceManager)mbeanServer.getAttribute(persistenceManagerObjectName, "Instance");
-   
-         directExchangeDelegate = (Exchange)mbeanServer.
-            getAttribute(directExchangeObjectName, "Instance");
+         persistenceManager = (PersistenceManager)mbeanServer.
+            getAttribute(persistenceManagerObjectName, "Instance");
+
+         jmsUserManager = (JMSUserManager)mbeanServer.
+            getAttribute(jmsUserManagerObjectName, "Instance");
          
-         topicExchangeDelegate = (Exchange)mbeanServer.
-            getAttribute(topicExchangeObjectName, "Instance");
+         shutdownLogger = (ShutdownLogger)mbeanServer.
+            getAttribute(shutdownLoggerObjectName, "Instance");
          
-         JMSUserManagerDelegate = (JMSUserManager)mbeanServer.
-            getAttribute(JMSUserManagerObjectName, "Instance");
+         //We get references to some plugins lazily to avoid problems with circular
+         //MBean dependencies
+            
+         // Create the wired components
+         messageIdManager = new IdManager("MESSAGE_ID", 8192, persistenceManager);
+         channelIdManager = new IdManager("CHANNEL_ID", 10, persistenceManager);
+         transactionIdManager = new IdManager("TRANSACTION_ID", 4096, persistenceManager);
+         destinationJNDIMapper = new DestinationJNDIMapper(this);
+         connFactoryJNDIMapper = new ConnectionFactoryJNDIMapper(this);
+         connectionManager = new SimpleConnectionManager();
+         connectorManager = new SimpleConnectorManager();
+         memoryManager = new SimpleMemoryManager();
+         messageStore = new SimpleMessageStore();         
+         txRepository = new TransactionRepository(persistenceManager, transactionIdManager);
+ 
+         // Start the wired components
+   
+         messageIdManager.start();
+         channelIdManager.start();
+         transactionIdManager.start();
+         destinationJNDIMapper.start();
+         connFactoryJNDIMapper.start();
+         connectionManager.start();
+         connectorManager.start();         
+         memoryManager.start();
+         messageStore.start();
+         securityStore.start();
+         txRepository.start();
          
-         shutdownLoggerDelegate = (ShutdownLogger)mbeanServer.
-            getAttribute(shutdownLoggerObjectName, "Instance");
-         
          //Did the server crash last time?
-         crashed = shutdownLoggerDelegate.startup(serverPeerID);
-                  
-         //TODO Make block size configurable
-         messageIdManager = new IdManager("MESSAGE_ID", 8192, persistenceManagerDelegate);
-         channelIdManager = new IdManager("CHANNEL_ID", 10, persistenceManagerDelegate);
-         transactionIdManager = new IdManager("TRANSACTION_ID", 4096, persistenceManagerDelegate);
-         
-         //Inject attributes
-         
-         ((DirectExchange)directExchangeDelegate).injectAttributes("Direct", serverPeerID,
-                                                                    messageStore,
-                                                                    channelIdManager,
-                                                                    queuedExecutorPool);
-                           
-//         ((ClusteredTopicExchange)topicExchangeDelegate).injectAttributes(null, null, null, "Topic", serverPeerID,
-//                                                                   messageStore, 
-//                                                                   channelIdManager,
-//                                                                   queuedExecutorPool,
-//                                                                   txRepository,
-//                                                                   persistenceManagerDelegate);
-         
-         ((TopicExchange)topicExchangeDelegate).injectAttributes("Topic", serverPeerID,
-                                                                messageStore, 
-                                                                channelIdManager,
-                                                                queuedExecutorPool,
-                                                                txRepository);
-         
+         crashed = shutdownLogger.startup(serverPeerID);
+                            
          if (crashed)
          {
-            topicExchangeDelegate.recover();
+            topicPostOffice.recover();
          }
-         
-         txRepository.injectAttributes(persistenceManagerDelegate, transactionIdManager);
-         
-         // start the rest of the internal components
-   
-         memoryManager.start();
-         destinationJNDIMapper.start();
-         securityStore.start();
-         connFactoryJNDIMapper.start();   
 
          initializeRemoting(mbeanServer);
    
@@ -270,6 +255,8 @@
    
          log.info("JBoss Messaging " + getVersion().getProviderVersion() + " server [" +
             getServerPeerID()+ "] started");      
+         
+         log.info("********** STARTED SERVER PEER");
       }
       catch (Throwable t)
       {
@@ -292,24 +279,39 @@
    
          removeRecoverable();
    
-         // stop the internal components
-         memoryManager.stop();
+         shutdownLogger.shutdown(serverPeerID);         
+                  
+         // Stop the wired components         
+         
+         messageIdManager.start();
+         messageIdManager = null;
+         channelIdManager.start();
+         channelIdManager = null;
+         transactionIdManager.start();
+         transactionIdManager = null;
+         destinationJNDIMapper.start();
+         destinationJNDIMapper = null;
+         connFactoryJNDIMapper.start();
+         connFactoryJNDIMapper = null;
+         connectionManager.start();
+         connectionManager = null;
+         connectorManager.start(); 
+         connectorManager = null;
+         memoryManager.start();
+         memoryManager = null;
+         messageStore.start();
+         messageStore = null;
+         securityStore.start();
+         securityStore = null;
+         txRepository.start();
          txRepository = null;
-         securityStore.stop();
-         securityStore = null;
-         connFactoryJNDIMapper.stop();
-         connFactoryJNDIMapper = null;
-         destinationJNDIMapper.stop();
-         destinationJNDIMapper = null;
    
          unloadServerAOPConfig();
    
          // TODO unloadClientAOPConfig();
          
          queuedExecutorPool.shutdown();
-         
-         shutdownLoggerDelegate.shutdown(serverPeerID);         
-   
+                  
          log.info("JMS " + this + " stopped");
       }
       catch (Throwable t)
@@ -330,34 +332,34 @@
       persistenceManagerObjectName = on;
    }
    
-   public ObjectName getDirectExchange()
+   public ObjectName getQueuePostOffice()
    {
-      return directExchangeObjectName;
+      return queuePostOfficeObjectName;
    }
 
-   public void setDirectExchange(ObjectName on)
+   public void setQueuePostOffice(ObjectName on)
    {
-      directExchangeObjectName = on;
+      queuePostOfficeObjectName = on;
    }
    
-   public ObjectName getTopicExchange()
+   public ObjectName getTopicPostOffice()
    {
-      return topicExchangeObjectName;
+      return topicPostOfficeObjectName;
    }
 
-   public void setTopicExchange(ObjectName on)
+   public void setTopicPostOffice(ObjectName on)
    {
-      topicExchangeObjectName = on;
+      topicPostOfficeObjectName = on;
    }
    
-   public ObjectName getJMSUserManager()
+   public ObjectName getJmsUserManager()
    {
-      return JMSUserManagerObjectName;
+      return jmsUserManagerObjectName;
    }
 
    public void setJMSUserManager(ObjectName on)
    {
-      JMSUserManagerObjectName = on;
+      jmsUserManagerObjectName = on;
    }
    
    public ObjectName getShutdownLogger()
@@ -425,9 +427,17 @@
       return defaultTopicJNDIContext;
    }
 
-   public void setSecurityDomain(String securityDomain)
+   public void setSecurityDomain(String securityDomain) throws Exception
    {
-      securityStore.setSecurityDomain(securityDomain);
+      try
+      {
+         log.info("&&&&&&&& setting security domain to: " + securityDomain);
+         securityStore.setSecurityDomain(securityDomain);      
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " setSecurityDomain");
+      } 
    }
 
    public String getSecurityDomain()
@@ -622,29 +632,41 @@
 
    // access to plugin references
 
-   public PersistenceManager getPersistenceManagerDelegate()
+   public PersistenceManager getPersistenceManagerInstance()
    {
-      return persistenceManagerDelegate;
+      return persistenceManager;
    }
    
-   public JMSUserManager getJMSUserManagerDelegate()
+   public JMSUserManager getJmsUserManagerInstance()
    {
-      return JMSUserManagerDelegate;
+      return jmsUserManager;
    }
    
-   public Exchange getDirectExchangeDelegate()
+   public PostOffice getQueuePostOfficeInstance() throws Exception
    {
-      return directExchangeDelegate;
+      // We get the reference lazily to avoid problems with MBean circular dependencies
+      if (queuePostOffice == null)
+      {
+         queuePostOffice = (PostOfficeImpl)getServer().
+            getAttribute(queuePostOfficeObjectName, "Instance");
+      }
+      return queuePostOffice;
    }
-   
-   public Exchange getTopicExchangeDelegate()
+      
+   public PostOffice getTopicPostOfficeInstance() throws Exception
    {
-      return topicExchangeDelegate;
+      // We get the reference lazily to avoid problems with MBean circular dependencies
+      if (topicPostOffice == null)
+      {
+         topicPostOffice = (PostOfficeImpl)getServer().
+            getAttribute(topicPostOfficeObjectName, "Instance");
+      }
+      return topicPostOffice;        
    }
-   
-   public ShutdownLogger getShutdownLoggerDelegate()
+      
+   public ShutdownLogger getShutdownLoggerInstance()
    {
-      return shutdownLoggerDelegate;
+      return shutdownLogger;
    }
    
    

Modified: trunk/src/main/org/jboss/jms/server/connectionfactory/ConnectionFactoryJNDIMapper.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/connectionfactory/ConnectionFactoryJNDIMapper.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/connectionfactory/ConnectionFactoryJNDIMapper.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -139,9 +139,9 @@
    {
       return (javax.jms.ConnectionFactory)factories.get(new Integer(connectionFactoryID));
    }
-
-   // Public --------------------------------------------------------
-
+   
+   // MessagingComponent implementation -----------------------------
+   
    public void start() throws Exception
    {
       initialContext = new InitialContext();
@@ -154,18 +154,13 @@
       log.debug("stopped");
    }
 
+   // Public --------------------------------------------------------
+
    // Package protected ---------------------------------------------
 
    // Protected -----------------------------------------------------
 
    // Private -------------------------------------------------------
-
- //  private long connFactoryIDSequence = 0;
-
-//   private synchronized String generateConnectionFactoryID()
-//   {
-//      return "CONNFACTORY_" + connFactoryIDSequence++;
-//   }
-
+   
    // Inner classes -------------------------------------------------
 }

Modified: trunk/src/main/org/jboss/jms/server/connectionmanager/SimpleConnectionManager.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/connectionmanager/SimpleConnectionManager.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/connectionmanager/SimpleConnectionManager.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -209,7 +209,17 @@
       }
    }
    
+   // MessagingComponent implementation --------------------------------
    
+   public void start() throws Exception
+   {
+      //NOOP
+   }
+   
+   public void stop() throws Exception
+   {
+      //NOOP
+   }
 
    // Public --------------------------------------------------------
 

Modified: trunk/src/main/org/jboss/jms/server/connectormanager/SimpleConnectorManager.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/connectormanager/SimpleConnectorManager.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/connectormanager/SimpleConnectorManager.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -108,4 +108,16 @@
          return i.intValue();
       }
    }
+   
+   // MessagingComponent implementation --------------------------------
+   
+   public void start() throws Exception
+   {
+      //NOOP
+   }
+   
+   public void stop() throws Exception
+   {
+      //NOOP
+   }
 }

Modified: trunk/src/main/org/jboss/jms/server/destination/DestinationServiceSupport.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/DestinationServiceSupport.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/destination/DestinationServiceSupport.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -9,9 +9,14 @@
 import javax.management.ObjectName;
 
 import org.jboss.jms.server.DestinationManager;
+import org.jboss.jms.server.QueuedExecutorPool;
 import org.jboss.jms.server.SecurityManager;
+import org.jboss.jms.server.ServerPeer;
 import org.jboss.jms.util.ExceptionUtil;
-import org.jboss.messaging.core.plugin.contract.Exchange;
+import org.jboss.messaging.core.plugin.IdManager;
+import org.jboss.messaging.core.plugin.contract.MessageStore;
+import org.jboss.messaging.core.plugin.contract.PersistenceManager;
+import org.jboss.messaging.core.plugin.contract.PostOffice;
 import org.jboss.system.ServiceMBeanSupport;
 import org.w3c.dom.Element;
 
@@ -30,71 +35,91 @@
 public abstract class DestinationServiceSupport extends ServiceMBeanSupport
 {
    // Constants -----------------------------------------------------
-   private static final int FULL_SIZE = 75000;
-   private static final int PAGE_SIZE = 2000;
-   private static final int DOWN_CACHE_SIZE = 2000;
 
+
    // Static --------------------------------------------------------
 
-   /**
-    * Destination implementations don't like empty string selectors, but this is how the jmx-console
-    * sends arguments that are not filled out. This method pre-processes the selector String and
-    * makes it a valid argument for destination methods.
-    */
-   static String trimSelector(String selector)
-   {
-      if (selector == null)
-      {
-         return null;
-      }
 
-      selector = selector.trim();
+   // Attributes ----------------------------------------------------
 
-      if (selector.length() == 0)
-      {
-         return null;
-      }
-
-      return selector;
-   }
+   private ObjectName serverPeerObjectName;
    
-   // Attributes ----------------------------------------------------
-
-   protected ObjectName serverPeerObjectName;
+   protected boolean started = false;
+   
+   protected ManagedDestination destination;
+   
+   protected PostOffice postOffice;
+      
+   protected ServerPeer serverPeer;
+   
    protected DestinationManager dm;
+   
    protected SecurityManager sm;
-   protected Exchange exchange;
-   protected Element securityConfig;
-
-   protected String name;
-   protected String jndiName;
-
-   protected boolean started = false;
-   private boolean createdProgrammatically = false;
    
-   // The following 3 attributes can only be changed when service is stopped.
-
-   // Default in memory message number limit
-   protected int fullSize = FULL_SIZE;
-
-   // Default paging size
-   protected int pageSize = PAGE_SIZE;
-
-   // Default down-cache size
-   protected int downCacheSize = DOWN_CACHE_SIZE;
-
+   protected PersistenceManager pm;
+   
+   protected QueuedExecutorPool pool;
+   
+   protected MessageStore ms;
+   
+   protected IdManager idm;
+   
    // Constructors --------------------------------------------------
 
-   public DestinationServiceSupport(boolean createdProgrammatically)
+   // ServiceMBeanSupport overrides -----------------------------------
+   
+   public synchronized void startService() throws Exception
    {
-      this.createdProgrammatically = createdProgrammatically;
+      super.startService();
+      
+      try
+      {
+         serverPeer = (ServerPeer)server.getAttribute(serverPeerObjectName, "Instance");
+         
+         dm = serverPeer.getDestinationManager();
+         
+         sm = serverPeer.getSecurityManager();
+         
+         pm = serverPeer.getPersistenceManagerInstance(); 
+         
+         pool = serverPeer.getQueuedExecutorPool();
+         
+         ms = serverPeer.getMessageStore();
+         
+         idm = serverPeer.getChannelIdManager();
+         
+         String name = null;
+                  
+         if (serviceName != null)
+         {
+            name = serviceName.getKeyProperty("name");
+         }
+   
+         if (name == null || name.length() == 0)
+         {
+            throw new IllegalStateException( "The " + (isQueue() ? "queue" : "topic") + " " +
+                                             "name was not properly set in the service's" +
+                                             "ObjectName");
+         }
+         
+         destination.setName(name);                   
+      }
+      catch (Throwable t)
+      {
+         ExceptionUtil.handleJMXInvocation(t, this + " startService");
+      }     
    }
-
+   
+   public synchronized void stopService() throws Exception
+   {
+      super.stopService();    
+   }
+   
    // JMX managed attributes ----------------------------------------
 
    public String getJNDIName()
    {
-      return jndiName;
+      return destination.getJndiName();
    }
 
    public void setJNDIName(String jndiName)
@@ -105,7 +130,7 @@
          return;
       }
 
-      this.jndiName = jndiName;
+      destination.setJndiName(jndiName);
    }
 
    public void setServerPeer(ObjectName on)
@@ -129,13 +154,13 @@
    {
       try
       {
-         // push security update to the server
-         if (sm != null)
+         if (started)
          {
-            sm.setSecurityConfig(isQueue(), name, securityConfig);
+            // push security update to the server
+            sm.setSecurityConfig(isQueue(), destination.getName(), securityConfig);  
          }
    
-         this.securityConfig = securityConfig;
+         destination.setSecurityConfig(securityConfig);
       }
       catch (Throwable t)
       {
@@ -145,18 +170,14 @@
 
    public Element getSecurityConfig()
    {
-      return securityConfig;
+      return destination.getSecurityConfig();
    }
 
    public String getName()
    {
-      return name;
+      return destination.getName();
    }
 
-   public boolean isCreatedProgrammatically()
-   {
-      return createdProgrammatically;
-   }
 
    /**
     * Get in-memory message limit
@@ -164,8 +185,7 @@
     */
    public int getFullSize()
    {
-      // XXX This value should be the same as getting from core destination
-      return fullSize;
+      return destination.getFullSize();
    }
 
    /**
@@ -179,7 +199,7 @@
          log.warn("FullSize can only be changed when destination is stopped");
          return;
       }      
-      this.fullSize = fullSize;
+      destination.setFullSize(fullSize);
    }
 
    /**
@@ -188,8 +208,7 @@
     */
    public int getPageSize()
    {
-      // XXX This value should be the same as getting from core destination
-      return pageSize;
+      return destination.getPageSize();
    }
 
    /**
@@ -203,7 +222,7 @@
          log.warn("PageSize can only be changed when destination is stopped");
          return;
       }
-      this.pageSize = pageSize;
+      destination.setPageSize(pageSize);
    }
 
    /**
@@ -212,8 +231,7 @@
     */
    public int getDownCacheSize()
    {
-      // XXX This value should be the same as getting from core destination
-      return downCacheSize;
+      return destination.getDownCacheSize();
    }
 
    /**
@@ -227,8 +245,23 @@
          log.warn("DownCacheSize can only be changed when destination is stopped");
          return;
       }
-      this.downCacheSize = downCacheSize;
+      destination.setDownCacheSize(downCacheSize);
    }
+   
+   public boolean isClustered()
+   {
+      return destination.isClustered();
+   }
+   
+   public void setClustered(boolean clustered)
+   {
+      if (started)
+      {
+         log.warn("Clustered can only be changed when destination is stopped");
+         return;
+      }
+      destination.setClustered(clustered);
+   }
 
    // JMX managed operations ----------------------------------------
    
@@ -280,15 +313,15 @@
 
    public String toString()
    {
-      String nameFromJNDI = jndiName;
+      String nameFromJNDI = destination.getJndiName();
       int idx = -1;
-      if (jndiName != null)
+      if (nameFromJNDI != null)
       {
-         idx = jndiName.lastIndexOf('/');
+         idx = nameFromJNDI.lastIndexOf('/');
       }
       if (idx != -1)
       {
-         nameFromJNDI = jndiName.substring(idx + 1);
+         nameFromJNDI = nameFromJNDI.substring(idx + 1);
       }
       StringBuffer sb = new StringBuffer();
       if (isQueue())
@@ -300,13 +333,13 @@
          sb.append("Topic");
       }
       sb.append('[');
-      if (name.equals(nameFromJNDI))
+      if (destination.getName().equals(nameFromJNDI))
       {
-         sb.append(jndiName);
+         sb.append(destination.getJndiName());
       }
       else
       {
-         sb.append(jndiName).append(", name=").append(name);
+         sb.append(destination.getJndiName()).append(", name=").append(destination.getName());
       }
       sb.append(']');
       return sb.toString();

Added: trunk/src/main/org/jboss/jms/server/destination/ManagedDestination.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/ManagedDestination.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/destination/ManagedDestination.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,171 @@
+/*
+ * 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.jms.server.destination;
+
+import org.jboss.messaging.core.plugin.contract.PostOffice;
+import org.w3c.dom.Element;
+
+/**
+ * A Destination
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public abstract class ManagedDestination
+{
+   private static final int DEFAULT_FULL_SIZE = 75000;
+   
+   private static final int DEFAULT_PAGE_SIZE = 2000;
+   
+   private static final int DEFAULT_DOWN_CACHE_SIZE = 2000;
+   
+   protected String name;
+   
+   protected String jndiName;
+   
+   protected boolean clustered;
+
+   protected boolean temporary;
+   
+   // Default in memory message number limit
+   protected int fullSize = DEFAULT_FULL_SIZE;
+
+   // Default paging size
+   protected int pageSize = DEFAULT_PAGE_SIZE;
+
+   // Default down-cache size
+   protected int downCacheSize = DEFAULT_DOWN_CACHE_SIZE;
+   
+   protected Element securityConfig;
+   
+   protected PostOffice postOffice;
+
+   public ManagedDestination()
+   {      
+   }
+   
+   /*
+    * Constructor for temporary destinations
+    */
+   public ManagedDestination(String name, int fullSize, int pageSize, int downCacheSize)
+   {
+      this.name = name;
+      this.fullSize = fullSize;
+      this.pageSize = pageSize;
+      this.downCacheSize = downCacheSize;
+   }
+
+   public boolean isClustered()
+   {
+      return clustered;
+   }
+
+   public void setClustered(boolean clustered)
+   {
+      this.clustered = clustered;
+   }
+
+   public int getDownCacheSize()
+   {
+      return downCacheSize;
+   }
+
+   public void setDownCacheSize(int downCacheSize)
+   {
+      this.downCacheSize = downCacheSize;
+   }
+
+   public int getFullSize()
+   {
+      return fullSize;
+   }
+
+   public void setFullSize(int fullSize)
+   {
+      this.fullSize = fullSize;
+   }
+
+   public String getJndiName()
+   {
+      return jndiName;
+   }
+
+   public void setJndiName(String jndiName)
+   {
+      this.jndiName = jndiName;
+   }
+
+   public String getName()
+   {
+      return name;
+   }
+
+   public void setName(String name)
+   {
+      this.name = name;
+   }
+
+   public int getPageSize()
+   {
+      return pageSize;
+   }
+
+   public void setPageSize(int pageSize)
+   {
+      this.pageSize = pageSize;
+   }
+
+   public Element getSecurityConfig()
+   {
+      return securityConfig;
+   }
+
+   public void setSecurityConfig(Element securityConfig)
+   {
+      this.securityConfig = securityConfig;
+   }
+
+   public PostOffice getPostOffice()
+   {
+      return postOffice;
+   }
+
+   public void setPostOffice(PostOffice postOffice)
+   {
+      this.postOffice = postOffice;
+   }
+
+   public boolean isTemporary()
+   {
+      return temporary;
+   }
+
+   public void setTemporary(boolean temporary)
+   {
+      this.temporary = temporary;
+   }
+   
+   public abstract boolean isQueue();
+}

Added: trunk/src/main/org/jboss/jms/server/destination/ManagedQueue.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/ManagedQueue.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/destination/ManagedQueue.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,128 @@
+/*
+ * 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.jms.server.destination;
+
+import java.util.List;
+
+import javax.jms.InvalidSelectorException;
+import javax.jms.JMSException;
+
+import org.jboss.jms.selector.Selector;
+import org.jboss.messaging.core.plugin.contract.Binding;
+import org.w3c.dom.Element;
+
+/**
+ * A ManagedQueue
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
+ * @author <a href="mailto:alex.fu at novell.com">Alex Fu</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class ManagedQueue extends ManagedDestination
+{
+   public ManagedQueue()
+   {      
+   }
+   
+   public ManagedQueue(String name, int fullSize, int pageSize, int downCacheSize)
+   {
+      super(name, fullSize, pageSize, downCacheSize);
+   }
+
+   public int getMessageCount() throws Exception
+   {
+      Binding binding = (Binding)postOffice.listBindingsForCondition(name).get(0);
+      
+      if (binding == null)
+      {
+         throw new IllegalStateException("Cannot find binding for queue:" + name);
+      }
+      
+      org.jboss.messaging.core.local.Queue queue = binding.getQueue();
+
+      return queue.messageCount();
+   }
+   
+   public void removeAllMessages() throws Throwable
+   {
+      Binding binding = (Binding)postOffice.listBindingsForCondition(name).get(0);
+      
+      if (binding == null)
+      {
+         throw new IllegalStateException("Cannot find binding for queue:" + name);
+      }
+      
+      org.jboss.messaging.core.local.Queue queue = binding.getQueue();
+
+      queue.removeAllReferences();
+   }
+   
+   public List listMessages(String selector) throws Exception
+   {
+      if (selector != null)
+      {
+         selector = selector.trim();
+         if (selector.equals(""))
+         {
+            selector = null;
+         }
+      }
+      
+      Binding binding = (Binding)postOffice.listBindingsForCondition(name).get(0);
+      
+      if (binding == null)
+      {
+         throw new IllegalStateException("Cannot find binding for queue:" + name);
+      }
+      
+      org.jboss.messaging.core.local.Queue queue = binding.getQueue();
+
+      try 
+      {
+         List msgs;
+         if (selector == null)
+         {
+            msgs = queue.browse();
+         }
+         else
+         {
+            msgs = queue.browse(new Selector(selector));
+         }
+         return msgs;
+      }
+      catch (InvalidSelectorException e)
+      {
+         Throwable th = new JMSException(e.getMessage());
+         th.initCause(e);
+         throw (JMSException)th;
+      }
+   }
+
+   public boolean isQueue()
+   {
+      return true;
+   }
+}

Added: trunk/src/main/org/jboss/jms/server/destination/ManagedTopic.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/ManagedTopic.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/destination/ManagedTopic.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,261 @@
+/*
+ * 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.jms.server.destination;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.jms.InvalidSelectorException;
+
+import org.jboss.jms.selector.Selector;
+import org.jboss.jms.util.MessageQueueNameHelper;
+import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.plugin.contract.Binding;
+import org.w3c.dom.Element;
+
+/**
+ * A ManagedTopic
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
+ * @author <a href="mailto:alex.fu at novell.com">Alex Fu</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class ManagedTopic extends ManagedDestination
+{
+   public ManagedTopic()
+   {      
+   }
+   
+   public ManagedTopic(String name, int fullSize, int pageSize, int downCacheSize)
+   {
+      super(name, fullSize, pageSize, downCacheSize);
+   }
+
+   public void removeAllMessages() throws Throwable
+   {
+      List subs = postOffice.listBindingsForCondition(name);
+      
+      //XXX How to lock down all subscriptions?
+      Iterator iter = subs.iterator();
+      while (iter.hasNext())
+      {
+         Binding binding = (Binding)iter.next();
+         Queue queue = binding.getQueue();
+         queue.removeAllReferences();
+      }
+   }
+   
+   public int subscriptionCount() throws Exception
+   {
+      List subs = postOffice.listBindingsForCondition(name);
+      
+      return subs.size();         
+   }
+   
+   public int subscriptionCount(boolean durable) throws Exception
+   {
+      List subs = postOffice.listBindingsForCondition(name);
+      
+      Iterator iter = subs.iterator();
+      
+      int count = 0;
+      
+      while (iter.hasNext())
+      {
+         Binding binding = (Binding)iter.next();
+         
+         if ((binding.isDurable() && durable) || (!binding.isDurable() && !durable))
+         {
+            count++;
+         }
+      }
+
+      return count;
+   }
+   
+   public String listSubscriptionsAsText() throws Exception
+   {
+      List subs = postOffice.listBindingsForCondition(name);
+      
+      return getSubscriptionsAsText(subs, true) + getSubscriptionsAsText(subs, false);
+   }
+   
+   public String listSubscriptionsAsText(boolean durable) throws Exception
+   {
+      List subs = postOffice.listBindingsForCondition(name);
+      
+      return getSubscriptionsAsText(subs, durable);
+   }
+   
+   public List listMessagesDurableSub(String subName, String clientID, String selector)
+      throws Exception
+   {
+      List subs = postOffice.listBindingsForCondition(name);
+      
+      return getMessagesFromDurableSub(subs, subName, clientID, trimSelector(selector));
+   }
+   
+   public List listMessagesNonDurableSub(long channelID, String selector)
+      throws Exception
+   {
+      List subs = postOffice.listBindingsForCondition(name);
+      
+      return getMessagesFromNonDurableSub(subs, channelID, trimSelector(selector));
+   }
+   
+   public boolean isQueue()
+   {
+      return false;
+   }
+   
+   // Private -------------------------------------------------------------
+   
+   
+   
+   private String getSubscriptionsAsText(List bindings, boolean durable)
+   {
+      StringBuffer sb = new StringBuffer();
+      Iterator iter = bindings.iterator();
+      while (iter.hasNext())
+      {
+         Binding binding = (Binding)iter.next();
+                  
+         if (durable && binding.isDurable())
+         {                      
+            MessageQueueNameHelper helper = MessageQueueNameHelper.createHelper(binding.getQueueName());
+            
+            sb.append("Durable, subscriptionID=\"");
+            sb.append(binding.getChannelId());    
+            sb.append("\", name=\"");
+            sb.append(helper.getSubName());
+            sb.append("\", clientID=\"");
+            sb.append(helper.getClientId());
+            sb.append("\", selector=\"");
+            sb.append(binding.getSelector());
+            sb.append("\", noLocal=\"");
+            sb.append(binding.isNoLocal());
+            sb.append("\"\n");
+         }
+         else if (!durable && !binding.isDurable())
+         {            
+            sb.append("Non-durable, subscriptionID=\"");
+            sb.append(binding.getChannelId());
+            sb.append("\", selector=\"");
+            sb.append(binding.getSelector());
+            sb.append("\", noLocal=\"");
+            sb.append(binding.isNoLocal());
+            sb.append("\"\n");
+         }
+      }
+      return sb.toString();
+   }
+     
+   // Test if the durable subscriptions match
+   private boolean matchDurableSubscription(String name, String clientID, Binding binding)
+   {
+      // Validate the name
+      if (null == name)
+         throw new IllegalArgumentException();
+      // Must be durable
+      if (!binding.isDurable())
+         return false;
+      
+      MessageQueueNameHelper helper = MessageQueueNameHelper.createHelper(binding.getQueueName());
+
+      // Subscription name check
+      if (!name.equals(helper.getSubName()))
+         return false;
+      // Client ID check: if no client ID specified, it's considered as matched 
+      if (null == clientID || 0 == clientID.length())
+         return true;
+      if (!clientID.equals(helper.getClientId()))
+         return false;
+      return true;
+   }
+   
+   // Test if the non-durable subscriptions match
+   private boolean matchNonDurableSubscription(long channelID, Binding binding)
+   {
+      // Must be non-durable
+      if (binding.isDurable())
+         return false;
+      // Channel ID must be the same
+      if (channelID != binding.getChannelId())
+         return false;
+      return true;
+   }
+   
+   private List getMessagesFromDurableSub(List bindings, String name,
+            String clientID, String selector) throws InvalidSelectorException
+   {
+      Iterator iter = bindings.iterator();
+      while (iter.hasNext())
+      {
+         Binding binding = (Binding)iter.next();
+         // If subID matches, then get message list from the subscription
+         if (matchDurableSubscription(name, clientID, binding))
+         {
+            Queue queue = binding.getQueue();
+            return queue.browse(null == selector ? null : new Selector(selector));
+         }
+      }   
+      // No match, return an empty list
+      return new ArrayList();
+   }
+   
+   private List getMessagesFromNonDurableSub(List bindings, long channelID, String selector) throws InvalidSelectorException
+   {
+      Iterator iter = bindings.iterator();
+      while (iter.hasNext())
+      {
+         Binding binding = (Binding)iter.next();
+         // If subID matches, then get message list from the subscription
+         if (matchNonDurableSubscription(channelID, binding))
+            return binding.getQueue().browse(null == selector ? null : new Selector(selector));
+      }   
+      // No match, return an empty list
+      return new ArrayList();
+   }
+   
+   private String trimSelector(String selector)
+   {
+      if (selector == null)
+      {
+         return null;
+      }
+
+      selector = selector.trim();
+
+      if (selector.length() == 0)
+      {
+         return null;
+      }
+
+      return selector;
+   }
+
+}

Deleted: trunk/src/main/org/jboss/jms/server/destination/Queue.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/Queue.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/destination/Queue.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -1,269 +0,0 @@
-/**
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package org.jboss.jms.server.destination;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.jms.InvalidSelectorException;
-import javax.jms.JMSException;
-
-import org.jboss.jms.destination.JBossQueue;
-import org.jboss.jms.selector.Selector;
-import org.jboss.jms.server.ServerPeer;
-import org.jboss.jms.util.ExceptionUtil;
-import org.jboss.jms.util.XMLUtil;
-import org.jboss.messaging.core.local.MessageQueue;
-import org.jboss.messaging.core.memory.MemoryManager;
-import org.jboss.messaging.core.plugin.contract.MessageStore;
-import org.jboss.messaging.core.plugin.contract.PersistenceManager;
-import org.jboss.messaging.core.plugin.exchange.Binding;
-
-/**
- * A deployable JBoss Messaging queue.
- *
- * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @author <a href="mailto:alex.fu at novell.com">Alex Fu</a>
- * @version <tt>$Revision$</tt>
- *
- * $Id$
- */
-public class Queue extends DestinationServiceSupport
-{
-   // Constants -----------------------------------------------------
-
-   // Static --------------------------------------------------------
-   
-   // Attributes ----------------------------------------------------
-
-   // Constructors --------------------------------------------------
-
-   public Queue()
-   {
-      super(false);
-   }
-
-   public Queue(boolean createProgrammatically)
-   {
-      super(createProgrammatically);
-   }
-
-   // JMX managed attributes ----------------------------------------
-   
-   public int getMessageCount() throws Exception
-   {
-      try
-      {
-         if (!started)
-         {
-            log.warn("Queue is stopped.");
-            return 0;
-         }
-         
-         Binding binding = (Binding)exchange.listBindingsForWildcard(name).get(0);
-         
-         if (binding == null)
-         {
-            throw new IllegalStateException("Cannot find binding for queue:" + name);
-         }
-         
-         MessageQueue queue = binding.getQueue();
-   
-   	   return queue.messageCount();
-      }
-      catch (Throwable t)
-      {
-         throw ExceptionUtil.handleJMXInvocation(t, this + " getMessageCount");
-      }
-   }
-
-   // JMX managed operations ----------------------------------------
-   
-   public synchronized void startService() throws Exception
-   {
-      try
-      {
-         started = true;
-   
-         if (serviceName != null)
-         {
-            name = serviceName.getKeyProperty("name");
-         }
-   
-         if (name == null || name.length() == 0)
-         {
-            throw new IllegalStateException( "The " + (isQueue() ? "queue" : "topic") + " " +
-                                             "name was not properly set in the service's" +
-                                             "ObjectName");
-         }
-   
-         ServerPeer serverPeer = (ServerPeer)server.getAttribute(serverPeerObjectName, "Instance");
-
-         dm = serverPeer.getDestinationManager();
-         sm = serverPeer.getSecurityManager();         
-         exchange = serverPeer.getDirectExchangeDelegate();
-         
-         //Binding must be added before destination is registered in JNDI
-         //otherwise the user could get a reference to the destination and use it
-         //while it is still being loaded
-         
-         MessageStore ms = serverPeer.getMessageStore();
-         PersistenceManager pm = serverPeer.getPersistenceManagerDelegate(); 
-         //Binding might already exist
-         
-         log.info("Deploying queue");
-         
-         Binding binding = exchange.getBindingForName(name);
-         
-         log.info("binding is: " + binding);
-         
-         if (binding != null)
-         {
-            //Reload the queue for the binding
-            log.info("reloading queue");
-            exchange.reloadQueues(name, ms, pm, fullSize, pageSize, downCacheSize);
-            log.info("reloaded queue");
-         }
-         else
-         {         
-            //Make a binding for this queue
-            log.info("bidning queue");
-            exchange.bindQueue(name, name, null, false, true, ms, pm, fullSize, pageSize, downCacheSize);
-            log.info("bound queue");
-         }
-         
-         JBossQueue q = new JBossQueue(name, fullSize, pageSize, downCacheSize);
-         
-         jndiName = dm.registerDestination(q, jndiName, securityConfig);
-        
-         log.debug(this + " security configuration: " + (securityConfig == null ?
-            "null" : "\n" + XMLUtil.elementToString(securityConfig)));
-
-         log.info(this + " started, fullSize=" + fullSize + ", pageSize=" + pageSize + ", downCacheSize=" + downCacheSize);
-      }
-      catch (Throwable t)
-      {
-         ExceptionUtil.handleJMXInvocation(t, this + " startService");
-      }
-   }
-
-   public void stopService() throws Exception
-   {
-      try
-      {
-         dm.unregisterDestination(new JBossQueue(name));
-         
-         //We undeploy the queue from memory - this also deactivates the binding
-         exchange.unloadQueues(name);
-         
-         started = false;
-         
-         log.info(this + " stopped");
-      }
-      catch (Throwable t)
-      {
-         ExceptionUtil.handleJMXInvocation(t, this + " stopService");
-      }
-   }
-   
-   public void removeAllMessages() throws Exception
-   {
-      try
-      {
-         if (!started)
-         {
-            log.warn("Queue is stopped.");
-            return;
-         }
-         
-         Binding binding = (Binding)exchange.listBindingsForWildcard(name).get(0);
-         
-         if (binding == null)
-         {
-            throw new IllegalStateException("Cannot find binding for queue:" + name);
-         }
-         
-         MessageQueue queue = binding.getQueue();
-   
-         queue.removeAllReferences();
-      }
-      catch (Throwable t)
-      {
-         throw ExceptionUtil.handleJMXInvocation(t, this + " removeAllMessages");
-      } 
-   }
-   
-   public List listMessages(String selector) throws Exception
-   {
-      try
-      {
-         if (!started)
-         {
-            log.warn("Queue is stopped.");
-            return new ArrayList();
-         }
-         
-         if (selector != null)
-         {
-            selector = selector.trim();
-            if (selector.equals(""))
-            {
-               selector = null;
-            }
-         }
-         
-         Binding binding = (Binding)exchange.listBindingsForWildcard(name).get(0);
-         
-         if (binding == null)
-         {
-            throw new IllegalStateException("Cannot find binding for queue:" + name);
-         }
-         
-         MessageQueue queue = binding.getQueue();
-   
-         try 
-         {
-            List msgs;
-            if (selector == null)
-            {
-               msgs = queue.browse();
-            }
-            else
-            {
-               msgs = queue.browse(new Selector(selector));
-            }
-            return msgs;
-         }
-         catch (InvalidSelectorException e)
-         {
-            Throwable th = new JMSException(e.getMessage());
-            th.initCause(e);
-            throw (JMSException)th;
-         }
-      }
-      catch (Throwable t)
-      {
-         throw ExceptionUtil.handleJMXInvocation(t, this + " listMessages");
-      } 
-   }
-    
-   // Public --------------------------------------------------------
-
-   // Package protected ---------------------------------------------
-
-   // Protected -----------------------------------------------------
-
-   protected boolean isQueue()
-   {
-      return true;
-   }
-
-   // Private -------------------------------------------------------
-
-   // Inner classes -------------------------------------------------
-}

Copied: trunk/src/main/org/jboss/jms/server/destination/QueueService.java (from rev 1269, trunk/src/main/org/jboss/jms/server/destination/Queue.java)
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/Queue.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/destination/QueueService.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,213 @@
+/**
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package org.jboss.jms.server.destination;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jboss.jms.util.ExceptionUtil;
+import org.jboss.jms.util.XMLUtil;
+import org.jboss.messaging.core.plugin.contract.Binding;
+
+import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
+
+/**
+ * MBean wrapper around a ManagedQueue
+ *
+ * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @author <a href="mailto:alex.fu at novell.com">Alex Fu</a>
+ * @version <tt>$Revision$</tt>
+ *
+ * $Id$
+ */
+public class QueueService extends DestinationServiceSupport
+{
+   // Constants -----------------------------------------------------
+
+   // Static --------------------------------------------------------
+   
+   // Attributes ----------------------------------------------------
+   
+   // Constructors --------------------------------------------------
+   
+   public QueueService()
+   {
+      destination = new ManagedQueue();      
+   }
+
+   // JMX managed attributes ----------------------------------------
+   
+   public int getMessageCount() throws Exception
+   {
+      try
+      {
+         if (!started)
+         {
+            log.warn("Queue is stopped.");
+            return 0;
+         }
+         
+         return ((ManagedQueue)destination).getMessageCount();
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " getMessageCount");
+      }
+   }
+
+   // JMX managed operations ----------------------------------------
+   
+   public synchronized void startService() throws Exception
+   {
+      super.startService();
+      
+      try
+      {
+         started = true;
+                                    
+         postOffice = serverPeer.getQueuePostOfficeInstance();
+         
+         destination.setPostOffice(postOffice);
+
+         //Binding must be added before destination is registered in JNDI
+         //otherwise the user could get a reference to the destination and use it
+         //while it is still being loaded
+         
+         //Binding might already exist
+         
+         log.info("Deploying queue: " + destination.getName());
+         
+         Binding binding = postOffice.getBindingForQueueName(destination.getName());
+         
+         QueuedExecutor executor = (QueuedExecutor)pool.get();
+         
+         if (binding != null)
+         {
+            log.info("Binding already exists!");
+            //Reload the queue for the binding
+            if (binding.isActive())
+            {
+               //Do nothing - binding is already active
+            }
+            else
+            {
+               org.jboss.messaging.core.local.Queue q = 
+                  new org.jboss.messaging.core.local.Queue(binding.getChannelId(), ms, pm, true, true,
+                           destination.getFullSize(), destination.getPageSize(), destination.getDownCacheSize(),
+                           executor, null);
+               q.load();
+               binding.setQueue(q);
+               binding.activate();
+            }
+         }
+         else
+         {         
+            //Create a new queue            
+            
+            org.jboss.messaging.core.local.Queue q = 
+               new org.jboss.messaging.core.local.Queue(idm.getId(), ms, pm, true, true,
+                        destination.getFullSize(), destination.getPageSize(), destination.getDownCacheSize(),
+                        executor, null);
+            
+            //Make a binding for this queue
+            postOffice.bindQueue(destination.getName(), destination.getName(), false, q);
+         }
+         
+         //push security update to the server
+         sm.setSecurityConfig(isQueue(), destination.getName(), destination.getSecurityConfig());
+          
+         dm.registerDestination(destination);
+        
+         log.debug(this + " security configuration: " + (destination.getSecurityConfig() == null ?
+            "null" : "\n" + XMLUtil.elementToString(destination.getSecurityConfig())));
+
+         log.info(this + " started, fullSize=" + destination.getFullSize() +
+                  ", pageSize=" + destination.getPageSize() + ", downCacheSize=" + destination.getDownCacheSize());
+      }
+      catch (Throwable t)
+      {
+         ExceptionUtil.handleJMXInvocation(t, this + " startService");
+      }
+   }
+
+   public void stopService() throws Exception
+   {
+      try
+      {
+         dm.unregisterDestination(destination);
+         
+         //We undeploy the queue from memory - this also deactivates the binding
+         Binding binding = postOffice.getBindingForQueueName(destination.getName());
+         
+         if (binding.isActive())
+         {
+            binding.deactivate();
+            binding.setQueue(null);
+         }
+         
+         started = false;
+         
+         log.info(this + " stopped");
+      }
+      catch (Throwable t)
+      {
+         ExceptionUtil.handleJMXInvocation(t, this + " stopService");
+      }
+   }
+   
+   public void removeAllMessages() throws Exception
+   {
+      try
+      {
+         if (!started)
+         {
+            log.warn("Queue is stopped.");
+            return;
+         }
+         
+         ((ManagedQueue)destination).removeAllMessages();
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " removeAllMessages");
+      } 
+   }
+   
+   public List listMessages(String selector) throws Exception
+   {
+      try
+      {
+         if (!started)
+         {
+            log.warn("Queue is stopped.");
+            return new ArrayList();
+         }
+         
+         return ((ManagedQueue)destination).listMessages(selector);
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " listMessages");
+      } 
+   }
+    
+   // Public --------------------------------------------------------
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   protected boolean isQueue()
+   {
+      return true;
+   }
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+}

Deleted: trunk/src/main/org/jboss/jms/server/destination/Topic.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/Topic.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/destination/Topic.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -1,634 +0,0 @@
-/**
- * JBoss, Home of Professional Open Source
- *
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
- */
-package org.jboss.jms.server.destination;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import javax.jms.InvalidSelectorException;
-import javax.jms.JMSException;
-
-import org.jboss.jms.destination.JBossTopic;
-import org.jboss.jms.selector.Selector;
-import org.jboss.jms.server.ServerPeer;
-import org.jboss.jms.util.ExceptionUtil;
-import org.jboss.jms.util.MessageQueueNameHelper;
-import org.jboss.jms.util.XMLUtil;
-import org.jboss.messaging.core.local.MessageQueue;
-import org.jboss.messaging.core.memory.MemoryManager;
-import org.jboss.messaging.core.plugin.contract.MessageStore;
-import org.jboss.messaging.core.plugin.contract.PersistenceManager;
-import org.jboss.messaging.core.plugin.exchange.Binding;
-
-
-/**
- * A deployable JBoss Messaging topic.
- *
- * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @author <a href="mailto:alex.fu at novell.com">Alex Fu</a>
- * @version <tt>$Revision$</tt>
- *
- * $Id$
- */
-public class Topic extends DestinationServiceSupport
-{
-   // Constants -----------------------------------------------------
-
-   // Static --------------------------------------------------------
-
-   // Attributes ----------------------------------------------------
-
-   // Constructors --------------------------------------------------
-
-   public Topic()
-   {
-      super(false);
-   }
-
-   public Topic(boolean createProgrammatically)
-   {
-      super(createProgrammatically);
-   }
-
-   // JMX managed attributes ----------------------------------------
-
-   // JMX managed operations ----------------------------------------
-   
-   public synchronized void startService() throws Exception
-   {
-      try
-      {
-         started = true;
-   
-         if (serviceName != null)
-         {
-            name = serviceName.getKeyProperty("name");
-         }
-   
-         if (name == null || name.length() == 0)
-         {
-            throw new IllegalStateException( "The " + (isQueue() ? "queue" : "topic") + " " +
-                                             "name was not properly set in the service's" +
-                                             "ObjectName");
-         }
-   
-         ServerPeer serverPeer = (ServerPeer)server.getAttribute(serverPeerObjectName, "Instance");
-
-         dm = serverPeer.getDestinationManager();
-         sm = serverPeer.getSecurityManager();
-         exchange = serverPeer.getTopicExchangeDelegate();
-         
-         MessageStore ms = serverPeer.getMessageStore();
-         PersistenceManager pm = serverPeer.getPersistenceManagerDelegate();
-        
-         //We deploy any queues corresponding to pre-existing durable subscriptions
-         exchange.reloadQueues(name, ms, pm, fullSize, pageSize, downCacheSize);
-                  
-         JBossTopic t = new JBossTopic(name, fullSize, pageSize, downCacheSize);
-         
-         jndiName = dm.registerDestination(t, jndiName, securityConfig);
-         
-         log.debug(this + " security configuration: " + (securityConfig == null ?
-            "null" : "\n" + XMLUtil.elementToString(securityConfig)));
-
-         log.info(this + " started, fullSize=" + fullSize + ", pageSize=" + pageSize + ", downCacheSize=" + downCacheSize);
-      }
-      catch (Throwable t)
-      {
-         ExceptionUtil.handleJMXInvocation(t, this + " startService");
-      }
-   }
-
-   public void stopService() throws Exception
-   {
-      try
-      {
-         dm.unregisterDestination(new JBossTopic(name));
-         
-         //When undeploying a topic, any non durable subscriptions will be removed
-         //Any durable subscriptions will survive in persistent storage, but be removed
-         //from memory
-         
-         //First we remove any data for a non durable sub - a non durable sub might have data in the
-         //database since it might have paged
-         
-         List bindings = exchange.listBindingsForWildcard(name);
-         
-         Iterator iter = bindings.iterator();
-         while (iter.hasNext())            
-         {
-            Binding binding = (Binding)iter.next();
-            
-            if (!binding.isDurable())
-            {
-               binding.getQueue().removeAllReferences();
-            }
-         }
-          
-         //We undeploy the queues for the subscriptions - this also unbinds the bindings
-         exchange.unloadQueues(name);
-         
-         started = false;
-         log.info(this + " stopped");
-      }
-      catch (Throwable t)
-      {
-         ExceptionUtil.handleJMXInvocation(t, this + " stopService");
-      }
-   }
-
-   /**
-    * Remove all messages from subscription's storage.
-    */
-   public void removeAllMessages() throws Exception
-   {
-      try
-      {
-         if (!started)
-         {
-            log.warn("Topic is stopped.");
-            return;
-         }
-         
-         List subs = exchange.listBindingsForWildcard(name);
-         
-         //XXX How to lock down all subscriptions?
-         Iterator iter = subs.iterator();
-         while (iter.hasNext())
-         {
-            Binding binding = (Binding)iter.next();
-            MessageQueue queue = binding.getQueue();
-            queue.removeAllReferences();
-         }
-      }
-      catch (Throwable t)
-      {
-         throw ExceptionUtil.handleJMXInvocation(t, this + " removeAllMessages");
-      } 
-   }
-   
-   /**
-    * All subscription count
-    * @return all subscription count
-    * @throws JMSException
-    */
-   public int subscriptionCount() throws Exception
-   {
-      try
-      {
-         if (!started)
-         {
-            log.warn("Topic is stopped.");
-            return 0;
-         }
-   
-         List subs = exchange.listBindingsForWildcard(name);
-         
-         return subs.size();         
-      }
-      catch (Throwable t)
-      {
-         throw ExceptionUtil.handleJMXInvocation(t, this + " subscriptionCount");
-      } 
-   }
-
-   /**
-    * Durable/nondurable subscription count
-    * @param durable If true return durable subscription count.
-    *                If false return nondurable subscription count.
-    * @return either durable or nondurable subscription count depending on param.
-    * @throws JMSException
-    */
-   public int subscriptionCount(boolean durable) throws Exception
-   {
-      try
-      {
-         if (!started)
-         {
-            log.warn("Topic is stopped.");
-            return 0;
-         }
-         
-         List subs = exchange.listBindingsForWildcard(name);
-         
-         Iterator iter = subs.iterator();
-         
-         int count = 0;
-         
-         while (iter.hasNext())
-         {
-            Binding binding = (Binding)iter.next();
-            
-            if ((binding.isDurable() && durable) || (!binding.isDurable() && !durable))
-            {
-               count++;
-            }
-         }
-   
-         return count;
-      }
-      catch (Throwable t)
-      {
-         throw ExceptionUtil.handleJMXInvocation(t, this + " subscriptionCount");
-      } 
-   }
-
-   /**
-    * XXX Placeholder
-    * Get all subscription list.
-    * @return List of CoreSubscription. Never null. 
-    * @throws JMSException
-    * @see ManageableTopic#getSubscriptions()
-    */
-   /*
-   public List listSubscriptions() throws JMSException
-   {
-      JBossTopic jbt = new JBossTopic(name);
-      ManageableTopic t = (ManageableTopic)cm.getCoreDestination(jbt);
-      return t.getSubscriptions();
-   }
-   */
-
-   /**
-    * Returns a human readable list containing the names of current subscriptions.
-    * @return String of subscription list. Never null.
-    */
-   public String listSubscriptionsAsText() throws Exception
-   {
-      try
-      {
-         if (!started)
-         {
-            log.warn("Topic is stopped.");
-            return "";
-         }
-   
-         List subs = exchange.listBindingsForWildcard(name);
-         
-         return getSubscriptionsAsText(subs, true) + getSubscriptionsAsText(subs, false);
-      }
-      catch (Throwable t)
-      {
-         throw ExceptionUtil.handleJMXInvocation(t, this + " listSubscriptionsAsText");
-      } 
-   }
-   
-   
-
-   /**
-    * Returns a human readable list containing the names of current subscriptions.
-    * @param durable If true, return durable subscription list.
-    *                If false, return non-durable subscription list.
-    * @return String of subscription list. Never null.
-    */
-   public String listSubscriptionsAsText(boolean durable) throws Exception
-   {
-      try
-      {
-         if (!started)
-         {
-            log.warn("Topic is stopped.");
-            return "";
-         }
-   
-         List subs = exchange.listBindingsForWildcard(name);
-         
-         return getSubscriptionsAsText(subs, durable);
-      }
-      catch (Throwable t)
-      {
-         throw ExceptionUtil.handleJMXInvocation(t, this + " listSubscriptionsAsText");
-      } 
-   }
-
-   /**
-    * XXX Placeholder
-    * Get durable/non-durable subscription list.
-    * @param durable If true, return durable subscription list.
-    *                If false, return non-durable subscription list.
-    * @return List of CoreDurableSubscription/CoreSubscription. Never null.
-    * @throws JMSException
-    * @see ManageableTopic#getSubscriptions(boolean)
-    */
-   /*
-   public List listSubscriptions(boolean durable) throws JMSException
-   {
-      JBossTopic jbt = new JBossTopic(name);
-      ManageableTopic t = (ManageableTopic)cm.getCoreDestination(jbt);
-      return t.getSubscriptions(durable);
-   }
-   */
-   
-   /**
-    * XXX Placeholder
-    * Get messages from certain subscription.
-    * @param channelID @see #listSubscriptions()
-    * @param clientID @see #listSubscriptions()
-    * @param subName @see #listSubscriptions()
-    * @param selector Filter expression
-    * @return list of javax.jms.Message
-    * @throws JMSException
-    * @see ManageableTopic#getMessages(long, String, String, String)
-    */
-   /*
-   public List listMessages(long channelID, String clientID, String subName, String selector)
-      throws JMSException
-   {
-      JBossTopic jbt = new JBossTopic(name);
-      ManageableTopic t = (ManageableTopic)cm.getCoreDestination(jbt);
-      return t.getMessages(channelID, clientID, subName, trimSelector(selector));
-   }
-   */
-   
-   /**
-    * Get messages from a durable subscription.
-    * @param subName Subscription name.
-    * @param clientID Client ID.
-    * @param selector Filter expression.
-    * @return list of javax.jms.Message
-    * @throws JMSException
-    * @see ManageableTopic#getMessagesFromDurableSub(String, String, String)
-    */
-   public List listMessagesDurableSub(String subName, String clientID, String selector)
-      throws Exception
-   {
-      try
-      {
-         if (!started)
-         {
-            log.warn("Topic is stopped.");
-            return new ArrayList();
-         }
-   
-         List subs = exchange.listBindingsForWildcard(name);
-         
-         return getMessagesFromDurableSub(subs, subName, clientID, trimSelector(selector));
-      }
-      catch (Throwable t)
-      {
-         throw ExceptionUtil.handleJMXInvocation(t, this + " listMessagesDurableSub");
-      } 
-   }
-   
-   /**
-    * Get messages from a non-durable subscription.
-    * @param channelID
-    * @param selector Filter expression.
-    * @return list of javax.jms.Message
-    * @throws JMSException
-    * @see ManageableTopic#getMessagesFromNonDurableSub(Long, String)
-    */
-   public List listMessagesNonDurableSub(long channelID, String selector)
-      throws Exception
-   {
-      try
-      {
-         if (!started)
-         {
-            log.warn("Topic is stopped.");
-            return new ArrayList();
-         }
-         
-         List subs = exchange.listBindingsForWildcard(name);
-         
-         return getMessagesFromNonDurableSub(subs, channelID, trimSelector(selector));
-      }
-      catch (Throwable t)
-      {
-         throw ExceptionUtil.handleJMXInvocation(t, this + " listMessagesNonDurableSub");
-      } 
-   }
-
-   
-   // TODO implement these:
-
-//   int getAllMessageCount();
-//
-//   int getDurableMessageCount();
-//
-//   int getNonDurableMessageCount();
-//
-//   int getAllSubscriptionsCount();
-//
-//   int getDurableSubscriptionsCount();
-//
-//   int getNonDurableSubscriptionsCount();
-//
-//   java.util.List listAllSubscriptions();
-//
-//   java.util.List listDurableSubscriptions();
-//
-//   java.util.List listNonDurableSubscriptions();
-//
-//   java.util.List listMessages(java.lang.String id) throws java.lang.Exception;
-//
-//   java.util.List listMessages(java.lang.String id, java.lang.String selector) throws java.lang.Exception;
-//
-//   List listNonDurableMessages(String id, String sub) throws Exception;
-//
-//   List listNonDurableMessages(String id, String sub, String selector) throws Exception;
-//
-//   List listDurableMessages(String id, String name) throws Exception;
-//
-//   List listDurableMessages(String id, String name, String selector) throws Exception;
-
-   // Public --------------------------------------------------------
-
-   // Package protected ---------------------------------------------
-
-   // Protected -----------------------------------------------------
-
-   protected boolean isQueue()
-   {
-      return false;
-   }
-   
-   protected String getSubscriptionsAsText(List bindings, boolean durable)
-   {
-      StringBuffer sb = new StringBuffer();
-      Iterator iter = bindings.iterator();
-      while (iter.hasNext())
-      {
-         Binding binding = (Binding)iter.next();
-                  
-         if (durable && binding.isDurable())
-         {                      
-            MessageQueueNameHelper helper = MessageQueueNameHelper.createHelper(binding.getQueueName());
-            
-            sb.append("Durable, subscriptionID=\"");
-            sb.append(binding.getChannelId());    
-            sb.append("\", name=\"");
-            sb.append(helper.getSubName());
-            sb.append("\", clientID=\"");
-            sb.append(helper.getClientId());
-            sb.append("\", selector=\"");
-            sb.append(binding.getSelector());
-            sb.append("\", noLocal=\"");
-            sb.append(binding.isNoLocal());
-            sb.append("\"\n");
-         }
-         else if (!durable && !binding.isDurable())
-         {            
-            sb.append("Non-durable, subscriptionID=\"");
-            sb.append(binding.getChannelId());
-            sb.append("\", selector=\"");
-            sb.append(binding.getSelector());
-            sb.append("\", noLocal=\"");
-            sb.append(binding.isNoLocal());
-            sb.append("\"\n");
-         }
-      }
-      return sb.toString();
-   }
-   
-   protected List getMessagesFromDurableSub(List bindings, String name,
-                                            String clientID, String selector) throws InvalidSelectorException
-   {
-      Iterator iter = bindings.iterator();
-      while (iter.hasNext())
-      {
-         Binding binding = (Binding)iter.next();
-         // If subID matches, then get message list from the subscription
-         if (matchDurableSubscription(name, clientID, binding))
-         {
-            MessageQueue queue = binding.getQueue();
-            return queue.browse(null == selector ? null : new Selector(selector));
-         }
-      }   
-      // No match, return an empty list
-      return new ArrayList();
-   }
-   
-   /**
-    * @see ManageableTopic#getMessagesFromNonDurableSub(Long, String)
-    */
-   public List getMessagesFromNonDurableSub(List bindings, long channelID, String selector) throws InvalidSelectorException
-   {
-      Iterator iter = bindings.iterator();
-      while (iter.hasNext())
-      {
-         Binding binding = (Binding)iter.next();
-         // If subID matches, then get message list from the subscription
-         if (matchNonDurableSubscription(channelID, binding))
-            return binding.getQueue().browse(null == selector ? null : new Selector(selector));
-      }   
-      // No match, return an empty list
-      return new ArrayList();
-   }
-
-   // Test if the durable subscriptions match
-   private boolean matchDurableSubscription(String name, String clientID, Binding binding)
-   {
-      // Validate the name
-      if (null == name)
-         throw new IllegalArgumentException();
-      // Must be durable
-      if (!binding.isDurable())
-         return false;
-      
-      MessageQueueNameHelper helper = MessageQueueNameHelper.createHelper(binding.getQueueName());
-
-      // Subscription name check
-      if (!name.equals(helper.getSubName()))
-         return false;
-      // Client ID check: if no client ID specified, it's considered as matched 
-      if (null == clientID || 0 == clientID.length())
-         return true;
-      if (!clientID.equals(helper.getClientId()))
-         return false;
-      return true;
-   }
-   
-   // Test if the non-durable subscriptions match
-   private boolean matchNonDurableSubscription(long channelID, Binding binding)
-   {
-      // Must be non-durable
-      if (binding.isDurable())
-         return false;
-      // Channel ID must be the same
-      if (channelID != binding.getChannelId())
-         return false;
-      return true;
-   }
-   
-   /**
-    * XXX Placeholder
-    * @see ManageableTopic#getSubscriptions()
-    */
-   /*
-   public List getSubscriptions()
-   {
-      ArrayList list = new ArrayList();
-      Iterator iter = iterator();
-      while (iter.hasNext())
-      {
-         CoreSubscription sub = (CoreSubscription)iter.next();
-         if (sub instanceof CoreDurableSubscription)
-            list.add(new String[]{ 
-                        Long.toString(sub.getChannelID()), 
-                        ((CoreDurableSubscription)sub).getClientID(),
-                        ((CoreDurableSubscription)sub).getName()});
-         else
-            list.add(new String[]{ 
-                  Long.toString(sub.getChannelID()), "", ""});
-      }
-      return list;
-   }
-   */
-   
-   
-   /**
-    * XXX Placeholder
-    * @see ManageableTopic#getSubscriptions(boolean)
-    */
-   /*
-   public List getSubscriptions(boolean durable)
-   {
-      ArrayList list = new ArrayList();
-      Iterator iter = iterator();
-      while (iter.hasNext())
-      {
-         CoreSubscription sub = (CoreSubscription)iter.next();
-         if (sub instanceof CoreDurableSubscription && durable)
-            list.add(new String[]{ 
-                        Long.toString(sub.getChannelID()), 
-                        ((CoreDurableSubscription)sub).getClientID(),
-                        ((CoreDurableSubscription)sub).getName()});
-         else if (!(sub instanceof CoreDurableSubscription) && !durable)
-            list.add(new String[]{ 
-                  Long.toString(sub.getChannelID()), "", ""});
-      }
-      return list;
-   }
-   */   
-   
-   /**
-    * XXX Placeholder
-    * @see ManageableTopic#getMessages(long, String, String, String)
-    */
-   /*
-   public List getMessages(long channelID, String clientID, String subName, String selector) throws InvalidSelectorException
-   {
-      Iterator iter = iterator();
-      while (iter.hasNext())
-      {
-         CoreSubscription sub = (CoreSubscription)iter.next();
-         // If subID matches, then get message list from the subscription
-         if (matchSubscription(channelID, clientID, subName, sub))
-            return sub.browse(null == selector ? null : new Selector(selector));
-      }   
-      // No match, return an empty list
-      return new ArrayList();
-   }
-   */
-
-   // Private -------------------------------------------------------
-
-   // Inner classes -------------------------------------------------
-}

Copied: trunk/src/main/org/jboss/jms/server/destination/TopicService.java (from rev 1269, trunk/src/main/org/jboss/jms/server/destination/Topic.java)
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/Topic.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/destination/TopicService.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,484 @@
+/**
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package org.jboss.jms.server.destination;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.jms.JMSException;
+
+import org.jboss.jms.server.QueuedExecutorPool;
+import org.jboss.jms.util.ExceptionUtil;
+import org.jboss.jms.util.XMLUtil;
+import org.jboss.messaging.core.plugin.contract.Binding;
+
+import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
+
+/**
+ * A deployable JBoss Messaging topic.
+ *
+ * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @author <a href="mailto:alex.fu at novell.com">Alex Fu</a>
+ * @version <tt>$Revision$</tt>
+ *
+ * $Id$
+ */
+public class TopicService extends DestinationServiceSupport
+{
+   // Constants -----------------------------------------------------
+
+   // Static --------------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   public TopicService()
+   {
+      destination = new ManagedTopic();      
+   }
+
+   // JMX managed attributes ----------------------------------------
+
+   // JMX managed operations ----------------------------------------
+   
+   public synchronized void startService() throws Exception
+   {
+      super.startService();
+      
+      try
+      {
+         postOffice = serverPeer.getTopicPostOfficeInstance();
+         
+         destination.setPostOffice(postOffice);
+           
+         // We deploy any queues corresponding to pre-existing durable subscriptions
+         List bindings = postOffice.listBindingsForCondition(destination.getName());
+         Iterator iter = bindings.iterator();
+         while (iter.hasNext())
+         {
+            Binding binding = (Binding)iter.next();
+            if (binding.isActive())
+            {
+               //Do nothing - already active
+            }
+            else
+            {
+               QueuedExecutorPool pool = serverPeer.getQueuedExecutorPool();
+               QueuedExecutor executor = (QueuedExecutor)pool.get();
+               org.jboss.messaging.core.local.Queue q = 
+                  new org.jboss.messaging.core.local.Queue(binding.getChannelId(), ms, pm, true, true,
+                           destination.getFullSize(), destination.getPageSize(), destination.getDownCacheSize(),
+                           executor, null);
+               q.load();
+               binding.setQueue(q);
+               binding.activate();
+            }
+         }
+
+         // push security update to the server
+         sm.setSecurityConfig(isQueue(), destination.getName(), destination.getSecurityConfig());
+                   
+         dm.registerDestination(destination);
+         
+         log.debug(this + " security configuration: " + (destination.getSecurityConfig() == null ?
+            "null" : "\n" + XMLUtil.elementToString(destination.getSecurityConfig())));
+
+         log.info(this + " started, fullSize=" + destination.getFullSize() + ", pageSize=" + destination.getPageSize() + ", downCacheSize=" + destination.getDownCacheSize());
+      }
+      catch (Throwable t)
+      {
+         ExceptionUtil.handleJMXInvocation(t, this + " startService");
+      }
+   }
+
+   public void stopService() throws Exception
+   {
+      try
+      {
+         dm.unregisterDestination(destination);
+         
+         //When undeploying a topic, any non durable subscriptions will be removed
+         //Any durable subscriptions will survive in persistent storage, but be removed
+         //from memory
+         
+         //First we remove any data for a non durable sub - a non durable sub might have data in the
+         //database since it might have paged
+         
+         List bindings = postOffice.listBindingsForCondition(destination.getName());
+         
+         Iterator iter = bindings.iterator();
+         while (iter.hasNext())            
+         {
+            Binding binding = (Binding)iter.next();
+            
+            binding.deactivate();
+            
+            if (!binding.isDurable())
+            {
+               binding.getQueue().removeAllReferences();
+            }
+            
+            binding.setQueue(null);
+         }
+          
+         started = false;
+         log.info(this + " stopped");
+      }
+      catch (Throwable t)
+      {
+         ExceptionUtil.handleJMXInvocation(t, this + " stopService");
+      }
+   }
+
+   /**
+    * Remove all messages from subscription's storage.
+    */
+   public void removeAllMessages() throws Exception
+   {
+      try
+      {
+         if (!started)
+         {
+            log.warn("Topic is stopped.");
+            return;
+         }
+         
+         ((ManagedTopic)destination).removeAllMessages();
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " removeAllMessages");
+      } 
+   }
+   
+   /**
+    * All subscription count
+    * @return all subscription count
+    * @throws JMSException
+    */
+   public int subscriptionCount() throws Exception
+   {
+      try
+      {
+         if (!started)
+         {
+            log.warn("Topic is stopped.");
+            return 0;
+         }
+   
+         return ((ManagedTopic)destination).subscriptionCount();        
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " subscriptionCount");
+      } 
+   }
+
+   /**
+    * Durable/nondurable subscription count
+    * @param durable If true return durable subscription count.
+    *                If false return nondurable subscription count.
+    * @return either durable or nondurable subscription count depending on param.
+    * @throws JMSException
+    */
+   public int subscriptionCount(boolean durable) throws Exception
+   {
+      try
+      {
+         if (!started)
+         {
+            log.warn("Topic is stopped.");
+            return 0;
+         }
+         
+         return ((ManagedTopic)destination).subscriptionCount(durable);
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " subscriptionCount");
+      } 
+   }
+
+   /**
+    * XXX Placeholder
+    * Get all subscription list.
+    * @return List of CoreSubscription. Never null. 
+    * @throws JMSException
+    * @see ManageableTopic#getSubscriptions()
+    */
+   /*
+   public List listSubscriptions() throws JMSException
+   {
+   }
+   */
+
+   /**
+    * Returns a human readable list containing the names of current subscriptions.
+    * @return String of subscription list. Never null.
+    */
+   public String listSubscriptionsAsText() throws Exception
+   {
+      try
+      {
+         if (!started)
+         {
+            log.warn("Topic is stopped.");
+            return "";
+         }
+   
+         return ((ManagedTopic)destination).listSubscriptionsAsText();
+
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " listSubscriptionsAsText");
+      } 
+   }
+   
+   
+
+   /**
+    * Returns a human readable list containing the names of current subscriptions.
+    * @param durable If true, return durable subscription list.
+    *                If false, return non-durable subscription list.
+    * @return String of subscription list. Never null.
+    */
+   public String listSubscriptionsAsText(boolean durable) throws Exception
+   {
+      try
+      {
+         if (!started)
+         {
+            log.warn("Topic is stopped.");
+            return "";
+         }
+   
+         return ((ManagedTopic)destination).listSubscriptionsAsText(durable);
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " listSubscriptionsAsText");
+      } 
+   }
+
+   /**
+    * XXX Placeholder
+    * Get durable/non-durable subscription list.
+    * @param durable If true, return durable subscription list.
+    *                If false, return non-durable subscription list.
+    * @return List of CoreDurableSubscription/CoreSubscription. Never null.
+    * @throws JMSException
+    * @see ManageableTopic#getSubscriptions(boolean)
+    */
+   /*
+   public List listSubscriptions(boolean durable) throws JMSException
+   {
+      JBossTopic jbt = new JBossTopic(name);
+      ManageableTopic t = (ManageableTopic)cm.getCoreDestination(jbt);
+      return t.getSubscriptions(durable);
+   }
+   */
+   
+   /**
+    * XXX Placeholder
+    * Get messages from certain subscription.
+    * @param channelID @see #listSubscriptions()
+    * @param clientID @see #listSubscriptions()
+    * @param subName @see #listSubscriptions()
+    * @param selector Filter expression
+    * @return list of javax.jms.Message
+    * @throws JMSException
+    * @see ManageableTopic#getMessages(long, String, String, String)
+    */
+   /*
+   public List listMessages(long channelID, String clientID, String subName, String selector)
+      throws JMSException
+   {
+      JBossTopic jbt = new JBossTopic(name);
+      ManageableTopic t = (ManageableTopic)cm.getCoreDestination(jbt);
+      return t.getMessages(channelID, clientID, subName, trimSelector(selector));
+   }
+   */
+   
+   /**
+    * Get messages from a durable subscription.
+    * @param subName Subscription name.
+    * @param clientID Client ID.
+    * @param selector Filter expression.
+    * @return list of javax.jms.Message
+    * @throws JMSException
+    * @see ManageableTopic#getMessagesFromDurableSub(String, String, String)
+    */
+   public List listMessagesDurableSub(String subName, String clientID, String selector)
+      throws Exception
+   {
+      try
+      {
+         if (!started)
+         {
+            log.warn("Topic is stopped.");
+            return new ArrayList();
+         }
+   
+         return ((ManagedTopic)destination).listMessagesDurableSub(subName, clientID, selector);
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " listMessagesDurableSub");
+      } 
+   }
+   
+   /**
+    * Get messages from a non-durable subscription.
+    * @param channelID
+    * @param selector Filter expression.
+    * @return list of javax.jms.Message
+    * @throws JMSException
+    * @see ManageableTopic#getMessagesFromNonDurableSub(Long, String)
+    */
+   public List listMessagesNonDurableSub(long channelID, String selector)
+      throws Exception
+   {
+      try
+      {
+         if (!started)
+         {
+            log.warn("Topic is stopped.");
+            return new ArrayList();
+         }
+         
+         return ((ManagedTopic)destination).listMessagesNonDurableSub(channelID, selector);
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " listMessagesNonDurableSub");
+      } 
+   }
+
+   
+   // TODO implement these:
+
+//   int getAllMessageCount();
+//
+//   int getDurableMessageCount();
+//
+//   int getNonDurableMessageCount();
+//
+//   int getAllSubscriptionsCount();
+//
+//   int getDurableSubscriptionsCount();
+//
+//   int getNonDurableSubscriptionsCount();
+//
+//   java.util.List listAllSubscriptions();
+//
+//   java.util.List listDurableSubscriptions();
+//
+//   java.util.List listNonDurableSubscriptions();
+//
+//   java.util.List listMessages(java.lang.String id) throws java.lang.Exception;
+//
+//   java.util.List listMessages(java.lang.String id, java.lang.String selector) throws java.lang.Exception;
+//
+//   List listNonDurableMessages(String id, String sub) throws Exception;
+//
+//   List listNonDurableMessages(String id, String sub, String selector) throws Exception;
+//
+//   List listDurableMessages(String id, String name) throws Exception;
+//
+//   List listDurableMessages(String id, String name, String selector) throws Exception;
+
+   // Public --------------------------------------------------------
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   protected boolean isQueue()
+   {
+      return false;
+   }
+   
+ 
+   /**
+    * XXX Placeholder
+    * @see ManageableTopic#getSubscriptions()
+    */
+   /*
+   public List getSubscriptions()
+   {
+      ArrayList list = new ArrayList();
+      Iterator iter = iterator();
+      while (iter.hasNext())
+      {
+         CoreSubscription sub = (CoreSubscription)iter.next();
+         if (sub instanceof CoreDurableSubscription)
+            list.add(new String[]{ 
+                        Long.toString(sub.getChannelID()), 
+                        ((CoreDurableSubscription)sub).getClientID(),
+                        ((CoreDurableSubscription)sub).getName()});
+         else
+            list.add(new String[]{ 
+                  Long.toString(sub.getChannelID()), "", ""});
+      }
+      return list;
+   }
+   */
+   
+   
+   /**
+    * XXX Placeholder
+    * @see ManageableTopic#getSubscriptions(boolean)
+    */
+   /*
+   public List getSubscriptions(boolean durable)
+   {
+      ArrayList list = new ArrayList();
+      Iterator iter = iterator();
+      while (iter.hasNext())
+      {
+         CoreSubscription sub = (CoreSubscription)iter.next();
+         if (sub instanceof CoreDurableSubscription && durable)
+            list.add(new String[]{ 
+                        Long.toString(sub.getChannelID()), 
+                        ((CoreDurableSubscription)sub).getClientID(),
+                        ((CoreDurableSubscription)sub).getName()});
+         else if (!(sub instanceof CoreDurableSubscription) && !durable)
+            list.add(new String[]{ 
+                  Long.toString(sub.getChannelID()), "", ""});
+      }
+      return list;
+   }
+   */   
+   
+   /**
+    * XXX Placeholder
+    * @see ManageableTopic#getMessages(long, String, String, String)
+    */
+   /*
+   public List getMessages(long channelID, String clientID, String subName, String selector) throws InvalidSelectorException
+   {
+      Iterator iter = iterator();
+      while (iter.hasNext())
+      {
+         CoreSubscription sub = (CoreSubscription)iter.next();
+         // If subID matches, then get message list from the subscription
+         if (matchSubscription(channelID, clientID, subName, sub))
+            return sub.browse(null == selector ? null : new Selector(selector));
+      }   
+      // No match, return an empty list
+      return new ArrayList();
+   }
+   */
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+}

Modified: trunk/src/main/org/jboss/jms/server/endpoint/ServerBrowserEndpoint.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/endpoint/ServerBrowserEndpoint.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/endpoint/ServerBrowserEndpoint.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -33,7 +33,7 @@
 import org.jboss.logging.Logger;
 import org.jboss.messaging.core.Filter;
 import org.jboss.messaging.core.Routable;
-import org.jboss.messaging.core.local.MessageQueue;
+import org.jboss.messaging.core.local.Queue;
 
 /**
  * Concrete implementation of BrowserEndpoint.
@@ -66,7 +66,7 @@
    // Constructors --------------------------------------------------
 
    protected ServerBrowserEndpoint(ServerSessionEndpoint session, int id,
-                                   MessageQueue destination, String messageSelector)
+                                   Queue destination, String messageSelector)
       throws JMSException
    {     
       this.session = session;

Modified: trunk/src/main/org/jboss/jms/server/endpoint/ServerConnectionEndpoint.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/endpoint/ServerConnectionEndpoint.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/endpoint/ServerConnectionEndpoint.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -52,8 +52,8 @@
 import org.jboss.jms.util.ToString;
 import org.jboss.logging.Logger;
 import org.jboss.messaging.core.MessageReference;
-import org.jboss.messaging.core.plugin.contract.Exchange;
 import org.jboss.messaging.core.plugin.contract.MessageStore;
+import org.jboss.messaging.core.plugin.contract.PostOffice;
 import org.jboss.messaging.core.tx.Transaction;
 import org.jboss.messaging.core.tx.TransactionRepository;
 import org.jboss.messaging.util.ConcurrentReaderHashSet;
@@ -108,9 +108,9 @@
    private ServerPeer serverPeer;
 
    // access to server's extensions
-   private Exchange directExchange;
+   private PostOffice queuePostOffice;
    
-   private Exchange topicExchange;
+   private PostOffice topicPostOffice;
    
    private SecurityManager sm;
    
@@ -138,7 +138,7 @@
                                       String username, String password, int prefetchSize,
                                       int defaultTempQueueFullSize,
                                       int defaultTempQueuePageSize,
-                                      int defaultTempQueueDownCacheSize)
+                                      int defaultTempQueueDownCacheSize) throws Exception
    {
       this.serverPeer = serverPeer;
       
@@ -146,9 +146,9 @@
       tr = serverPeer.getTxRepository();
       cm = serverPeer.getConnectionManager();
       ms = serverPeer.getMessageStore();
-      directExchange = serverPeer.getDirectExchangeDelegate();
-      topicExchange = serverPeer.getTopicExchangeDelegate();
-
+      queuePostOffice = serverPeer.getQueuePostOfficeInstance();
+      topicPostOffice = serverPeer.getTopicPostOfficeInstance();
+      
       started = false;
 
       this.connectionID = serverPeer.getNextObjectID();
@@ -308,17 +308,8 @@
             JBossDestination dest = (JBossDestination)i.next();
 
             if (dest.isQueue())
-            {
-//               //Unbind
-//               Binding binding = directExchange.unbind(dest.getName());
-//               
-//               //Remove all data for queue - even though it is a temporary queue it may have data in the
-//               //db since it might have gone into paging
-//               
-//               binding.getQueue().removeAllReferences();
-               
-               directExchange.unbindQueue(dest.getName());
-               
+            {     
+               queuePostOffice.unbindQueue(dest.getName());               
             }
             else
             {
@@ -650,7 +641,7 @@
    {
       JBossDestination dest = (JBossDestination)msg.getJMSDestination();
       
-      //We must reference the message *before* we send it the destination to be handled. This is
+      // We must reference the message *before* we send it the destination to be handled. This is
       // so we can guarantee that the message doesn't disappear from the store before the
       // handling is complete. Each channel then takes copies of the reference if they decide to
       // maintain it internally
@@ -663,14 +654,14 @@
          
          if (dest.isQueue())
          {
-            if (!directExchange.route(ref, dest.getName(), tx))
+            if (!queuePostOffice.route(ref, dest.getName(), tx))
             {
                throw new JMSException("Failed to route message");
             }
          }
          else
-         {                                
-            topicExchange.route(ref, dest.getName(), tx);           
+         {
+            topicPostOffice.route(ref, dest.getName(), tx);   
          }
       }
       finally

Modified: trunk/src/main/org/jboss/jms/server/endpoint/ServerConnectionFactoryEndpoint.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/endpoint/ServerConnectionFactoryEndpoint.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/endpoint/ServerConnectionFactoryEndpoint.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -111,7 +111,7 @@
             
             
             String preconfClientID =
-               serverPeer.getJMSUserManagerDelegate().getPreConfiguredClientID(username);
+               serverPeer.getJmsUserManagerInstance().getPreConfiguredClientID(username);
             
             if (preconfClientID != null)
             {

Modified: trunk/src/main/org/jboss/jms/server/endpoint/ServerConsumerEndpoint.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/endpoint/ServerConsumerEndpoint.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/endpoint/ServerConsumerEndpoint.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -49,9 +49,9 @@
 import org.jboss.messaging.core.Receiver;
 import org.jboss.messaging.core.Routable;
 import org.jboss.messaging.core.SimpleDelivery;
-import org.jboss.messaging.core.local.MessageQueue;
-import org.jboss.messaging.core.plugin.contract.Exchange;
-import org.jboss.messaging.core.plugin.exchange.Binding;
+import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.plugin.contract.Binding;
+import org.jboss.messaging.core.plugin.contract.PostOffice;
 import org.jboss.messaging.core.tx.Transaction;
 import org.jboss.messaging.core.tx.TransactionException;
 import org.jboss.messaging.core.tx.TxCallback;
@@ -88,7 +88,7 @@
 
    private int id;
 
-   private MessageQueue messageQueue;
+   private Queue messageQueue;
    
    private String queueName;
 
@@ -127,7 +127,7 @@
    
    // Constructors --------------------------------------------------
 
-   protected ServerConsumerEndpoint(int id, MessageQueue messageQueue, String queueName,
+   protected ServerConsumerEndpoint(int id, Queue messageQueue, String queueName,
                                     ServerSessionEndpoint sessionEndpoint,
                                     String selector, boolean noLocal, JBossDestination dest,
                                     int prefetchSize)
@@ -204,9 +204,9 @@
    /*
     * The queue ensures that handle is never called concurrently by more than one thread.
     */
-   public Delivery handle(DeliveryObserver observer, Routable reference, Transaction tx)
+   public Delivery handle(DeliveryObserver observer, MessageReference ref, Transaction tx)
    {
-      if (trace) { log.trace(this + " receives " + reference + " for delivery"); }
+      if (trace) { log.trace(this + " receives " + ref + " for delivery"); }
       
       // This is ok to have outside lock - is volatile
       if (bufferFull)
@@ -231,9 +231,7 @@
             log.debug(this + " NOT started yet!");
             return null;
          }
-            
-         MessageReference ref = (MessageReference)reference;
-                     
+                        
          JBossMessage message = (JBossMessage)ref.getMessage();
          
          boolean selectorRejected = !this.accept(message);
@@ -359,10 +357,10 @@
             
             if (destination.isTopic())
             {
-               Exchange topicExchange = 
-                  sessionEndpoint.getConnectionEndpoint().getServerPeer().getTopicExchangeDelegate();
+               PostOffice topicExchange = 
+                  sessionEndpoint.getConnectionEndpoint().getServerPeer().getTopicPostOfficeInstance();
                
-               Binding binding = topicExchange.getBindingForName(queueName);
+               Binding binding = topicExchange.getBindingForQueueName(queueName);
                
                if (binding == null)
                {

Modified: trunk/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -38,12 +38,15 @@
 import org.jboss.jms.delegate.ConsumerDelegate;
 import org.jboss.jms.destination.JBossDestination;
 import org.jboss.jms.destination.JBossQueue;
-import org.jboss.jms.destination.JBossTemporaryTopic;
 import org.jboss.jms.destination.JBossTopic;
 import org.jboss.jms.message.JBossMessage;
 import org.jboss.jms.selector.Selector;
 import org.jboss.jms.server.DestinationManager;
+import org.jboss.jms.server.QueuedExecutorPool;
 import org.jboss.jms.server.ServerPeer;
+import org.jboss.jms.server.destination.ManagedDestination;
+import org.jboss.jms.server.destination.ManagedQueue;
+import org.jboss.jms.server.destination.ManagedTopic;
 import org.jboss.jms.server.endpoint.advised.BrowserAdvised;
 import org.jboss.jms.server.endpoint.advised.ConsumerAdvised;
 import org.jboss.jms.server.remoting.JMSDispatcher;
@@ -51,12 +54,16 @@
 import org.jboss.jms.util.ExceptionUtil;
 import org.jboss.jms.util.MessageQueueNameHelper;
 import org.jboss.logging.Logger;
-import org.jboss.messaging.core.plugin.contract.Exchange;
+import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.plugin.IdManager;
+import org.jboss.messaging.core.plugin.contract.Binding;
 import org.jboss.messaging.core.plugin.contract.MessageStore;
 import org.jboss.messaging.core.plugin.contract.PersistenceManager;
-import org.jboss.messaging.core.plugin.exchange.Binding;
+import org.jboss.messaging.core.plugin.contract.PostOffice;
 import org.jboss.util.id.GUID;
 
+import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
+
 /**
  * Concrete implementation of SessionEndpoint.
  * 
@@ -90,13 +97,16 @@
    private PersistenceManager pm;
    private MessageStore ms;
    private DestinationManager dm;
-   private Exchange topicExchange;
-   private Exchange directExchange;
+   private IdManager idm;
+   private QueuedExecutorPool pool;
+   private PostOffice topicPostOffice;
+   private PostOffice queuePostOffice;
    
    
    // Constructors --------------------------------------------------
 
    protected ServerSessionEndpoint(int sessionID, ServerConnectionEndpoint connectionEndpoint)
+      throws Exception
    {
       this.sessionID = sessionID;
       
@@ -104,11 +114,13 @@
 
       ServerPeer sp = connectionEndpoint.getServerPeer();
 
-      pm = sp.getPersistenceManagerDelegate();
+      pm = sp.getPersistenceManagerInstance();
       ms = sp.getMessageStore();
       dm = sp.getDestinationManager();
-      topicExchange = sp.getTopicExchangeDelegate();
-      directExchange = sp.getDirectExchangeDelegate();
+      topicPostOffice = sp.getTopicPostOfficeInstance();
+      queuePostOffice = sp.getQueuePostOfficeInstance();
+      idm = sp.getChannelIdManager();
+      pool = sp.getQueuedExecutorPool();
 
       consumers = new HashMap();
 		browsers = new HashMap();  
@@ -136,16 +148,13 @@
          
          log.debug("creating consumer for " + jmsDestination + ", selector " + selectorString + ", " + (noLocal ? "noLocal, " : "") + "subscription " + subscriptionName);
    
-         //"Refresh" the destination - this will populate it with it's paging values
-         //TODO There's probably a better way of doing this
+         ManagedDestination mDest = dm.getDestination(jmsDestination.getName(), jmsDestination.isQueue());
          
-         if (!dm.destinationExists(jmsDestination))
+         if (jmsDestination == null)
          {
             throw new InvalidDestinationException("No such destination: " + jmsDestination);
-         } 
+         }
          
-         jmsDestination = dm.getDestination(jmsDestination);
-         
          if (jmsDestination.isTemporary())
          {
             // Can only create a consumer for a temporary destination on the same connection
@@ -176,13 +185,17 @@
                // non-durable subscription
                if (log.isTraceEnabled()) { log.trace("creating new non-durable subscription on " + jmsDestination); }
                      
-               binding = topicExchange.bindQueue(new GUID().toString(), jmsDestination.getName(),
-                                                 selector, noLocal,
-                                                 false, ms, pm,
-                                                 jmsDestination.getFullSize(),
-                                                 jmsDestination.getPageSize(),
-                                                 jmsDestination.getDownCacheSize());
+               //Create the sub
+               QueuedExecutor executor = (QueuedExecutor)pool.get();
+               Queue q = 
+                  new Queue(idm.getId(), ms, pm, true, false,
+                           mDest.getFullSize(),
+                           mDest.getPageSize(),
+                           mDest.getDownCacheSize(),
+                           executor, selector);
                
+               //Make a binding for this queue
+               binding = topicPostOffice.bindQueue(new GUID().toString(), jmsDestination.getName(), false, q);               
             }
             else
             {
@@ -202,7 +215,7 @@
                
                String name = MessageQueueNameHelper.createSubscriptionName(clientID, subscriptionName);
                
-               binding = topicExchange.getBindingForName(name);
+               binding = topicPostOffice.getBindingForQueueName(name);
                   
                if (binding == null)
                {
@@ -210,14 +223,16 @@
                   
                   if (trace) { log.trace("creating new durable subscription on " + jmsDestination); }
                   
-                  //Create a new binding for the durable subscription
-
-                  binding = topicExchange.bindQueue(name, jmsDestination.getName(),
-                                                  selector, noLocal,
-                                                  true, ms, pm,
-                                                  jmsDestination.getFullSize(),
-                                                  jmsDestination.getPageSize(),
-                                                  jmsDestination.getDownCacheSize());
+                  QueuedExecutor executor = (QueuedExecutor)pool.get();
+                  Queue q = 
+                     new Queue(idm.getId(), ms, pm, true, true,
+                              mDest.getFullSize(),
+                              mDest.getPageSize(),
+                              mDest.getDownCacheSize(),
+                              executor, selector);
+                  
+                  //Make a binding for this queue
+                  binding = topicPostOffice.bindQueue(name, jmsDestination.getName(), false, q);               
                }
                else
                {
@@ -251,16 +266,20 @@
    
                      // Unbind the durable subscription
                      
-                     topicExchange.unbindQueue(name);
+                     topicPostOffice.unbindQueue(name);
    
                      // create a fresh new subscription
                      
-                     binding = topicExchange.bindQueue(name, jmsDestination.getName(),
-                                                     selector, noLocal,
-                                                     true, ms, pm,
-                                                     jmsDestination.getFullSize(),
-                                                     jmsDestination.getPageSize(),
-                                                     jmsDestination.getDownCacheSize());
+                     QueuedExecutor executor = (QueuedExecutor)pool.get();
+                     Queue q = 
+                        new Queue(idm.getId(), ms, pm, true, true,
+                                 mDest.getFullSize(),
+                                 mDest.getPageSize(),
+                                 mDest.getDownCacheSize(),
+                                 executor, selector);
+                     
+                     //Make a binding for this queue
+                     binding = topicPostOffice.bindQueue(name, jmsDestination.getName(), false, q);  
                   }               
                }
             }
@@ -270,7 +289,7 @@
             //Consumer on a jms queue
             
             //Let's find the binding
-            binding = directExchange.getBindingForName(jmsDestination.getName());
+            binding = queuePostOffice.getBindingForQueueName(jmsDestination.getName());
             
             if (binding == null)
             {
@@ -322,12 +341,12 @@
             throw new IllegalStateException("Cannot browse a topic");
          }
    	   
-         if (!dm.destinationExists(jmsDestination))
+         if (dm.getDestination(jmsDestination.getName(), jmsDestination.isQueue()) == null)
          {
             throw new InvalidDestinationException("No such destination: " + jmsDestination);
          }
          
-         Binding binding = directExchange.getBindingForName(jmsDestination.getName());
+         Binding binding = queuePostOffice.getBindingForQueueName(jmsDestination.getName());
          
    	   int browserID = connectionEndpoint.getServerPeer().getNextObjectID();
    	   
@@ -359,12 +378,14 @@
             throw new IllegalStateException("Session is closed");
          }
          
-         if (!dm.destinationExists(new JBossQueue(name)))
+         ManagedDestination dest = (ManagedDestination)dm.getDestination(name, true);
+         
+         if (dest == null)
          {
             throw new JMSException("There is no administratively defined queue with name:" + name);
          }        
    
-         return new JBossQueue(name);
+         return new JBossQueue(dest.getName());
       }
       catch (Throwable t)
       {
@@ -381,10 +402,12 @@
             throw new IllegalStateException("Session is closed");
          }
          
-         if (!dm.destinationExists(new JBossTopic(name)))
+         ManagedDestination dest = (ManagedDestination)dm.getDestination(name, false);
+                  
+         if (dest == null)
          {
             throw new JMSException("There is no administratively defined topic with name:" + name);
-         } 
+         }        
    
          return new JBossTopic(name);
       }
@@ -529,27 +552,32 @@
          
          //Register with the destination manager
          
+         ManagedDestination mDest;
+         
+         int fullSize = connectionEndpoint.getDefaultTempQueueFullSize();
+         int pageSize = connectionEndpoint.getDefaultTempQueuePageSize();
+         int downCacheSize = connectionEndpoint.getDefaultTempQueueDownCacheSize();
+         
          if (dest.isTopic())
          {
-            //TODO - we should find a better way of maintaining the paging params
-            dest = new JBossTemporaryTopic(dest.getName(),
-                     connectionEndpoint.getDefaultTempQueueFullSize(),
-                     connectionEndpoint.getDefaultTempQueuePageSize(),
-                     connectionEndpoint.getDefaultTempQueueDownCacheSize());
+            mDest = new ManagedTopic(dest.getName(), fullSize, pageSize, downCacheSize);
          }
+         else
+         {
+            mDest = new ManagedQueue(dest.getName(), fullSize, pageSize, downCacheSize);
+         }
          
-         dm.registerDestination(dest, null, null);
+         dm.registerDestination(mDest);
          
          if (dest.isQueue())
          {
-            //Create a new binding
-
-            directExchange.bindQueue(dest.getName(), dest.getName(),
-                                     null, false,
-                                     false, ms, pm,
-                                     connectionEndpoint.getDefaultTempQueueFullSize(),
-                                     connectionEndpoint.getDefaultTempQueuePageSize(),
-                                     connectionEndpoint.getDefaultTempQueueDownCacheSize());        
+            QueuedExecutor executor = (QueuedExecutor)pool.get();
+            Queue q = 
+               new Queue(idm.getId(), ms, pm, true, true, fullSize, pageSize, downCacheSize,
+                         executor, null);
+            
+            //Make a binding for this queue
+            queuePostOffice.bindQueue(dest.getName(), dest.getName(), false, q);  
          }         
       }
       catch (Throwable t)
@@ -572,21 +600,23 @@
             throw new InvalidDestinationException("Destination:" + dest + " is not a temporary destination");
          }
          
-         if (!dm.destinationExists(dest))
+         ManagedDestination mDest = dm.getDestination(dest.getName(), dest.isQueue());
+         
+         if (mDest == null)
          {
-            throw new InvalidDestinationException("Destination:" + dest + " does not exist");      
+            throw new InvalidDestinationException("No such destination: " + dest);
          }
                   
          if (dest.isQueue())
          {
             //Unbind
-            directExchange.unbindQueue(dest.getName());
+            queuePostOffice.unbindQueue(dest.getName());
          }
          else
          {
             //Topic
             
-            List bindings = topicExchange.listBindingsForWildcard(dest.getName());
+            List bindings = topicPostOffice.listBindingsForCondition(dest.getName());
             
             if (!bindings.isEmpty())
             {
@@ -594,7 +624,7 @@
             }
          }
          
-         dm.unregisterDestination(dest);         
+         dm.unregisterDestination(mDest);         
             
          connectionEndpoint.removeTemporaryDestination(dest);
       }
@@ -626,7 +656,7 @@
          
          String queueName = MessageQueueNameHelper.createSubscriptionName(clientID, subscriptionName);
          
-         Binding binding = topicExchange.getBindingForName(queueName);
+         Binding binding = topicPostOffice.getBindingForQueueName(queueName);
          
          if (binding == null)
          {
@@ -636,7 +666,7 @@
          
          //Unbind it
   
-         topicExchange.unbindQueue(queueName);
+         topicPostOffice.unbindQueue(queueName);
       }
       catch (Throwable t)
       {

Modified: trunk/src/main/org/jboss/jms/server/plugin/JDBCJMSUserManager.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/plugin/JDBCJMSUserManager.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/plugin/JDBCJMSUserManager.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -30,10 +30,14 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Properties;
 
+import javax.sql.DataSource;
+import javax.transaction.TransactionManager;
+
 import org.jboss.jms.server.plugin.contract.JMSUserManager;
 import org.jboss.logging.Logger;
-import org.jboss.messaging.core.plugin.JDBCServiceSupport;
+import org.jboss.messaging.core.plugin.JDBCSupport;
 
 /**
  * A JDBCJMSUserManager
@@ -47,11 +51,19 @@
  * $Id$
  *
  */
-public class JDBCJMSUserManager extends JDBCServiceSupport implements JMSUserManager
+public class JDBCJMSUserManager extends JDBCSupport implements JMSUserManager
 {
    private static final Logger log = Logger.getLogger(JDBCJMSUserManager.class);
+   
+   // Constructors ----------------------------------------------------
+   
+   public JDBCJMSUserManager(DataSource ds, TransactionManager tm, Properties sqlProperties,
+                             boolean createTablesOnStartup)
+   {
+      super(ds, tm, sqlProperties, createTablesOnStartup);
+   }
       
-   // PersistentServiceSupport overrides ----------------------------
+   // JDBCSupport overrides ----------------------------
    
    protected Map getDefaultDMLStatements()
    {                
@@ -72,23 +84,22 @@
       return map;
    }
    
-   // ServiceMBeanSupport overrides ---------------------------------
+   // MessagingComponent overrides ---------------------------------
    
-   protected void startService() throws Exception
+   public void start() throws Exception
    {
-      super.startService();
+      super.start();
       
       insertUserRoleData();
    }
+   
+   public void stop() throws Exception
+   {
+      super.stop();
+   }
 
-   // MBean operations ----------------------------------------------
-   
-   // MBean attributes --------------------------------------------------------
-   
    // JMSUserManager implementation -------------------------------------
 
-   //TODO There is no reason why this class should implement ClientIDRetriever
-   //the implementation should be moved out into a completely different service
    public String getPreConfiguredClientID(String username) throws Exception
    {
       Connection conn = null;
@@ -138,6 +149,8 @@
       }     
    }
    
+   // Private ----------------------------------------------------------------------
+   
    private void insertUserRoleData() throws Exception
    {
       List populateTables = new ArrayList();

Added: trunk/src/main/org/jboss/jms/server/plugin/JDBCJMSUserManagerService.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/plugin/JDBCJMSUserManagerService.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/plugin/JDBCJMSUserManagerService.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,108 @@
+/*
+ * 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.jms.server.plugin;
+
+import javax.transaction.TransactionManager;
+
+import org.jboss.jms.server.plugin.contract.JMSUserManager;
+import org.jboss.jms.util.ExceptionUtil;
+import org.jboss.messaging.core.plugin.JDBCServiceSupport;
+import org.jboss.messaging.core.plugin.contract.MessagingComponent;
+
+/**
+ * A JDBCJMSUserManagerService
+ * 
+ * MBean wrapper for a JMSUserManager
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class JDBCJMSUserManagerService extends JDBCServiceSupport
+{
+   private JMSUserManager userManager;
+   
+   private boolean started;
+   
+   // Constructors -----------------------------------------------------
+   
+   public JDBCJMSUserManagerService()
+   {      
+   }
+   
+   // ServerPlugin implementation ------------------------------------------
+   
+   public MessagingComponent getInstance()
+   {
+      return userManager;
+   }
+   
+   // ServiceMBeanSupport overrides ---------------------------------
+   
+   protected synchronized void startService() throws Exception
+   {
+      if (started)
+      {
+         throw new IllegalStateException("Service is already started");
+      }
+      
+      super.startService();
+      
+      try
+      {  
+         TransactionManager tm = getTransactionManagerReference();
+         
+         userManager = new JDBCJMSUserManager(ds, tm, sqlProperties, createTablesOnStartup);
+         
+         userManager.start();
+         
+         started = true;         
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " startService");
+      } 
+   }
+   
+   protected void stopService() throws Exception
+   {
+      if (!started)
+      {
+         throw new IllegalStateException("Service is not started");
+      }
+      
+      super.stopService();
+      
+      try
+      {      
+         userManager.stop();
+         
+         started = false;
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " startService");
+      } 
+   }
+}

Modified: trunk/src/main/org/jboss/jms/server/plugin/contract/JMSUserManager.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/plugin/contract/JMSUserManager.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/jms/server/plugin/contract/JMSUserManager.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -21,17 +21,18 @@
  */
 package org.jboss.jms.server.plugin.contract;
 
+import org.jboss.messaging.core.plugin.contract.MessagingComponent;
 
 /**
  * A JMSUserManager
-
+ *
  * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
  * @version <tt>$Revision: 1.1 $</tt>
  *
  * $Id$
  *
  */
-public interface JMSUserManager
+public interface JMSUserManager extends MessagingComponent
 {
    String getPreConfiguredClientID(String username) throws Exception;
 }

Modified: trunk/src/main/org/jboss/messaging/core/Channel.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/Channel.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/Channel.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -44,7 +44,7 @@
  *
  * $Id$
  */
-public interface Channel extends DeliveryObserver, Receiver, Distributor
+public interface Channel extends DeliveryObserver, Distributor, Receiver
 {
 
    /**    

Modified: trunk/src/main/org/jboss/messaging/core/ChannelSupport.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/ChannelSupport.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/ChannelSupport.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -140,7 +140,7 @@
 
    // Receiver implementation ---------------------------------------
 
-   public Delivery handle(DeliveryObserver sender, Routable r, Transaction tx)
+   public Delivery handle(DeliveryObserver sender, MessageReference ref, Transaction tx)
    {
       checkClosed();
       
@@ -154,7 +154,7 @@
             // Since remoting doesn't currently handle non blocking IO, we still have to wait for the
             // result, but when remoting does, we can use a full SEDA approach and get even better
             // throughput.
-            this.executor.execute(new HandleRunnable(result, sender, r, true));
+            this.executor.execute(new HandleRunnable(result, sender, ref, true));
          }
          catch (InterruptedException e)
          {
@@ -165,11 +165,11 @@
       }
       else
       {
-         return handleInternal(sender, r, tx, true);
+         return handleInternal(sender, ref, tx, true);
       }
    }
    
-   public Delivery handleDontPersist(DeliveryObserver sender, Routable r, Transaction tx)
+   public Delivery handleDontPersist(DeliveryObserver sender, MessageReference ref, Transaction tx)
    {
       checkClosed();
       
@@ -183,7 +183,7 @@
             // Since remoting doesn't currently handle non blocking IO, we still have to wait for the
             // result, but when remoting does, we can use a full SEDA approach and get even better
             // throughput.
-            this.executor.execute(new HandleRunnable(result, sender, r, false));
+            this.executor.execute(new HandleRunnable(result, sender, ref, false));
          }
          catch (InterruptedException e)
          {
@@ -194,7 +194,7 @@
       }
       else
       {
-         return handleInternal(sender, r, tx, false);
+         return handleInternal(sender, ref, tx, false);
       }
    }
       
@@ -671,16 +671,18 @@
       }
    }
 
-   protected Delivery handleInternal(DeliveryObserver sender, Routable r, Transaction tx, boolean persist)
+   protected Delivery handleInternal(DeliveryObserver sender, MessageReference ref,
+                                     Transaction tx, boolean persist)
    {
-      if (r == null)
+      if (ref == null)
       {
          return null;
       }
 
-      if (trace) { log.trace(this + " handles " + r + (tx == null ? " non-transactionally" : " in transaction: " + tx)); }
+      if (trace) { log.trace(this + " handles " + ref + (tx == null ? " non-transactionally" : " in transaction: " + tx)); }
  
-      MessageReference ref = obtainReference(r);
+      //Each channel has its own copy of the reference
+      ref = ref.copy();
 
       try
       {
@@ -705,9 +707,9 @@
             // delivery of a reliable
             // message, which in these conditions cannot be done.
 
-            if (r.isReliable() && !acceptReliableMessages)
+            if (ref.isReliable() && !acceptReliableMessages)
             {
-               log.error("Cannot handle reliable message " + r
+               log.error("Cannot handle reliable message " + ref
                         + " because the channel has a non-recoverable state!");
                return null;
             }
@@ -739,11 +741,9 @@
                // this transaction has no chance to succeed, since a reliable
                // message cannot be
                // safely stored by a non-recoverable state, so doom the
-               // transaction
-               if (trace)
-               {
-                  log.trace(this + " cannot handle reliable messages, dooming the transaction");
-               }
+               // transaction               
+               log.warn(this + " cannot handle reliable messages, dooming the transaction");
+               
                tx.setRollbackOnly();
             } 
             else
@@ -805,40 +805,8 @@
       if (trace) { log.trace(this + " removed " + d + " from memory:" + removed); }
       
       return removed;
-   }
-   
-   protected MessageReference obtainReference(Routable r)
-   {
-      MessageReference ref = null;
+   }     
 
-      // Convert to reference
-      try
-      {
-         if (!r.isReference())
-         {
-            // We should only handle references in core.
-            // TODO enforce this in the signature of handle method
-            // See http://jira.jboss.com/jira/browse/JBMESSAGING-255
-            log.warn("Should only handle references");
-            // Remove this when this is enforced
-            ref = ms.reference((Message) r);
-         }
-         else
-         {
-            // Each channel has its own copy of the reference
-            ref = ((MessageReference) r).copy();
-         }
-
-         return ref;
-      }
-      catch (Exception e)
-      {
-         log.error("Failed to reference routable", e);
-         // FIXME - Swallowing exceptions
-         return null;
-      }
-   }
-
    protected InMemoryCallback getCallback(Transaction tx)
    {
       InMemoryCallback callback = (InMemoryCallback) tx.getCallback(this);
@@ -1108,21 +1076,21 @@
 
       DeliveryObserver sender;
 
-      Routable routable;
+      MessageReference ref;
       
       boolean persist;
 
-      HandleRunnable(Future result, DeliveryObserver sender, Routable routable, boolean persist)
+      HandleRunnable(Future result, DeliveryObserver sender, MessageReference ref, boolean persist)
       {
          this.result = result;
          this.sender = sender;
-         this.routable = routable;
+         this.ref = ref;
          this.persist = persist;
       }
 
       public void run()
       {
-         Delivery d = handleInternal(sender, routable, null, persist);
+         Delivery d = handleInternal(sender, ref, null, persist);
          result.setResult(d);
       }
    }   

Modified: trunk/src/main/org/jboss/messaging/core/Distributor.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/Distributor.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/Distributor.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -25,10 +25,12 @@
 
 /**
  * An interface for Receiver management.
- *
+ * 
+ * Distributes a reference to a maximum of one of the attached receivers
+ * 
  * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
- * @version <tt>$Revision$</tt>
- *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * 
  * $Id$
  */
 public interface Distributor

Modified: trunk/src/main/org/jboss/messaging/core/Filter.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/Filter.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/Filter.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -21,23 +21,17 @@
   */
 package org.jboss.messaging.core;
 
-import java.io.Serializable;
-
-
 /**
  * A filter encapsulates the logic of whether to accept a message or not. Filters are used when
  * browsing to restrict the messages browsed, or when routing messages.
  *
- * A filter must be serializable because it can be sent between two address spaces as argument
- * of a distributed RPC.
- *
  * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
  * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
  * @version <tt>$Revision$</tt>
  *
  * $Id$
  */
-public interface Filter extends Serializable
+public interface Filter
 {
 	/**
 	 * Tests whether the routable should be accepted.

Modified: trunk/src/main/org/jboss/messaging/core/MessageReference.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/MessageReference.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/MessageReference.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -21,7 +21,6 @@
   */
 package org.jboss.messaging.core;
 
-
 /**
  * A "lightweight" message representative.
  *

Modified: trunk/src/main/org/jboss/messaging/core/Receiver.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/Receiver.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/Receiver.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -46,6 +46,6 @@
     * @see org.jboss.messaging.core.Delivery
     * @see org.jboss.messaging.core.DeliveryObserver
     */
-   Delivery handle(DeliveryObserver observer, Routable routable, Transaction tx);
+   Delivery handle(DeliveryObserver observer, MessageReference reference, Transaction tx);
      
 }

Modified: trunk/src/main/org/jboss/messaging/core/Router.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/Router.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/Router.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -21,7 +21,6 @@
   */
 package org.jboss.messaging.core;
 
-import org.jboss.messaging.core.tx.Transaction;
 
 /**
  * 
@@ -33,7 +32,6 @@
  * 
  * $Id$
  */
-public interface Router extends Distributor
+public interface Router extends Distributor, Receiver
 {
-   Delivery handle(DeliveryObserver observer, Routable routable, Transaction transaction);
 }

Modified: trunk/src/main/org/jboss/messaging/core/local/FirstReceiverPointToPointRouter.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/local/FirstReceiverPointToPointRouter.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/local/FirstReceiverPointToPointRouter.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -28,8 +28,8 @@
 import org.jboss.logging.Logger;
 import org.jboss.messaging.core.Delivery;
 import org.jboss.messaging.core.DeliveryObserver;
+import org.jboss.messaging.core.MessageReference;
 import org.jboss.messaging.core.Receiver;
-import org.jboss.messaging.core.Routable;
 import org.jboss.messaging.core.Router;
 import org.jboss.messaging.core.SimpleDelivery;
 import org.jboss.messaging.core.tx.Transaction;
@@ -69,7 +69,7 @@
 
    // Router implementation -----------------------------------------
 
-   public Delivery handle(DeliveryObserver observer, Routable routable, Transaction tx)
+   public Delivery handle(DeliveryObserver observer, MessageReference ref, Transaction tx)
    {
       Delivery del = null;
       
@@ -83,9 +83,9 @@
             
             try
             {
-               Delivery d = receiver.handle(observer, routable, tx);
+               Delivery d = receiver.handle(observer, ref, tx);
 
-               if (trace) { log.trace("receiver " + receiver + " handled " + routable + " and returned " + d); }
+               if (trace) { log.trace("receiver " + receiver + " handled " + ref + " and returned " + d); }
      
                if (d != null && !d.isCancelled())
                {

Deleted: trunk/src/main/org/jboss/messaging/core/local/MessageQueue.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/local/MessageQueue.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/local/MessageQueue.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -1,120 +0,0 @@
-/*
-  * 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.messaging.core.local;
-
-import org.jboss.logging.Logger;
-import org.jboss.messaging.core.Delivery;
-import org.jboss.messaging.core.DeliveryObserver;
-import org.jboss.messaging.core.Filter;
-import org.jboss.messaging.core.PagingChannel;
-import org.jboss.messaging.core.Routable;
-import org.jboss.messaging.core.plugin.contract.MessageStore;
-import org.jboss.messaging.core.plugin.contract.PersistenceManager;
-import org.jboss.messaging.core.tx.Transaction;
-
-import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
-
-/**
- * 
- * A MessageQueue
- * 
- * Represents a generic message queue.
- * 
- * Can be used to implement a point to point queue, or a subscription fed from a topic
- *
- * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision$</tt>
- *
- * $Id$
- *
- */
-public class MessageQueue extends PagingChannel
-{
-   // Constants -----------------------------------------------------
-   
-   private static final Logger log;
-   
-   private static final boolean trace;
-   
-   static
-   {
-      log = Logger.getLogger(MessageQueue.class);
-      trace = log.isTraceEnabled();
-   }
-
-   // Static --------------------------------------------------------
-   
-   // Attributes ----------------------------------------------------
-   
-   protected Filter filter;
-   
-   
-   // Constructors --------------------------------------------------
-
-   public MessageQueue(long id, MessageStore ms, PersistenceManager pm,             
-                       boolean acceptReliableMessages, boolean recoverable,
-                       int fullSize, int pageSize, int downCacheSize, QueuedExecutor executor,
-                       Filter filter)
-   {
-      super(id, ms, pm, acceptReliableMessages, recoverable, fullSize, pageSize, downCacheSize, executor);
-      
-      router = new RoundRobinPointToPointRouter();
-      
-      this.filter = filter;
-   }
-    
-   // Channel implementation ----------------------------------------
-   
-   public Delivery handle(DeliveryObserver sender, Routable r, Transaction tx)
-   { 
-      //If the queue has a Filter we do not accept any Message references that do not
-      //match the Filter
-      if (filter != null && !filter.accept(r))
-      {
-         if (trace) { log.trace(this + " not accepting " + r); }
-         return null;
-      }
-      
-      return super.handle(sender, r, tx);
-   }
-
-   // Public --------------------------------------------------------
-
-   public String toString()
-   {
-      return "Queue[" + getChannelID() + "]";
-   }
-   
-   public Filter getFilter()
-   {
-      return filter;
-   }
-
-   // Package protected ---------------------------------------------
-   
-   // Protected -----------------------------------------------------
-   
-   // Private -------------------------------------------------------
-   
-   // Inner classes -------------------------------------------------   
-}

Copied: trunk/src/main/org/jboss/messaging/core/local/Queue.java (from rev 1264, trunk/src/main/org/jboss/messaging/core/local/MessageQueue.java)
===================================================================
--- trunk/src/main/org/jboss/messaging/core/local/MessageQueue.java	2006-09-06 04:04:35 UTC (rev 1264)
+++ trunk/src/main/org/jboss/messaging/core/local/Queue.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,120 @@
+/*
+  * 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.messaging.core.local;
+
+import org.jboss.logging.Logger;
+import org.jboss.messaging.core.Delivery;
+import org.jboss.messaging.core.DeliveryObserver;
+import org.jboss.messaging.core.Filter;
+import org.jboss.messaging.core.MessageReference;
+import org.jboss.messaging.core.PagingChannel;
+import org.jboss.messaging.core.plugin.contract.MessageStore;
+import org.jboss.messaging.core.plugin.contract.PersistenceManager;
+import org.jboss.messaging.core.tx.Transaction;
+
+import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
+
+/**
+ * 
+ * A Queue
+ * 
+ * Represents a generic reference queue.
+ * 
+ * Can be used to implement a point to point queue, or a subscription fed from a topic
+ *
+ * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision$</tt>
+ *
+ * $Id$
+ *
+ */
+public class Queue extends PagingChannel
+{
+   // Constants -----------------------------------------------------
+   
+   private static final Logger log;
+   
+   private static final boolean trace;
+   
+   static
+   {
+      log = Logger.getLogger(Queue.class);
+      trace = log.isTraceEnabled();
+   }
+
+   // Static --------------------------------------------------------
+   
+   // Attributes ----------------------------------------------------
+   
+   protected Filter filter;
+   
+   
+   // Constructors --------------------------------------------------
+
+   public Queue(long id, MessageStore ms, PersistenceManager pm,             
+                boolean acceptReliableMessages, boolean recoverable,
+                int fullSize, int pageSize, int downCacheSize, QueuedExecutor executor,
+                Filter filter)
+   {
+      super(id, ms, pm, acceptReliableMessages, recoverable, fullSize, pageSize, downCacheSize, executor);
+      
+      router = new RoundRobinPointToPointRouter();
+      
+      this.filter = filter;
+   }
+    
+   // Channel implementation ----------------------------------------
+   
+   public Delivery handle(DeliveryObserver sender, MessageReference ref, Transaction tx)
+   { 
+      //If the queue has a Filter we do not accept any Message references that do not
+      //match the Filter
+      if (filter != null && !filter.accept(ref))
+      {
+         if (trace) { log.trace(this + " not accepting " + ref); }
+         return null;
+      }
+      
+      return super.handle(sender, ref, tx);
+   }
+
+   // Public --------------------------------------------------------
+
+   public String toString()
+   {
+      return "Queue[" + getChannelID() + "]";
+   }
+   
+   public Filter getFilter()
+   {
+      return filter;
+   }
+
+   // Package protected ---------------------------------------------
+   
+   // Protected -----------------------------------------------------
+   
+   // Private -------------------------------------------------------
+   
+   // Inner classes -------------------------------------------------   
+}

Modified: trunk/src/main/org/jboss/messaging/core/local/RoundRobinPointToPointRouter.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/local/RoundRobinPointToPointRouter.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/local/RoundRobinPointToPointRouter.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -27,8 +27,8 @@
 import org.jboss.logging.Logger;
 import org.jboss.messaging.core.Delivery;
 import org.jboss.messaging.core.DeliveryObserver;
+import org.jboss.messaging.core.MessageReference;
 import org.jboss.messaging.core.Receiver;
-import org.jboss.messaging.core.Routable;
 import org.jboss.messaging.core.Router;
 import org.jboss.messaging.core.SimpleDelivery;
 import org.jboss.messaging.core.tx.Transaction;
@@ -72,7 +72,7 @@
 
    // Router implementation -----------------------------------------
    
-   public Delivery handle(DeliveryObserver observer, Routable routable, Transaction tx)
+   public Delivery handle(DeliveryObserver observer, MessageReference ref, Transaction tx)
    {
       int initial, current;
       ArrayList receiversCopy;
@@ -102,9 +102,9 @@
 
          try
          {
-            Delivery d = r.handle(observer, routable, tx);
+            Delivery d = r.handle(observer, ref, tx);
 
-            if (trace) { log.trace("receiver " + r + " handled " + routable + " and returned " + d); }
+            if (trace) { log.trace("receiver " + r + " handled " + ref + " and returned " + d); }
 
             if (d != null && !d.isCancelled())
             {

Modified: trunk/src/main/org/jboss/messaging/core/memory/MemoryManager.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/memory/MemoryManager.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/memory/MemoryManager.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -21,6 +21,8 @@
  */
 package org.jboss.messaging.core.memory;
 
+import org.jboss.messaging.core.plugin.contract.MessagingComponent;
+
 /**
  * A MemoryManager
 
@@ -30,12 +32,7 @@
  * $Id$
  *
  */
-public interface MemoryManager
+public interface MemoryManager extends MessagingComponent
 {
-   void start();
-   
-   void stop();
-   
-   boolean isMemoryLow();
-      
+   boolean isMemoryLow();    
 }

Added: trunk/src/main/org/jboss/messaging/core/plugin/ClusteredPostOfficeService.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/ClusteredPostOfficeService.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/ClusteredPostOfficeService.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,230 @@
+/*
+ * 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.messaging.core.plugin;
+
+import javax.management.ObjectName;
+import javax.transaction.TransactionManager;
+
+import org.jboss.jms.server.ServerPeer;
+import org.jboss.jms.util.ExceptionUtil;
+import org.jboss.messaging.core.plugin.contract.MessageStore;
+import org.jboss.messaging.core.plugin.contract.MessagingComponent;
+import org.jboss.messaging.core.plugin.contract.PersistenceManager;
+import org.jboss.messaging.core.plugin.postoffice.cluster.ClusteredPostOfficeImpl;
+import org.jboss.messaging.core.tx.TransactionRepository;
+import org.w3c.dom.Element;
+
+/**
+ * A ClusteredPostOfficeService
+ * 
+ * MBean wrapper for a clustered post office
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class ClusteredPostOfficeService extends JDBCServiceSupport
+{
+   private ClusteredPostOfficeImpl postOffice;
+   
+   private ObjectName serverPeerObjectName;
+   
+   private String officeName;
+   
+   private boolean started;
+   
+   private Element syncChannelConfig;
+   
+   private Element asyncChannelConfig;
+   
+   private long stateTimeout = 5000;
+   
+   private long castTimeout = 5000;
+   
+   private String groupName;
+   
+   // Constructors --------------------------------------------------------
+   
+   public ClusteredPostOfficeService()
+   {      
+   }
+   
+   // ServerPlugin implementation ------------------------------------------
+   
+   public MessagingComponent getInstance()
+   {
+      return postOffice;
+   }
+   
+   // MBean attributes -----------------------------------------------------
+   
+   public synchronized ObjectName getServerPeer()
+   {
+      return serverPeerObjectName;
+   }
+   
+   public synchronized void setServerPeer(ObjectName on)
+   {
+      if (started)
+      {
+         log.warn("Cannot set attribute when service is started");
+         return;
+      }
+      this.serverPeerObjectName = on;
+   }
+   
+   public synchronized String getPostOfficeName()
+   {
+      return officeName;
+   }
+   
+   public synchronized void setPostOfficeName(String name)
+   {
+      if (started)
+      {
+         log.warn("Cannot set attribute when service is started");
+         return;
+      }
+      this.officeName = name;
+   }
+   
+   public void setSyncChannelConfig(Element config) throws Exception
+   {
+      syncChannelConfig = config;
+   }
+
+   public Element getSyncChannelConfig()
+   {
+      return syncChannelConfig;
+   }
+   
+   public void setAsyncChannelConfig(Element config) throws Exception
+   {
+      asyncChannelConfig = config;
+   }
+
+   public Element getAsyncChannelConfig()
+   {
+      return asyncChannelConfig;
+   }
+   
+   public void setStateTimeout(long timeout)
+   {
+      this.stateTimeout = timeout;
+   }
+   
+   public long getStateTimeout()
+   {
+      return stateTimeout;
+   }
+   
+   public void setCastTimeout(long timeout)
+   {
+      this.castTimeout = timeout;
+   }
+   
+   public long getCastTimeout()
+   {
+      return castTimeout;
+   }
+   
+   public void setGroupName(String groupName)
+   {
+      this.groupName = groupName;
+   }
+   
+   public String getGroupName()
+   {
+      return groupName;
+   }
+   
+   // ServiceMBeanSupport overrides ---------------------------------
+   
+   protected synchronized void startService() throws Exception
+   {
+      if (started)
+      {
+         throw new IllegalStateException("Service is already started");
+      }
+      
+      super.startService();
+      
+      try
+      {  
+         TransactionManager tm = getTransactionManagerReference();
+                  
+         
+         ServerPeer serverPeer = (ServerPeer)server.getAttribute(serverPeerObjectName, "Instance");
+         
+         MessageStore ms = serverPeer.getMessageStore();
+         
+         TransactionRepository tr = serverPeer.getTxRepository();
+         
+         PersistenceManager pm = serverPeer.getPersistenceManagerInstance();
+         
+         String nodeId = serverPeer.getServerPeerID();
+                  
+         postOffice =  new ClusteredPostOfficeImpl(ds, tm, sqlProperties, createTablesOnStartup,
+                                               nodeId, officeName, ms,
+                                               groupName,
+                                               syncChannelConfig, asyncChannelConfig,
+                                               tr, pm, stateTimeout, castTimeout);
+         
+         postOffice.start();
+         
+         started = true;         
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " startService");
+      } 
+   }
+   
+   protected void stopService() throws Exception
+   {
+      if (!started)
+      {
+         throw new IllegalStateException("Service is not started");
+      }
+      
+      super.stopService();      
+      
+      try
+      {      
+         postOffice.stop();
+         
+         postOffice = null;
+               
+         started = false;
+         
+         log.debug(this + " stopped");
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " startService");
+      } 
+   }
+      
+}
+

Modified: trunk/src/main/org/jboss/messaging/core/plugin/IdManager.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/IdManager.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/IdManager.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -22,6 +22,7 @@
 package org.jboss.messaging.core.plugin;
 
 import org.jboss.logging.Logger;
+import org.jboss.messaging.core.plugin.contract.MessagingComponent;
 import org.jboss.messaging.core.plugin.contract.PersistenceManager;
 
 /**
@@ -33,7 +34,7 @@
  *
  * IdManager.java,v 1.1 2006/03/07 17:11:15 timfox Exp
  */
-public class IdManager
+public class IdManager implements MessagingComponent
 {
    private static final Logger log = Logger.getLogger(IdManager.class);   
    
@@ -55,11 +56,19 @@
       
       this.pm = pm;
       
-      this.counterName = counterName;
-      
+      this.counterName = counterName;           
+   }
+   
+   public void start() throws Exception
+   {
       getNextBigBlock();
    }
    
+   public void stop() throws Exception
+   {
+      //NOOP
+   }
+   
    public synchronized IdBlock getIdBlock(int size) throws Exception
    {
       if (size <= 0)

Added: trunk/src/main/org/jboss/messaging/core/plugin/JDBCMBeanSupport.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/JDBCMBeanSupport.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/JDBCMBeanSupport.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,181 @@
+/*
+ * 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.messaging.core.plugin;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.ObjectName;
+import javax.naming.InitialContext;
+import javax.sql.DataSource;
+import javax.transaction.TransactionManager;
+
+import org.jboss.jms.util.ExceptionUtil;
+import org.jboss.system.ServiceMBeanSupport;
+import org.jboss.tm.TransactionManagerServiceMBean;
+
+/**
+ * A JDBCMBeanSupport
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class JDBCMBeanSupport extends ServiceMBeanSupport
+{
+   protected DataSource ds;
+   
+   protected Properties sqlProperties;
+         
+   protected TransactionManager tm;
+      
+   private String dataSourceJNDIName;
+   
+   private boolean createTablesOnStartup = true;
+   
+   private ObjectName tmObjectName;
+     
+   public JDBCMBeanSupport()
+   {
+      sqlProperties = new Properties();
+   }   
+   
+   // ServiceMBeanSupport overrides ---------------------------------
+   
+   protected void startService() throws Exception
+   {
+      try
+      {
+         if (ds == null)
+         {
+            InitialContext ic = new InitialContext();
+            ds = (DataSource)ic.lookup(dataSourceJNDIName);
+            ic.close();
+         }
+         
+         if (ds == null)
+         {
+            throw new IllegalStateException("No DataSource found. This service dependencies must " +
+            "have not been enforced correctly!");
+         }
+         
+         log.debug(this + " started");
+         
+         tm = getTransactionManagerReference();
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " startService");
+      } 
+   }
+   
+   protected void stopService() throws Exception
+   {
+      log.debug(this + " stopped");
+   }
+  
+   // MBean attributes --------------------------------------------------------
+      
+   public String getSqlProperties()
+   {
+      try
+      {
+         ByteArrayOutputStream boa = new ByteArrayOutputStream();
+         sqlProperties.store(boa, "");
+         return new String(boa.toByteArray());
+      }
+      catch (IOException shouldnothappen)
+      {
+         return "";
+      }
+   }
+   
+   public void setSqlProperties(String value)
+   {
+      try
+      {         
+         ByteArrayInputStream is = new ByteArrayInputStream(value.getBytes());
+         sqlProperties = new Properties();
+         sqlProperties.load(is);         
+      }
+      catch (IOException shouldnothappen)
+      {
+         log.error("Caught IOException", shouldnothappen);
+      }
+   }
+      
+   public void setDataSource(String dataSourceJNDIName) throws Exception
+   {
+      this.dataSourceJNDIName = dataSourceJNDIName;
+   }
+   
+   public String getDataSource()
+   {
+      return dataSourceJNDIName;
+   }
+   
+   public void setTransactionManager(ObjectName tmObjectName) throws Exception
+   {
+      this.tmObjectName = tmObjectName;
+   }
+   
+   public ObjectName getTransactionManager()
+   {
+      return tmObjectName;
+   }
+
+   public boolean isCreateTablesOnStartup() throws Exception
+   {
+      return createTablesOnStartup;
+   }
+
+   public void setCreateTablesOnStartup(boolean b) throws Exception
+   {
+      createTablesOnStartup = b;
+   }
+   
+   // Protected ----------------------------------------------------------     
+   
+   // Private ----------------------------------------------------------------
+   
+   private TransactionManager getTransactionManagerReference()
+   {
+      // lazy initialization
+      if (tm == null)
+      {
+         TransactionManagerServiceMBean tms =
+            (TransactionManagerServiceMBean)MBeanServerInvocationHandler.
+            newProxyInstance(getServer(), tmObjectName, TransactionManagerServiceMBean.class, false);
+
+         tm = tms.getTransactionManager();
+      }
+
+      return tm;
+   }
+           
+   // Innner classes ---------------------------------------------------------   
+}

Modified: trunk/src/main/org/jboss/messaging/core/plugin/JDBCPersistenceManager.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/JDBCPersistenceManager.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/JDBCPersistenceManager.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -38,6 +38,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Properties;
 
 import javax.sql.DataSource;
 import javax.transaction.TransactionManager;
@@ -75,7 +76,7 @@
  *
  * JDBCPersistenceManager.java,v 1.1 2006/02/22 17:33:41 timfox Exp
  */
-public class JDBCPersistenceManager extends JDBCServiceSupport implements PersistenceManager
+public class JDBCPersistenceManager extends JDBCSupport implements PersistenceManager
 {
    // Constants -----------------------------------------------------
    
@@ -87,33 +88,33 @@
    
    private boolean trace = log.isTraceEnabled();
       
-   protected boolean usingBatchUpdates = false;
+   private boolean usingBatchUpdates = false;
    
-   protected boolean usingBinaryStream = true;
+   private boolean usingBinaryStream = true;
    
-   protected int maxParams = 100;
+   private int maxParams;
    
-   protected int minOrdering;
-   
    // Constructors --------------------------------------------------
-   
-   public JDBCPersistenceManager()
+    
+   public JDBCPersistenceManager(DataSource ds, TransactionManager tm, Properties sqlProperties,
+                                 boolean createTablesOnStartup, boolean usingBatchUpdates,
+                                 boolean usingBinaryStream, int maxParams)
    {
+      super(ds, tm, sqlProperties, createTablesOnStartup);
+      
+      this.usingBatchUpdates = usingBatchUpdates;
+      
+      this.usingBinaryStream = usingBinaryStream;
+      
+      this.maxParams = maxParams;      
    }
    
-   /*
-    * This constructor should only be used for testing
-    */
-   public JDBCPersistenceManager(DataSource ds, TransactionManager tm)
-   {
-      super(ds, tm);
-   }
-      
-   // ServiceMBeanSupport overrides ---------------------------------
    
-   protected void startService() throws Exception
+   // MessagingComponent overrides ---------------------------------
+   
+   public void start() throws Exception
    {
-      super.startService();
+      super.start();
 
       Connection conn = null;
       
@@ -144,6 +145,11 @@
       log.debug(this + " started");
    }
    
+   public void stop() throws Exception
+   {
+      super.stop();
+   }
+   
    // PersistenceManager implementation -------------------------
    
    // Related to counters
@@ -454,7 +460,7 @@
                   byte[] payload = getBytes(rs, 7);
                   int persistentChannelCount = rs.getInt(8);
                   
-                  //FIXME - We are mixing concerns here
+                  //TODO - We are mixing concerns here
                   //The basic JDBCPersistencManager should *only* know about core messages - not 
                   //JBossMessages - we should subclass JBDCPersistenceManager and the JBossMessage
                   //specific code in a subclass
@@ -1868,42 +1874,13 @@
       }
    }
    
-  
    // Public --------------------------------------------------------
    
-   /**
-    * Managed attribute.
-    */
-   public boolean isUsingBatchUpdates() throws Exception
-   {
-      return usingBatchUpdates;
-   }
-   
-   /**
-    * Managed attribute.
-    */
-   public void setUsingBatchUpdates(boolean b) throws Exception
-   {
-      usingBatchUpdates = b;
-   }
-   
-   public int getMaxParams()
-   {
-      return maxParams;
-   }
-   
-   public void setMaxParams(int maxParams)
-   {
-      this.maxParams = maxParams;
-   }
-   
    public String toString()
    {
       return "JDBCPersistenceManager[" + Integer.toHexString(hashCode()) + "]";
    }
    
-   // Public --------------------------------------------------------
-   
    // Package protected ---------------------------------------------
    
    // Protected -----------------------------------------------------

Added: trunk/src/main/org/jboss/messaging/core/plugin/JDBCPersistenceManagerService.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/JDBCPersistenceManagerService.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/JDBCPersistenceManagerService.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,138 @@
+/*
+ * 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.messaging.core.plugin;
+
+import javax.transaction.TransactionManager;
+
+import org.jboss.jms.util.ExceptionUtil;
+import org.jboss.messaging.core.plugin.contract.MessagingComponent;
+import org.jboss.messaging.core.plugin.contract.PersistenceManager;
+
+/**
+ * A JDBCPersistenceManagerService
+ * 
+ * MBean wrapper around a JDBCPersistenceManager
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class JDBCPersistenceManagerService extends JDBCServiceSupport
+{
+   private PersistenceManager persistenceManager;
+   
+   private boolean started;
+   
+   private boolean usingBatchUpdates = false;
+   
+   private int maxParams = 100;
+   
+   // Constructors --------------------------------------------------------
+   
+   public JDBCPersistenceManagerService()
+   {      
+   }
+   
+   // ServerPlugin implementation ------------------------------------------
+   
+   public MessagingComponent getInstance()
+   {
+      return persistenceManager;
+   }
+   
+   // ServiceMBeanSupport overrides -----------------------------------------
+   
+   protected synchronized void startService() throws Exception
+   {
+      if (started)
+      {
+         throw new IllegalStateException("Service is already started");
+      }
+      
+      super.startService();
+      
+      try
+      {  
+         TransactionManager tm = getTransactionManagerReference();
+         
+         persistenceManager =
+            new JDBCPersistenceManager(ds, tm, sqlProperties,
+                                       createTablesOnStartup, usingBatchUpdates,
+                                       true, maxParams);
+         
+         persistenceManager.start();
+         
+         started = true;
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " startService");
+      } 
+   }
+   
+   protected void stopService() throws Exception
+   {
+      if (!started)
+      {
+         throw new IllegalStateException("Service is not started");
+      }
+      
+      try
+      {
+         persistenceManager.stop();
+         
+         persistenceManager = null;
+         
+         started = false;
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " startService");
+      } 
+      
+      log.debug(this + " stopped");
+   }
+   
+   // MBean attributes -------------------------------------------------------
+   
+   public boolean isUsingBatchUpdates()
+   {
+      return usingBatchUpdates;
+   }
+   
+   public void setUsingBatchUpdates(boolean b)
+   {
+      usingBatchUpdates = b;
+   }
+   
+   public int getMaxParams()
+   {
+      return maxParams;
+   }
+   
+   public void setMaxParams(int maxParams)
+   {
+      this.maxParams = maxParams;
+   }
+}

Modified: trunk/src/main/org/jboss/messaging/core/plugin/JDBCServiceSupport.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/JDBCServiceSupport.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/JDBCServiceSupport.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -24,18 +24,12 @@
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
 import java.util.Properties;
 
 import javax.management.MBeanServerInvocationHandler;
 import javax.management.ObjectName;
 import javax.naming.InitialContext;
 import javax.sql.DataSource;
-import javax.transaction.Status;
 import javax.transaction.TransactionManager;
 
 import org.jboss.jms.util.ExceptionUtil;
@@ -44,12 +38,12 @@
 import org.jboss.tm.TransactionManagerServiceMBean;
 
 /**
+ * 
  * A JDBCServiceSupport
+ * 
+ * MBean wrapper for any service that needs database attributes
  *
- * Common functionality for any service that needs to access a database
- *
  * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
  * @version <tt>$Revision: 1.1 $</tt>
  *
  * $Id$
@@ -61,49 +55,15 @@
    
    protected Properties sqlProperties;
          
-   // never access directly
-   private TransactionManager tm;
-    
-   private Map defaultDMLStatements;
-   
-   private Map defaultDDLStatements;
-   
    private String dataSourceJNDIName;
    
-   private boolean createTablesOnStartup = true;
+   protected boolean createTablesOnStartup = true;
    
    private ObjectName tmObjectName;
    
-   
-   public JDBCServiceSupport()
-   {
-      defaultDMLStatements = new HashMap();
+   private TransactionManager tm;
       
-      defaultDDLStatements = new HashMap();
-      
-      sqlProperties = new Properties();
-   }
    
-   /*
-    * This constructor should only be used for testing
-    */
-   public JDBCServiceSupport(DataSource ds, TransactionManager tm)
-   {
-      this();
-      
-      this.ds = ds;
-      
-      this.tm = tm;
-   }
-   
-   
-   // ServerPlugin implementation ------------------------------------------
-   
-   public Object getInstance()
-   {
-      return this;
-   }
-   
    // ServiceMBeanSupport overrides ---------------------------------
    
    protected void startService() throws Exception
@@ -123,58 +83,6 @@
             "have not been enforced correctly!");
          }
          
-         defaultDMLStatements.putAll(getDefaultDMLStatements());
-         
-         defaultDDLStatements.putAll(getDefaultDDLStatements());
-                  
-         //Validate the SQL properties
-         Iterator iter = this.sqlProperties.keySet().iterator();
-         
-         while (iter.hasNext())
-         {
-            String statementName = (String)iter.next();
-            
-            //This will throw an exception if there is no default for the statement specified in the
-            //sql properties
-            getSQLStatement(statementName);
-         }
-         
-         //Also we validate the other way - if there are any sql properties specified then there should be one for every
-         //default property
-         //This allows us to catch subtle errors in the persistence manager configuration
-         if (!sqlProperties.isEmpty())
-         {
-            iter = defaultDMLStatements.keySet().iterator();
-            
-            while (iter.hasNext())
-            {
-               String statementName = (String)iter.next();
-               
-               if (sqlProperties.get(statementName) == null)
-               {
-                  throw new IllegalStateException("SQL statement " + statementName + " is not specified in the persistence manager SQL properties");
-               }
-            }
-            
-            iter = defaultDDLStatements.keySet().iterator();
-            
-            while (iter.hasNext())
-            {
-               String statementName = (String)iter.next();
-               
-               if (sqlProperties.get(statementName) == null)
-               {
-                  throw new IllegalStateException("SQL statement " + statementName + " is not specified in the persistence manager SQL properties");
-               }
-            }
-         }
-         
-         if (createTablesOnStartup)
-         {
-            createSchema();
-         }
-         
-         log.debug(this + " started");
       }
       catch (Throwable t)
       {
@@ -248,34 +156,8 @@
    }
    
    // Protected ----------------------------------------------------------     
-   
-   protected String getSQLStatement(String statementName)
-   {
-      String defaultStatement = (String)defaultDMLStatements.get(statementName);
       
-      if (defaultStatement == null)
-      {
-         defaultStatement = (String)defaultDDLStatements.get(statementName);
-      }
-      
-      if (defaultStatement == null)
-      {
-         throw new IllegalArgumentException("No such SQL statement: " + statementName);
-      }
-      
-      String statement = sqlProperties.getProperty(statementName, defaultStatement);
-      
-      return statement;
-   }
-   
-   protected abstract Map getDefaultDDLStatements();
-   
-   protected abstract Map getDefaultDMLStatements();
-   
-   
-   // Private ----------------------------------------------------------------
-   
-   private TransactionManager getTransactionManagerReference()
+   protected TransactionManager getTransactionManagerReference()
    {
       // lazy initialization
       if (tm == null)
@@ -289,101 +171,10 @@
 
       return tm;
    }
-           
-   private void createSchema() throws Exception
-   {      
-      Connection conn = null;      
-      TransactionWrapper tx = new TransactionWrapper();
-      
-      try
-      {
-         conn = ds.getConnection();
-         
-         Iterator iter = defaultDDLStatements.keySet().iterator();
-         
-         while (iter.hasNext())
-         {
-            String statementName = (String)iter.next();
-             
-            String statement = getSQLStatement(statementName);
-            
-            try
-            {
-               if (log.isTraceEnabled()) { log.trace("Executing: " + statement); }
-                   
-               conn.createStatement().executeUpdate(statement);
-            }
-            catch (SQLException e) 
-            {
-               log.debug("Failed to execute: " + statement, e);
-            }  
-         }      
-      }
-      finally
-      {
-         if (conn != null)
-         {
-            try
-            {
-               conn.close();
-            }
-            catch (Throwable t)
-            {}
-         }
-         tx.end();
-      }      
-   }      
    
-   // Innner classes ---------------------------------------------------------
+   // Private ----------------------------------------------------------------
    
-   protected class TransactionWrapper
-   {
-      private javax.transaction.Transaction oldTx;
-      
-      private boolean failed;
-      
-      public TransactionWrapper() throws Exception
-      {
-         TransactionManager tm = getTransactionManagerReference();
-
-         oldTx = tm.suspend();
-         
-         tm.begin();
-      }
-      
-      public void end() throws Exception
-      {
-         TransactionManager tm = getTransactionManagerReference();
-
-         try
-         {
-            if (Status.STATUS_MARKED_ROLLBACK == tm.getStatus())
-            {
-               failed = true;
-               tm.rollback();               
-            }
-            else
-            {
-               tm.commit();
-            }
-         }
-         finally
-         {
-            if (oldTx != null && tm != null)
-            {
-               tm.resume(oldTx);
-            }
-         }
-      }      
-      
-      public void exceptionOccurred() throws Exception
-      {
-         getTransactionManagerReference().setRollbackOnly();
-      }
-      
-      public boolean isFailed()
-      {
-         return failed;
-      }
-   }
+                 
+   // Innner classes ---------------------------------------------------------   
 }
+

Modified: trunk/src/main/org/jboss/messaging/core/plugin/JDBCShutdownLogger.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/JDBCShutdownLogger.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/JDBCShutdownLogger.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -26,12 +26,17 @@
 import java.sql.ResultSet;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Properties;
 
+import javax.sql.DataSource;
+import javax.transaction.TransactionManager;
+
 import org.jboss.logging.Logger;
 import org.jboss.messaging.core.plugin.contract.ShutdownLogger;
 
 /**
- * A ShutdownLogger
+ * 
+ * A JDBCShutdownLogger
  *
  * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
  * @version <tt>$Revision: 1.1 $</tt>
@@ -39,30 +44,20 @@
  * $Id$
  *
  */
-public class JDBCShutdownLogger extends JDBCServiceSupport implements ShutdownLogger
+public class JDBCShutdownLogger extends JDBCSupport implements ShutdownLogger
 {
    private static final Logger log = Logger.getLogger(JDBCShutdownLogger.class); 
    
-   protected Map getDefaultDDLStatements()
+   // Constructors ----------------------------------------------------
+   
+   public JDBCShutdownLogger(DataSource ds, TransactionManager tm, Properties sqlProperties,
+                             boolean createTablesOnStartup)
    {
-      Map sql = new HashMap();
-      
-      sql.put("CREATE_STARTUP", "CREATE TABLE JMS_STARTUP (NODE_ID CHAR(1) PRIMARY KEY)");
-      
-      return sql;
+      super(ds, tm, sqlProperties, createTablesOnStartup);
    }
-
-   protected Map getDefaultDMLStatements()
-   {
-      Map sql = new HashMap();
-      
-      sql.put("SELECT_STARTUP", "SELECT NODE_ID FROM JMS_STARTUP WHERE NODE_ID = ?");
-      sql.put("DELETE_STARTUP", "DELETE FROM JMS_STARTUP WHERE NODE_ID = ?");
-      sql.put("INSERT_STARTUP", "INSERT INTO JMS_STARTUP (NODE_ID) VALUES (?)");
-      
-      return sql;
-   }
-
+   
+   // ShutdownLogger implementation ---------------------------------------------
+   
    public boolean shutdown(String nodeId) throws Exception
    {
       boolean exists = existsStartup(nodeId);
@@ -207,6 +202,8 @@
       }
    }
    
+   // Private ------------------------------------------------------------
+   
    private void insertStartup(String nodeId) throws Exception
    {
       Connection conn = null;
@@ -252,5 +249,25 @@
          wrap.end();
       }
    }
+   
+   protected Map getDefaultDDLStatements()
+   {
+      Map sql = new HashMap();
+      
+      sql.put("CREATE_STARTUP", "CREATE TABLE JMS_STARTUP (NODE_ID CHAR(1) PRIMARY KEY)");
+      
+      return sql;
+   }
 
+   protected Map getDefaultDMLStatements()
+   {
+      Map sql = new HashMap();
+      
+      sql.put("SELECT_STARTUP", "SELECT NODE_ID FROM JMS_STARTUP WHERE NODE_ID = ?");
+      sql.put("DELETE_STARTUP", "DELETE FROM JMS_STARTUP WHERE NODE_ID = ?");
+      sql.put("INSERT_STARTUP", "INSERT INTO JMS_STARTUP (NODE_ID) VALUES (?)");
+      
+      return sql;
+   }
+
 }

Added: trunk/src/main/org/jboss/messaging/core/plugin/JDBCShutdownLoggerService.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/JDBCShutdownLoggerService.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/JDBCShutdownLoggerService.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,99 @@
+/*
+ * 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.messaging.core.plugin;
+
+import javax.transaction.TransactionManager;
+
+import org.jboss.jms.util.ExceptionUtil;
+import org.jboss.messaging.core.plugin.contract.MessagingComponent;
+import org.jboss.messaging.core.plugin.contract.ShutdownLogger;
+
+/**
+ * A JDBCShutdownLoggerService
+ * 
+ * MBean wrapper around a ShutDownLogger
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class JDBCShutdownLoggerService extends JDBCServiceSupport
+{
+   private ShutdownLogger shutdownLogger;
+   
+   private boolean started;
+   
+   // Constructors ---------------------------------------------------------
+   
+   public JDBCShutdownLoggerService()
+   {      
+   }
+   
+   // ServerPlugin implementation ------------------------------------------
+   
+   public MessagingComponent getInstance()
+   {
+      return shutdownLogger;
+   }
+   
+   // ServiceMBeanSupport overrides ---------------------------------
+   
+   protected synchronized void startService() throws Exception
+   {
+      if (started)
+      {
+         throw new IllegalStateException("Service is already started");
+      }
+      
+      super.startService();
+      
+      try
+      {  
+         TransactionManager tm = getTransactionManagerReference();
+                  
+         shutdownLogger = new JDBCShutdownLogger(ds, tm, sqlProperties, createTablesOnStartup);
+         
+         shutdownLogger.start();
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " startService");
+      } 
+   }
+   
+   protected void stopService() throws Exception
+   {
+      if (!started)
+      {
+         throw new IllegalStateException("Service is not started");
+      }
+      
+      shutdownLogger.stop();
+      shutdownLogger = null;
+      
+      started = false;
+      
+      log.debug(this + " stopped");
+   }
+}

Added: trunk/src/main/org/jboss/messaging/core/plugin/JDBCSupport.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/JDBCSupport.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/JDBCSupport.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,284 @@
+/*
+ * 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.messaging.core.plugin;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.sql.DataSource;
+import javax.transaction.Status;
+import javax.transaction.TransactionManager;
+
+import org.jboss.logging.Logger;
+import org.jboss.messaging.core.plugin.contract.MessagingComponent;
+
+/**
+ * 
+ * A JDBCSupport
+ * 
+ * Common functionality for messaging components that need to access a database
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class JDBCSupport implements MessagingComponent
+{
+   private static final Logger log = Logger.getLogger(JDBCSupport.class);
+      
+   protected DataSource ds;
+   
+   private TransactionManager tm;
+      
+   protected Properties sqlProperties;
+         
+   private Map defaultDMLStatements;
+   
+   private Map defaultDDLStatements;
+       
+   private boolean createTablesOnStartup = true;
+      
+   public JDBCSupport()
+   {
+      defaultDMLStatements = new HashMap();
+      
+      defaultDDLStatements = new HashMap();
+      
+      sqlProperties = new Properties();
+   }
+   
+   public JDBCSupport(DataSource ds, TransactionManager tm, Properties sqlProperties,
+                      boolean createTablesOnStartup)
+   {
+      this();
+      
+      this.ds = ds;
+      
+      this.tm = tm;
+      
+      if (sqlProperties != null)
+      {
+         this.sqlProperties = sqlProperties;
+      }
+      
+      this.createTablesOnStartup = createTablesOnStartup;
+   }
+      
+   // MessagingComponent overrides ---------------------------------
+   
+   public void start() throws Exception
+   {
+      log.info("In jdbcsupport::start");
+      
+      defaultDMLStatements.putAll(getDefaultDMLStatements());
+      
+      defaultDDLStatements.putAll(getDefaultDDLStatements());
+               
+      //Validate the SQL properties
+      Iterator iter = this.sqlProperties.keySet().iterator();
+      
+      while (iter.hasNext())
+      {
+         String statementName = (String)iter.next();
+         
+         //This will throw an exception if there is no default for the statement specified in the
+         //sql properties
+         getSQLStatement(statementName);
+      }
+      
+      //Also we validate the other way - if there are any sql properties specified then there should be one for every
+      //default property
+      //This allows us to catch subtle errors in the persistence manager configuration
+      if (!sqlProperties.isEmpty())
+      {
+         iter = defaultDMLStatements.keySet().iterator();
+         
+         while (iter.hasNext())
+         {
+            String statementName = (String)iter.next();
+            
+            if (sqlProperties.get(statementName) == null)
+            {
+               throw new IllegalStateException("SQL statement " + statementName + " is not specified in the persistence manager SQL properties");
+            }
+         }
+         
+         iter = defaultDDLStatements.keySet().iterator();
+         
+         while (iter.hasNext())
+         {
+            String statementName = (String)iter.next();
+            
+            if (sqlProperties.get(statementName) == null)
+            {
+               throw new IllegalStateException("SQL statement " + statementName + " is not specified in the persistence manager SQL properties");
+            }
+         }
+      }
+      
+      if (createTablesOnStartup)
+      {
+         createSchema();
+      }
+      
+      log.debug(this + " started");      
+   }
+   
+   public void stop() throws Exception
+   {
+      log.debug(this + " stopped");
+   }
+    
+   
+   // Protected ----------------------------------------------------------     
+   
+   protected String getSQLStatement(String statementName)
+   {
+      String defaultStatement = (String)defaultDMLStatements.get(statementName);
+      
+      if (defaultStatement == null)
+      {
+         defaultStatement = (String)defaultDDLStatements.get(statementName);
+      }
+      
+      if (defaultStatement == null)
+      {
+         throw new IllegalArgumentException("No such SQL statement: " + statementName);
+      }
+      
+      String statement = sqlProperties.getProperty(statementName, defaultStatement);
+      
+      return statement;
+   }
+   
+   protected Map getDefaultDMLStatements()
+   {                
+      return Collections.EMPTY_MAP;
+   }
+   
+   protected Map getDefaultDDLStatements()
+   {
+      return Collections.EMPTY_MAP;
+   }
+   
+   // Private ----------------------------------------------------------------
+              
+   private void createSchema() throws Exception
+   {      
+      Connection conn = null;      
+      TransactionWrapper tx = new TransactionWrapper();
+      
+      try
+      {
+         conn = ds.getConnection();
+         
+         Iterator iter = defaultDDLStatements.keySet().iterator();
+         
+         while (iter.hasNext())
+         {
+            String statementName = (String)iter.next();
+             
+            String statement = getSQLStatement(statementName);
+            
+            try
+            {
+               if (log.isTraceEnabled()) { log.trace("Executing: " + statement); }
+                   
+               conn.createStatement().executeUpdate(statement);
+            }
+            catch (SQLException e) 
+            {
+               log.debug("Failed to execute: " + statement, e);
+            }  
+         }      
+      }
+      finally
+      {
+         if (conn != null)
+         {
+            try
+            {
+               conn.close();
+            }
+            catch (Throwable t)
+            {}
+         }
+         tx.end();
+      }      
+   }      
+   
+   // Innner classes ---------------------------------------------------------
+   
+   protected class TransactionWrapper
+   {
+      private javax.transaction.Transaction oldTx;
+      
+      private boolean failed;
+      
+      public TransactionWrapper() throws Exception
+      {
+         oldTx = tm.suspend();
+         
+         tm.begin();
+      }
+      
+      public void end() throws Exception
+      {
+         try
+         {
+            if (Status.STATUS_MARKED_ROLLBACK == tm.getStatus())
+            {
+               failed = true;
+               tm.rollback();               
+            }
+            else
+            {
+               tm.commit();
+            }
+         }
+         finally
+         {
+            if (oldTx != null && tm != null)
+            {
+               tm.resume(oldTx);
+            }
+         }
+      }      
+      
+      public void exceptionOccurred() throws Exception
+      {
+         tm.setRollbackOnly();
+      }
+      
+      public boolean isFailed()
+      {
+         return failed;
+      }
+   }
+}

Modified: trunk/src/main/org/jboss/messaging/core/plugin/SimpleMessageStore.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/SimpleMessageStore.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/SimpleMessageStore.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -135,6 +135,18 @@
    {
       return new ArrayList(messages.keySet());
    }
+   
+   // MessagingComponent implementation --------------------------------
+   
+   public void start() throws Exception
+   {
+      //NOOP
+   }
+   
+   public void stop() throws Exception
+   {
+      //NOOP
+   }
 
    // Public --------------------------------------------------------
    

Added: trunk/src/main/org/jboss/messaging/core/plugin/SimplePostOfficeService.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/SimplePostOfficeService.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/SimplePostOfficeService.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,159 @@
+/*
+ * 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.messaging.core.plugin;
+
+import javax.management.ObjectName;
+import javax.transaction.TransactionManager;
+
+import org.jboss.jms.server.ServerPeer;
+import org.jboss.jms.util.ExceptionUtil;
+import org.jboss.messaging.core.plugin.contract.MessageStore;
+import org.jboss.messaging.core.plugin.contract.MessagingComponent;
+import org.jboss.messaging.core.plugin.postoffice.PostOfficeImpl;
+
+/**
+ * A SimplePostOfficeService
+ * 
+ * MBean wrapper for a simple post office
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class SimplePostOfficeService extends JDBCServiceSupport
+{
+   private PostOfficeImpl postOffice;
+   
+   private ObjectName serverPeerObjectName;
+   
+   private String officeName;
+   
+   private boolean started;
+   
+   // Constructor ----------------------------------------------------------
+   
+   public SimplePostOfficeService()
+   {      
+   }
+   
+   // ServerPlugin implementation ------------------------------------------
+   
+   public MessagingComponent getInstance()
+   {
+      return postOffice;
+   }
+   
+   // MBean attributes -----------------------------------------------------
+   
+   public synchronized ObjectName getServerPeer()
+   {
+      return serverPeerObjectName;
+   }
+   
+   public synchronized void setServerPeer(ObjectName on)
+   {
+      if (started)
+      {
+         log.warn("Cannot set attribute when service is started");
+         return;
+      }
+      this.serverPeerObjectName = on;
+   }
+   
+   public synchronized String getPostOfficeName()
+   {
+      return officeName;
+   }
+   
+   public synchronized void setPostOfficeName(String name)
+   {
+      if (started)
+      {
+         log.warn("Cannot set attribute when service is started");
+         return;
+      }
+      this.officeName = name;
+   }
+   
+   // ServiceMBeanSupport overrides ---------------------------------
+   
+   protected synchronized void startService() throws Exception
+   {
+      if (started)
+      {
+         throw new IllegalStateException("Service is already started");
+      }
+      
+      super.startService();
+      
+      try
+      {  
+         TransactionManager tm = getTransactionManagerReference();
+         
+         log.info("SERVER PEER OBJECT NAME IS " + serverPeerObjectName);
+         ServerPeer serverPeer = (ServerPeer)server.getAttribute(serverPeerObjectName, "Instance");
+         
+         MessageStore ms = serverPeer.getMessageStore();
+         
+         String nodeId = serverPeer.getServerPeerID();
+                  
+         postOffice = new PostOfficeImpl(ds, tm, sqlProperties,
+                                           createTablesOnStartup,
+                                           nodeId, officeName, ms);
+         
+         postOffice.start();
+         
+         started = true;         
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " startService");
+      } 
+   }
+   
+   protected void stopService() throws Exception
+   {
+      if (!started)
+      {
+         throw new IllegalStateException("Service is not started");
+      }
+      
+      super.stopService();
+      
+      try
+      {      
+         postOffice.stop();
+         
+         postOffice = null;
+               
+         started = false;
+                     
+         log.debug(this + " stopped");
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " startService");
+      } 
+   }      
+}

Added: trunk/src/main/org/jboss/messaging/core/plugin/contract/Binding.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/contract/Binding.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/contract/Binding.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,61 @@
+/*
+ * 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.messaging.core.plugin.contract;
+
+import org.jboss.messaging.core.local.Queue;
+
+/**
+ * A Binding
+
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public interface Binding
+{
+   String getNodeId();
+   
+   String getQueueName();
+   
+   String getCondition();
+   
+   Queue getQueue();
+   
+   String getSelector();
+     
+   long getChannelId();
+   
+   boolean isDurable();
+   
+   boolean isNoLocal();
+   
+   boolean isActive();
+   
+   void activate();
+   
+   void deactivate();
+   
+   void setQueue(Queue queue);
+
+}

Added: trunk/src/main/org/jboss/messaging/core/plugin/contract/ClusteredPostOffice.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/contract/ClusteredPostOffice.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/contract/ClusteredPostOffice.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,57 @@
+/*
+ * 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.messaging.core.plugin.contract;
+
+import org.jboss.messaging.core.local.Queue;
+
+/**
+ * 
+ * A ClusteredPostOffice
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public interface ClusteredPostOffice extends PostOffice
+{
+   /**
+    * Bind a queue to the post office under a specific condition
+    * such that it is available across the cluster
+    * @param queueName The unique name of the queue
+    * @param condition The condition to be used when routing references
+    * @param noLocal
+    * @param queue
+    * @return
+    * @throws Exception
+    */
+   Binding bindClusteredQueue(String queueName, String condition, boolean noLocal, Queue queue) throws Exception;
+   
+   /**
+    * Unbind a clustered queue from the post office
+    * @param queueName The unique name of the queue
+    * @return
+    * @throws Throwable
+    */
+   Binding unbindClusteredQueue(String queueName) throws Throwable;
+}

Deleted: trunk/src/main/org/jboss/messaging/core/plugin/contract/Exchange.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/contract/Exchange.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/contract/Exchange.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -1,148 +0,0 @@
-/*
- * 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.messaging.core.plugin.contract;
-
-import java.util.List;
-
-import org.jboss.messaging.core.Filter;
-import org.jboss.messaging.core.MessageReference;
-import org.jboss.messaging.core.memory.MemoryManager;
-import org.jboss.messaging.core.plugin.exchange.Binding;
-import org.jboss.messaging.core.tx.Transaction;
-
-/**
- * 
- * An Exchange
- * 
- * It is the responsibility of the exchange to maintain bindings between names and queues, and handle
- * message routing to queues.
- * 
- * For a standard point to point queue, the Queue would be bound to a name that represents the name
- * of the queue, e.g. "MyQueue".
- * 
- * If the Queue represents a publish-subscribe subscription then it might be bound to the name
- * "MyTopic.subscription123".
- * 
- * Then we handling the message, a routing key is specified.
- * 
- * The routing key might be a simple name like "MyQueue" in which case the message would get sent to MyQueue
- * or it might be a wildcard expression e.g. "MyTopic.*" - in which case the message would get sent to any 
- * Queues bound to any names that start with "MyTopic."
- * 
- * In such a way we can provide the semantics of JMS Queues and Topics without having to create separate Queue
- * and Topic constructs which vastly simplifies the code.
- * 
- * It also acts as a placeholder for much more complex routing policies in the future.
- * 
- * Finally, it makes clustering simpler, since we only have to worry about clustering the Queue.
- * 
- * For now we only support one binding per queue.
- * 
- * If we are to support full blown AMQP style message exchanges then we would
- * need to support more than one binding per queue.
- * 
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision: 1.1 $</tt>
- *
- * $Id$
- *
- */
-public interface Exchange extends ServerPlugin
-{   
-   /**
-    * Creates a new MessageQueue and binds it to the exchange
-    * If a binding with the queueName already exist an exception is thrown
-    * @param queueName
-    * @param condition
-    * @param selector
-    * @param noLocal
-    * @param durable
-    * @return The binding
-    * @throws Exception
-    */
-   Binding bindQueue(String queueName, String condition, Filter filter, boolean noLocal, boolean durable,
-                     MessageStore ms, PersistenceManager pm,
-                     int fullSize, int pageSize, int downCacheSize) throws Exception;
-   
-   /**
-    * Removes the queue and all its data and unbinds it from the exchange
-    * @param queueName
-    * @return
-    * @throws Exception
-    */
-   Binding unbindQueue(String queueName) throws Throwable;
-   
-   /**
-    * Reloads any message queues whose condition matches the wildcard.
-    * @param wildcard
-    * @param ms
-    * @param pm
-    * @param mm
-    * @param fullSize
-    * @param pageSize
-    * @param downCacheSize
-    * @throws Exception
-    */
-   void reloadQueues(String wildcard,
-                     MessageStore ms, PersistenceManager pm,
-                     int fullSize, int pageSize, int downCacheSize) throws Exception;
-   
-   /**
-    * Unloads any queues for any bindings whose condition matches the wildcard
-    * @param wildcard
-    * @throws Exception
-    */
-   void unloadQueues(String wildcard) throws Exception;
-   
-   /**
-    * List all bindings whose condition matches the wildcard
-    * @param wildcard
-    * @return
-    * @throws Exception
-    */
-   List listBindingsForWildcard(String wildcard) throws Exception;
-   
-   
-   /**
-    * Returns binding that matches the name
-    * @param queueName
-    * @return
-    * @throws Exception
-    */
-   Binding getBindingForName(String queueName) throws Exception;
-   
-   /**
-    * Route a message
-    * @param message
-    * @param routingKey
-    * @param tx
-    * @return
-    * @throws Exception
-    */
-   boolean route(MessageReference ref, String routingKey, Transaction tx) throws Exception;   
-   
-   /**
-    * Recover the exchange
-    * @throws Exception
-    */
-   void recover() throws Exception;
-}

Modified: trunk/src/main/org/jboss/messaging/core/plugin/contract/MessageStore.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/contract/MessageStore.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/contract/MessageStore.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -18,7 +18,7 @@
  *
  * $Id$
  */
-public interface MessageStore
+public interface MessageStore extends MessagingComponent
 {
    /**
     * Message m is stored in the store if it is not already known to the store, then

Added: trunk/src/main/org/jboss/messaging/core/plugin/contract/MessagingComponent.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/contract/MessagingComponent.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/contract/MessagingComponent.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,38 @@
+/*
+ * 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.messaging.core.plugin.contract;
+
+/**
+ * A MessagingComponent
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public interface MessagingComponent
+{
+   void start() throws Exception;
+   
+   void stop() throws Exception;
+}

Added: trunk/src/main/org/jboss/messaging/core/plugin/contract/MessagingService.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/contract/MessagingService.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/contract/MessagingService.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,38 @@
+/*
+ * 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.messaging.core.plugin.contract;
+
+/**
+ * A MessagingService
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public interface MessagingService
+{
+   public void start() throws Exception;
+   
+   public void stop() throws Exception;
+}

Modified: trunk/src/main/org/jboss/messaging/core/plugin/contract/PersistenceManager.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/contract/PersistenceManager.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/contract/PersistenceManager.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -35,7 +35,7 @@
  *
  * PersistenceManager.java,v 1.1 2006/02/22 17:33:42 timfox Exp
  */
-public interface PersistenceManager extends ServerPlugin
+public interface PersistenceManager extends MessagingComponent
 {
    void addReference(long channelID, MessageReference ref, Transaction tx) throws Exception;
 

Added: trunk/src/main/org/jboss/messaging/core/plugin/contract/PostOffice.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/contract/PostOffice.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/contract/PostOffice.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,98 @@
+/*
+ * 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.messaging.core.plugin.contract;
+
+import java.util.List;
+
+import org.jboss.messaging.core.MessageReference;
+import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.tx.Transaction;
+
+/**
+ * 
+ * A PostOffice
+ * 
+ * A post office holds bindings of queues to conditions.
+ * 
+ * When routing a reference, the post office routes the reference to any binding whose
+ * condition matches the condition specified in the call to route(...)
+ * 
+ * Currently we only support conditions where the condition is an exact text match, and
+ * there is a single binding per queue.
+ * 
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public interface PostOffice extends MessagingComponent
+{   
+   /**
+    * Bind a queue to the post office under a specific condition
+    * @param queueName The unique name of the queue
+    * @param condition The condition to be used when routing references
+    * @param noLocal
+    * @param queue
+    * @return
+    * @throws Exception
+    */
+   Binding bindQueue(String queueName, String condition, boolean noLocal, Queue queue) throws Exception;
+   
+   /**
+    * Unbind a queue from the post office
+    * @param queueName The unique name of the queue
+    * @return
+    * @throws Throwable
+    */
+   Binding unbindQueue(String queueName) throws Throwable;
+   
+   /**
+    * List the bindings that match the specified condition
+    * @param condition
+    * @return
+    * @throws Exception
+    */
+   List listBindingsForCondition(String condition) throws Exception;
+   
+   /**
+    * Get the binding for the specified queue name
+    * @param queueName
+    * @return
+    * @throws Exception
+    */
+   Binding getBindingForQueueName(String queueName) throws Exception;
+   
+   /**
+    * Route a reference.
+    * @param ref
+    * @param condition The message will be routed to a queue if specified condition matches the condition
+    * of the binding
+    * 
+    * @param tx The transaction or null if not in the context of a transaction
+    * @return true if ref was accepted by at least one queue
+    * @throws Exception
+    */
+   boolean route(MessageReference ref, String condition, Transaction tx) throws Exception;   
+   
+   void recover() throws Exception;
+}

Modified: trunk/src/main/org/jboss/messaging/core/plugin/contract/ServerPlugin.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/contract/ServerPlugin.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/contract/ServerPlugin.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -6,19 +6,19 @@
  */
 package org.jboss.messaging.core.plugin.contract;
 
-import org.jboss.system.Service;
 
 /**
  * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
  * @version <tt>$Revision$</tt>
  *
  * $Id$
  */
-public interface ServerPlugin extends Service
+public interface ServerPlugin
 {
    /**
     * A server plugin will be always accessed via a hard reference, so it is essential that each
     * implementation exposes this method.
     */
-   Object getInstance();
+   MessagingComponent getInstance();
 }

Modified: trunk/src/main/org/jboss/messaging/core/plugin/contract/ShutdownLogger.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/contract/ShutdownLogger.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/contract/ShutdownLogger.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -30,7 +30,7 @@
  * $Id$
  *
  */
-public interface ShutdownLogger extends ServerPlugin
+public interface ShutdownLogger extends MessagingComponent
 {
    boolean startup(String nodeId) throws Exception;
    

Added: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/BindingImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/BindingImpl.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/BindingImpl.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,226 @@
+/*
+ * 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.messaging.core.plugin.postoffice;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.plugin.contract.Binding;
+
+/**
+ * 
+ * A BindingImpl
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class BindingImpl implements Binding, Externalizable
+{
+   private static final long serialVersionUID = -5518552214992031242L;
+
+   private static final byte NULL = 0;
+   
+   private static final byte NOT_NULL = 1;   
+
+   private String nodeId;
+   
+   private String queueName;
+   
+   private String condition;
+   
+   private Queue queue;
+    
+   private boolean noLocal;
+   
+   private boolean active;
+   
+   private String selector;
+   
+   private long channelId;
+     
+   private boolean durable;
+   
+   public BindingImpl()
+   {      
+   }
+
+   public BindingImpl(String nodeId, String queueName, String condition, String selector,
+                        boolean noLocal, long channelId, boolean durable)
+   {
+      this.nodeId = nodeId;
+      
+      this.queueName = queueName;
+      
+      this.condition = condition;      
+      
+      this.noLocal = noLocal;
+      
+      this.selector = selector;
+      
+      this.channelId = channelId;
+         
+      //Bindings are always created de-activated
+      this.active = false;
+      
+      this.durable = durable;          
+   }
+   
+   public String getNodeId()
+   {
+      return nodeId;
+   }
+     
+   public String getQueueName()
+   {
+      return queueName;
+   }
+   
+   public String getCondition()
+   {
+      return condition;
+   }
+   
+   public Queue getQueue()
+   {
+      return queue;
+   }
+
+   public boolean isNoLocal()
+   {
+      return noLocal;
+   }
+   
+   public void activate()
+   {
+      active = true;
+   }
+   
+   public void deactivate()
+   {
+      active = false;
+   }
+   
+   public boolean isActive()
+   {
+      return active;
+   }
+   
+   public String getSelector()
+   {
+      return selector;
+   }
+   
+   public long getChannelId()
+   {
+      return channelId;
+   }
+    
+   public boolean isDurable()
+   {
+      return durable;
+   }
+   
+   public void setQueue(Queue queue)
+   {
+      this.queue = queue;
+      
+      if (queue != null)
+      {
+         this.channelId = queue.getChannelID();
+      }            
+   }
+   
+
+   public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
+   {
+      nodeId = in.readUTF();
+      
+      queueName = in.readUTF();
+      
+      condition = in.readUTF();
+      
+      noLocal = in.readBoolean();
+      
+      active = in.readBoolean();
+      
+      selector = readString(in);
+      
+      channelId = in.readLong();
+      
+      durable = in.readBoolean();
+   }
+
+   public void writeExternal(ObjectOutput out) throws IOException
+   {
+      out.writeUTF(nodeId);
+      
+      out.writeUTF(queueName);
+      
+      out.writeUTF(condition);
+      
+      out.writeBoolean(noLocal);
+      
+      out.writeBoolean(active);
+      
+      writeString(selector, out);
+      
+      out.writeLong(channelId);
+      
+      out.writeBoolean(durable);
+   }
+   
+   private void writeString(String string, DataOutput out) throws IOException
+   {
+      if (string == null)
+      {
+         out.writeByte(NULL);
+      }
+      else
+      {
+         out.writeByte(NOT_NULL);
+         out.writeUTF(string);
+      }
+   }
+   
+   private String readString(DataInput in) throws IOException
+   {
+      byte b = in.readByte();
+      
+      if (b == NULL)
+      {
+         return null;
+      }
+      else
+      {
+         return in.readUTF();
+      }
+   }
+   
+}

Added: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/PostOfficeImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/PostOfficeImpl.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/PostOfficeImpl.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,613 @@
+/*
+ * 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.messaging.core.plugin.postoffice;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.sql.DataSource;
+import javax.transaction.TransactionManager;
+
+import org.jboss.logging.Logger;
+import org.jboss.messaging.core.Delivery;
+import org.jboss.messaging.core.MessageReference;
+import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.plugin.JDBCSupport;
+import org.jboss.messaging.core.plugin.contract.Binding;
+import org.jboss.messaging.core.plugin.contract.MessageStore;
+import org.jboss.messaging.core.plugin.contract.PostOffice;
+import org.jboss.messaging.core.tx.Transaction;
+
+import EDU.oswego.cs.dl.util.concurrent.ReadWriteLock;
+import EDU.oswego.cs.dl.util.concurrent.WriterPreferenceReadWriteLock;
+
+/**
+ * 
+ * A PostOfficeImpl
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class PostOfficeImpl extends JDBCSupport implements PostOffice
+{
+   private static final Logger log = Logger.getLogger(PostOfficeImpl.class);
+          
+   private String officeName;
+   
+   protected ReadWriteLock lock;
+   
+   protected MessageStore ms;     
+   
+   protected String nodeId;
+   
+   //Map <node id, Map < queue name, binding > >
+   protected Map nameMaps;
+   
+   //Map <condition, List <binding> >
+   protected Map conditionMap;
+     
+   public PostOfficeImpl()
+   {      
+   }
+   
+   public PostOfficeImpl(DataSource ds, TransactionManager tm, Properties sqlProperties,
+                           boolean createTablesOnStartup,
+                           String nodeId, String officeName, MessageStore ms)
+   {            
+      super (ds, tm, sqlProperties, createTablesOnStartup);
+      
+      lock = new WriterPreferenceReadWriteLock();
+      
+      nameMaps = new LinkedHashMap();
+       
+      conditionMap = new LinkedHashMap(); 
+      
+      this.nodeId = nodeId;
+      
+      this.officeName = officeName;
+      
+      this.ms = ms;
+   }
+   
+   // MessagingComponent implementation --------------------------------
+   
+   public void start() throws Exception
+   {
+      super.start();
+      
+      loadBindings();
+   }
+   
+   public void stop() throws Exception
+   {
+      super.stop();
+   }
+     
+   // Exchange implementation ---------------------------------------        
+         
+   public Binding bindQueue(String queueName, String condition, boolean noLocal,
+                            Queue queue) throws Exception
+   {
+      if (queueName == null)
+      {
+         throw new IllegalArgumentException("Queue name is null");
+      }
+      
+      if (condition == null)
+      {
+         throw new IllegalArgumentException("Condition is null");
+      }
+      
+      lock.writeLock().acquire();
+
+      try
+      {         
+         //We currently only allow one binding per name per node
+         Map nameMap = (Map)nameMaps.get(this.nodeId);
+         
+         Binding binding = null;
+         
+         if (nameMap != null)
+         {
+            binding = (Binding)nameMap.get(queueName);
+         }
+         
+         if (binding != null)
+         {
+            throw new IllegalArgumentException("Binding already exists for name " + queueName);
+         }
+         
+         boolean durable = queue.isRecoverable();
+         
+         String filter = queue.getFilter() == null ? null : queue.getFilter().getFilterString();
+                    
+         binding = new BindingImpl(nodeId, queueName, condition, filter,
+                                   noLocal, queue.getChannelID(), durable);         
+         
+         binding.setQueue(queue);
+         
+         binding.activate();
+         
+         addBinding(binding);
+               
+         if (durable)
+         {
+            //Need to write the binding to the db            
+            insertBinding(binding);       
+         }
+                           
+         return binding;   
+      }
+      finally
+      {
+         lock.writeLock().release();
+      }
+   }
+            
+   public Binding unbindQueue(String queueName) throws Throwable
+   {
+      if (queueName == null)
+      {
+         throw new IllegalArgumentException("Queue name is null");
+      }
+      
+      lock.writeLock().acquire();
+      
+      try
+      {         
+         Binding binding = removeBinding(this.nodeId, queueName);
+      
+         if (binding.isDurable())
+         {
+            //Need to remove from db too
+            
+            deleteBinding(binding.getQueueName());                        
+         }
+         
+         if (binding.getQueue() != null)
+         {
+            binding.getQueue().removeAllReferences();
+         }
+         
+         return binding;     
+      }
+      finally
+      {
+         lock.writeLock().release();
+      }
+   }   
+   
+   public List listBindingsForCondition(String condition) throws Exception
+   {
+      if (condition == null)
+      {
+         throw new IllegalArgumentException("Condition is null");
+      }
+      
+      lock.writeLock().acquire();
+      
+      try
+      {
+         return listMatchingBindings(condition);
+      }
+      finally
+      {
+         lock.writeLock().release();
+      }
+   }
+   
+   public Binding getBindingForQueueName(String queueName) throws Exception
+   {    
+      if (queueName == null)
+      {
+         throw new IllegalArgumentException("Queue name is null");
+      }
+      
+      lock.writeLock().acquire();
+      
+      try
+      {
+         Map nameMap = (Map)nameMaps.get(this.nodeId);
+         
+         Binding binding = null;
+         
+         if (nameMap != null)
+         {
+            binding = (Binding)nameMap.get(queueName);
+         }
+         
+         return binding;
+      }
+      finally
+      {
+         lock.writeLock().release();
+      }
+   }
+   
+   public void recover() throws Exception
+   {
+      //NOOP
+   }
+   
+   public boolean route(MessageReference ref, String condition, Transaction tx) throws Exception
+   {
+      if (ref == null)
+      {
+         throw new IllegalArgumentException("Message reference is null");
+      }
+      
+      if (condition == null)
+      {
+         throw new IllegalArgumentException("Condition key is null");
+      }
+      
+      boolean routed = false;
+      
+      lock.readLock().acquire();
+                
+      try
+      {                 
+         //We route on the condition
+         List bindings = (List)conditionMap.get(condition);
+           
+         if (bindings != null)
+         {            
+            Iterator iter = bindings.iterator();
+            
+            while (iter.hasNext())
+            {
+               Binding binding = (Binding)iter.next();
+                 
+               if (binding.isActive() && binding.getNodeId().equals(this.nodeId))
+               {
+                  //It's a local binding so we pass the message on to the subscription
+                  Queue subscription = binding.getQueue();
+               
+                  Delivery del = subscription.handle(null, ref, tx);
+                  
+                  if (del != null && del.isSelectorAccepted())
+                  {
+                     routed = true;
+                  }                  
+               }               
+            }                        
+         }
+                 
+         return routed;
+      }
+      finally
+      {                  
+         lock.readLock().release();
+      }
+   } 
+     
+   // Protected -----------------------------------------------------
+   
+   protected void loadBindings() throws Exception
+   {
+      lock.writeLock().acquire();
+      
+      try
+      {
+         List list = getBindings();
+         
+         Iterator iter = list.iterator();
+         
+         while (iter.hasNext())
+         {
+            Binding binding = (Binding)iter.next();
+            
+            addBinding(binding);              
+         }
+      }
+      finally
+      {
+         lock.writeLock().release();
+      }
+   }
+         
+   protected void insertBinding(Binding binding) throws Exception
+   {
+      Connection conn = null;
+      PreparedStatement ps  = null;     
+      TransactionWrapper wrap = new TransactionWrapper();
+      
+      try
+      {
+         conn = ds.getConnection();
+         
+         ps = conn.prepareStatement(getSQLStatement("INSERT_BINDING"));
+                  
+         ps.setString(1, this.officeName);
+         ps.setString(2, this.nodeId);
+         ps.setString(3, binding.getQueueName());
+         ps.setString(4, binding.getCondition());         
+         ps.setString(5, binding.getSelector());
+         ps.setString(6, binding.isNoLocal() ? "Y" : "N");
+         ps.setLong(7, binding.getChannelId());
+
+         ps.executeUpdate();;
+      }
+      finally
+      {
+         if (ps != null)
+         {
+            ps.close();
+         }
+         if (conn != null)
+         {
+            conn.close();
+         }
+         wrap.end();
+      }     
+   }
+   
+   protected boolean deleteBinding(String queueName) throws Exception
+   {
+      Connection conn = null;
+      PreparedStatement ps  = null;
+      TransactionWrapper wrap = new TransactionWrapper();
+      
+      try
+      {
+         conn = ds.getConnection();
+
+         ps = conn.prepareStatement(getSQLStatement("DELETE_BINDING"));
+         
+         ps.setString(1, this.officeName);
+         ps.setString(2, this.nodeId);
+         ps.setString(3, queueName);
+
+         int rows = ps.executeUpdate();
+         
+         return rows == 1;
+      }
+      finally
+      {
+         if (ps != null)
+         {
+            ps.close();
+         }
+         if (conn != null)
+         {
+            conn.close();
+         }
+         wrap.end();
+      }     
+   }
+
+   /*
+    * Note that we get all bindings irrespective of which node this represents.
+    * This is because persistent messages are always persisted in durable subscriptions on
+    * 
+    */
+   protected List getBindings() throws Exception
+   {
+      Connection conn = null;
+      PreparedStatement ps  = null;
+      ResultSet rs = null;
+      TransactionWrapper wrap = new TransactionWrapper();
+      
+      List list = new ArrayList();
+      
+      try
+      {
+         conn = ds.getConnection();
+         
+         ps = conn.prepareStatement(getSQLStatement("LOAD_BINDINGS"));
+                 
+         ps.setString(1, this.officeName);
+
+         rs = ps.executeQuery();
+              
+         while (rs.next())
+         {
+            String nodeId = rs.getString(1);
+            
+            String queueName = rs.getString(2);
+            
+            String condition = rs.getString(3);
+            
+            String selector = rs.getString(4);
+            
+            boolean noLocal = rs.getString(5).equals("Y");
+            
+            long channelId = rs.getLong(6);
+              
+            //We don't load the actual queue - this is because we don't know the paging params until
+            //activation time
+                    
+            Binding binding = new BindingImpl(nodeId, queueName, condition, selector, noLocal, channelId, true);
+            
+            list.add(binding);
+         }
+         
+         return list;
+      }
+      finally
+      {
+         if (rs != null)
+         {
+            rs.close();
+         }
+         if (ps != null)
+         {
+            ps.close();
+         }
+         if (conn != null)
+         {
+            conn.close();
+         }
+         wrap.end();
+      }     
+   }
+   
+   protected void addBinding(Binding binding)
+   {
+      Map nameMap = (Map)nameMaps.get(binding.getNodeId());
+      
+      if (nameMap == null)
+      {
+         nameMap = new LinkedHashMap();
+         
+         nameMaps.put(binding.getNodeId(), nameMap);
+      }
+      
+      nameMap.put(binding.getQueueName(), binding);
+      
+      String condition = binding.getCondition();
+            
+      List bindings = (List)conditionMap.get(condition);
+      
+      if (bindings == null)
+      {
+         bindings = new ArrayList();
+         
+         conditionMap.put(condition, bindings);
+      }
+      
+      bindings.add(binding);
+   }   
+   
+   protected Binding removeBinding(String nodeId, String queueName)
+   {
+      if (queueName == null)
+      {
+         throw new IllegalArgumentException("Queue name is null");
+      }
+             
+      Map nameMap = (Map)nameMaps.get(nodeId);
+      
+      if (nameMap == null)
+      {
+         throw new IllegalArgumentException("Cannot find any bindings for node Id: " + nodeId);
+      }
+      
+      Binding binding = null;            
+      
+      if (nameMap != null)
+      {
+         binding = (Binding)nameMap.remove(queueName);
+      }
+      
+      if (binding == null)
+      {
+         throw new IllegalArgumentException("Name map does not contain binding for " + queueName);
+      }
+              
+      if (nameMap.isEmpty())
+      {
+         nameMaps.remove(nodeId);
+      }
+                  
+      List bindings = (List)conditionMap.get(binding.getCondition());
+      
+      if (bindings == null)
+      {
+         throw new IllegalStateException("Cannot find condition bindings for " + binding.getCondition());
+      }
+      
+      boolean removed = bindings.remove(binding);
+      
+      if (!removed)
+      {
+         throw new IllegalStateException("Cannot find binding in condition binding list");
+      }
+      
+      if (binding == null)
+      {
+         throw new IllegalStateException("Channel id map does not contain binding for " + binding.getChannelId());
+      }
+      
+      if (!removed)
+      {
+         throw new IllegalStateException("Cannot find binding in condition binding list");
+      }
+      
+      if (bindings.isEmpty())
+      {
+         conditionMap.remove(binding.getCondition());
+      }        
+      
+      return binding;
+   }
+   
+   protected Map getDefaultDMLStatements()
+   {                
+      Map map = new HashMap();
+      map.put("INSERT_BINDING",
+               "INSERT INTO JMS_EXCHANGE_BINDING (EXCHANGE_NAME, NODE_ID, QUEUE_NAME, CONDITION, SELECTOR, NOLOCAL, CHANNEL_ID) " +
+               "VALUES (?, ?, ?, ?, ?, ?, ?)");
+      map.put("DELETE_BINDING",
+              "DELETE FROM JMS_EXCHANGE_BINDING WHERE EXCHANGE_NAME=? AND NODE_ID=? AND QUEUE_NAME=?");
+      map.put("LOAD_BINDINGS",
+              "SELECT NODE_ID, QUEUE_NAME, CONDITION, SELECTOR, NOLOCAL, CHANNEL_ID FROM JMS_EXCHANGE_BINDING " +
+              "WHERE EXCHANGE_NAME  = ?");
+      return map;
+   }
+   
+   protected Map getDefaultDDLStatements()
+   {
+      Map map = new HashMap();
+      map.put("CREATE_BINDING_TABLE",
+              "CREATE TABLE JMS_EXCHANGE_BINDING (EXCHANGE_NAME VARCHAR(256), NODE_ID VARCHAR(256)," +
+              "QUEUE_NAME VARCHAR(1024), CONDITION VARCHAR(1024), " +
+              "SELECTOR VARCHAR(1024), NOLOCAL CHAR(1), CHANNEL_ID BIGINT)");
+      return map;
+   }
+   
+   // Private -------------------------------------------------------             
+   
+   /*
+    * List all bindings whose condition matches the wildcard
+    * Initially we just do an exact match - when we support topic hierarchies this
+    * will change
+    */
+   private List listMatchingBindings(String wildcard)
+   {      
+      List list = (List)conditionMap.get(wildcard);
+      
+      if (list == null)
+      {
+         return Collections.EMPTY_LIST;
+      }
+      else
+      {
+         return list;
+      }
+   }
+  
+                  
+   // Inner classes -------------------------------------------------            
+}

Added: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/BindRequest.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/BindRequest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/BindRequest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,75 @@
+/*
+ * 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.messaging.core.plugin.postoffice.cluster;
+
+/**
+ * A BindRequest
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+class BindRequest implements ClusterRequest
+{
+   private static final long serialVersionUID = -2881616453863261327L;
+   
+   private String nodeId;   
+   
+   private String queueName;   
+   
+   private String condition;   
+   
+   private String filterString; 
+   
+   private boolean noLocal;   
+   
+   private long channelId;   
+   
+   private boolean durable;
+   
+   BindRequest(String nodeId, String queueName, String condition, String filterString,
+               boolean noLocal, long channelId, boolean durable)
+   {
+      this.nodeId = nodeId;
+      
+      this.queueName = queueName;
+      
+      this.condition = condition;
+      
+      this.filterString = filterString;
+      
+      this.noLocal = noLocal;
+      
+      this.channelId = channelId;
+      
+      this.durable = durable;
+   }
+
+   public void execute(ExchangeInternal exchange) throws Exception
+   {
+      exchange.addBindingFromCluster(nodeId, queueName, condition,
+                                     filterString, noLocal, channelId, durable);
+      
+   }
+}

Added: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/CastMessagesCallback.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/CastMessagesCallback.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/CastMessagesCallback.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,154 @@
+/*
+ * 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.messaging.core.plugin.postoffice.cluster;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jboss.messaging.core.Message;
+import org.jboss.messaging.core.tx.TxCallback;
+
+/**
+ * A CastMessageCallback
+ * 
+ * When we want to send persistent message(s) across the group to remote subscriptions
+ * and there is at least one remote durable subscription we do the following:
+ * 1) Cast the message(s) to group members. They are held in a "holding area" on the remote node
+ * and not immediately sent to the channels.
+ * 2) Persist the message(s) in the durable subscription(s) on the sending node.
+ * 3) Cast another message to the group members telling them to process the messages in the "holding" area
+ * for a particular transaction id
+ * This allows us to avoid an expensive 2PC protocol which involve extra database updates
+ * When the sending node starts up, it records a flag in the database, on clean shutdown it deletes the flag.
+ * If the server finds the flag in the database at start-up it knows it crashed the last time, so it
+ * sends a "check" message to all members of the group.
+ * On receipt of the "check" message, the receiving node checks in it's holding area for any holding messages for
+ * that node id, if they exist AND they also exist in the db (i.e. they were persisted ok) then they are processed
+ * otherwise they are discarded.
+ * 
+ * The execution order of callbacks must be as follows:
+ * 
+ * CastMessagesCallback.beforeCommit() - cast message(s) to holding areas
+ * JDBCPersistenceManager.TransactionCallback.beforeCommit() - persist message(s) in database
+ * CastMessagesCallback.afterCommit() - send "commit" message to holding areas
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+class CastMessagesCallback implements TxCallback
+{           
+   private List persistent;
+   
+   private List nonPersistent;
+   
+   private String nodeId;
+   
+   private long txId;
+   
+   private ExchangeInternal exchange;
+   
+   void addMessage(String routingKey, Message message)
+   {
+      MessageHolder holder = new MessageHolder(routingKey, message);
+      
+      if (message.isReliable())
+      {
+         if (persistent == null)
+         {
+            persistent = new ArrayList();
+         }
+         persistent.add(holder);
+      }
+      else
+      {
+         if (nonPersistent == null)
+         {
+            nonPersistent = new ArrayList();
+         }
+         nonPersistent.add(holder);
+      }
+   }
+   
+   CastMessagesCallback(String nodeId, long txId, ExchangeInternal exchange)
+   {
+      this.nodeId = nodeId;
+      
+      this.txId = txId;
+      
+      this.exchange = exchange;
+   }
+
+   public void afterCommit(boolean onePhase) throws Exception
+   {            
+      if (nonPersistent != null)
+      {
+         // Cast the non persistent - this don't need to go into a holding area on the receiving node
+         ClusterRequest req = new MessagesRequest(nonPersistent);
+         
+         exchange.asyncSendRequest(req);
+      }
+      
+      if (persistent != null)
+      {
+         // Cast a commit message
+         ClusterRequest req = new TransactionRequest(nodeId, txId);
+         
+         // Stack must be FIFO
+         exchange.asyncSendRequest(req);
+      }
+      
+      nonPersistent = persistent = null;
+   }
+
+   public void afterPrepare() throws Exception
+   { 
+   }
+
+   public void afterRollback(boolean onePhase) throws Exception
+   {
+   }
+
+   public void beforeCommit(boolean onePhase) throws Exception
+   {
+      if (persistent != null)
+      {
+         //We send the persistent messages which go into the "holding area" on
+         //the receiving nodes
+         ClusterRequest req = new TransactionRequest(nodeId, txId, persistent);
+         
+         //Stack must be FIFO
+         exchange.asyncSendRequest(req);
+      }
+   }
+
+   public void beforePrepare() throws Exception
+   {
+   }
+
+   public void beforeRollback(boolean onePhase) throws Exception
+   {
+   }
+      
+}    

Added: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/CheckMessage.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/CheckMessage.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/CheckMessage.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,48 @@
+/*
+ * 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.messaging.core.plugin.postoffice.cluster;
+
+/**
+ * A CheckMessage
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+class CheckMessage implements ClusterRequest
+{
+   private static final long serialVersionUID = 6254127318656179872L;
+   
+   private String nodeId;
+   
+   CheckMessage(String nodeId)
+   {
+      this.nodeId = nodeId;
+   }
+   
+   public void execute(ExchangeInternal exchange) throws Exception
+   {
+      exchange.check(nodeId);
+   }
+}

Added: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusterRequest.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusterRequest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusterRequest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,40 @@
+/*
+ * 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.messaging.core.plugin.postoffice.cluster;
+
+import java.io.Serializable;
+
+
+/**
+ * 
+ * A ClusterRequest
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+interface ClusterRequest extends Serializable
+{
+   void execute(ExchangeInternal exchange) throws Exception;
+}

Added: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredPostOfficeImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredPostOfficeImpl.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredPostOfficeImpl.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,1107 @@
+/*
+ * 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.messaging.core.plugin.postoffice.cluster;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.sql.DataSource;
+import javax.transaction.TransactionManager;
+
+import org.jboss.logging.Logger;
+import org.jboss.messaging.core.MessageReference;
+import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.plugin.contract.Binding;
+import org.jboss.messaging.core.plugin.contract.ClusteredPostOffice;
+import org.jboss.messaging.core.plugin.contract.MessageStore;
+import org.jboss.messaging.core.plugin.contract.PersistenceManager;
+import org.jboss.messaging.core.plugin.postoffice.PostOfficeImpl;
+import org.jboss.messaging.core.plugin.postoffice.BindingImpl;
+import org.jboss.messaging.core.tx.Transaction;
+import org.jboss.messaging.core.tx.TransactionRepository;
+import org.jgroups.Address;
+import org.jgroups.Channel;
+import org.jgroups.JChannel;
+import org.jgroups.MembershipListener;
+import org.jgroups.Message;
+import org.jgroups.MessageListener;
+import org.jgroups.Receiver;
+import org.jgroups.View;
+import org.jgroups.blocks.GroupRequest;
+import org.jgroups.blocks.MessageDispatcher;
+import org.jgroups.blocks.RequestHandler;
+import org.jgroups.util.Util;
+import org.w3c.dom.Element;
+
+/**
+ * 
+ * A ClusteredPostOfficeImpl
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class ClusteredPostOfficeImpl extends PostOfficeImpl implements ClusteredPostOffice, ExchangeInternal
+{
+   private static final Logger log = Logger.getLogger(ClusteredPostOfficeImpl.class);
+                       
+   private Channel syncChannel;
+   
+   private Channel asyncChannel;
+   
+   private String groupName;
+   
+   private MessageDispatcher controlMessageDispatcher;
+   
+   private MessageListener controlMessageListener;
+   
+   private Receiver dataReceiver;
+   
+   private MembershipListener controlMembershipListener;
+   
+   private RequestHandler requestHandler;
+   
+   private Object setStateLock = new Object();
+   
+   private boolean stateSet;
+   
+   private View currentView;
+   
+   //Map < Address, node id>
+   private Map nodeIdAddressMap;
+   
+   private Map holdingArea;
+   
+   private PersistenceManager pm;
+   
+   private TransactionRepository tr;  
+   
+   private Element syncChannelConfigE;
+   
+   private Element asyncChannelConfigE;
+   
+   private String syncChannelConfigS;
+   
+   private String asyncChannelConfigS;
+   
+   private long stateTimeout;
+   
+   private long castTimeout;
+      
+   public ClusteredPostOfficeImpl()
+   {        
+      init();
+   }
+   
+   private void init()
+   {
+      this.nodeIdAddressMap = new HashMap();
+      
+      this.holdingArea = new HashMap();
+   }
+   
+   /*
+    * Constructor using Element for configuration
+    */
+   public ClusteredPostOfficeImpl(DataSource ds, TransactionManager tm, Properties sqlProperties,
+                              boolean createTablesOnStartup,
+                              String nodeId, String officeName, MessageStore ms,
+                              String groupName,
+                              Element syncChannelConfig,
+                              Element asyncChannelConfig,
+                              TransactionRepository tr,
+                              PersistenceManager pm,
+                              long stateTimeout, long castTimeout) throws Exception
+   {            
+      this(ds, tm, sqlProperties, createTablesOnStartup, nodeId, officeName, ms,
+           groupName, tr, pm, stateTimeout, castTimeout);
+      
+      this.syncChannelConfigE = syncChannelConfig;      
+      this.asyncChannelConfigE = asyncChannelConfig;     
+   }
+     
+   /*
+    * Constructor using String for configuration
+    */
+   public ClusteredPostOfficeImpl(DataSource ds, TransactionManager tm, Properties sqlProperties,
+                              boolean createTablesOnStartup,
+                              String nodeId, String officeName, MessageStore ms,
+                              String groupName,
+                              String syncChannelConfig,
+                              String asyncChannelConfig,
+                              TransactionRepository tr,
+                              PersistenceManager pm,
+                              long stateTimeout, long castTimeout) throws Exception
+   {            
+      this(ds, tm, sqlProperties, createTablesOnStartup, nodeId, officeName, ms,
+           groupName, tr, pm, stateTimeout, castTimeout);
+
+      this.syncChannelConfigS = syncChannelConfig;      
+      this.asyncChannelConfigS = asyncChannelConfig;     
+   }
+   
+   private ClusteredPostOfficeImpl(DataSource ds, TransactionManager tm, Properties sqlProperties,
+                               boolean createTablesOnStartup,
+                               String nodeId, String officeName, MessageStore ms,
+                               String groupName,
+                               TransactionRepository tr,
+                               PersistenceManager pm,
+                               long stateTimeout, long castTimeout)
+   {
+      super (ds, tm, sqlProperties, createTablesOnStartup, nodeId, officeName, ms);
+       
+      this.tr = tr;
+      
+      this.pm = pm;
+      
+      this.groupName = groupName;
+      
+      this.stateTimeout = stateTimeout;
+      
+      this.castTimeout = castTimeout;
+      
+      init();
+   }
+
+   
+   public void start() throws Exception
+   {
+      if (syncChannelConfigE != null)
+      {        
+         this.syncChannel = new JChannel(syncChannelConfigE);
+         this.asyncChannel = new JChannel(asyncChannelConfigE); 
+      }
+      else
+      {
+         this.syncChannel = new JChannel(syncChannelConfigS);
+         this.asyncChannel = new JChannel(asyncChannelConfigS); 
+      }
+      
+      //We don't want to receive local messages on any of the channels
+      syncChannel.setOpt(Channel.LOCAL, Boolean.FALSE);
+      
+      asyncChannel.setOpt(Channel.LOCAL, Boolean.FALSE);
+      
+      this.controlMessageListener = new ControlMessageListener();
+      
+      this.requestHandler = new ExchangeRequestHandler();
+      
+      this.controlMembershipListener = new ControlMembershipListener();
+      
+      this.controlMessageDispatcher = new MessageDispatcher(syncChannel, controlMessageListener,
+                                                            controlMembershipListener, requestHandler, true);      
+      this.dataReceiver = new DataReceiver();
+      
+      asyncChannel.setReceiver(dataReceiver);    
+             
+      syncChannel.connect(groupName);
+      
+      asyncChannel.connect(groupName);
+      
+      super.start();
+      
+      Address currentAddress = syncChannel.getLocalAddress();
+             
+      handleAddressNodeMapping(currentAddress, nodeId);
+      
+      syncSendRequest(new SendNodeIdRequest(currentAddress, nodeId));
+   }
+
+   public void stop() throws Exception
+   {
+      super.stop();
+      
+      syncChannel.close();
+      
+      asyncChannel.close();
+   }  
+   
+   // PostOffice implementation ---------------------------------------        
+   
+   public Binding bindClusteredQueue(String queueName, String condition, boolean noLocal,
+                                     Queue queue) throws Exception
+   {           
+      Binding binding = super.bindQueue(queueName, condition, noLocal,
+                                        queue);
+      
+      boolean durable = queue.isRecoverable();
+      
+      String filter = queue.getFilter() == null ? null : queue.getFilter().getFilterString();
+      
+      BindRequest request =
+         new BindRequest(nodeId, queueName, condition, filter,
+                         noLocal, binding.getChannelId(), durable);
+      
+      syncSendRequest(request);
+      
+      return binding;
+   }
+   
+   public Binding unbindClusteredQueue(String queueName) throws Throwable
+   {
+      Binding binding = super.unbindQueue(queueName);
+      
+      UnbindRequest request = new UnbindRequest(nodeId, queueName);
+      
+      syncSendRequest(request);
+      
+      return binding;
+   }
+   
+   /*
+    * This is called by the server peer if it determines that the server crashed last time it was run
+    */
+   public void recover() throws Exception
+   {
+      //We send a "check" message to all nodes of the cluster
+      this.asyncSendRequest(new CheckMessage(nodeId));
+   }
+   
+   public boolean route(MessageReference ref, String condition, Transaction tx) throws Exception
+   {
+      if (ref == null)
+      {
+         throw new IllegalArgumentException("Message reference is null");
+      }
+      
+      if (condition == null)
+      {
+         throw new IllegalArgumentException("Condition is null");
+      }
+      
+      lock.readLock().acquire();
+      
+      try
+      {      
+         // We route on the condition
+         List bindings = (List)conditionMap.get(condition);
+      
+         if (bindings != null)
+         {                
+            // When routing a persistent message without a transaction then we may need to start an 
+            // internal transaction in order to route it.
+            // We do this if the message is reliable AND:
+            // (
+            // a) The message needs to be routed to more than one durable subscription. This is so we
+            // can guarantee the message is persisted on all the durable subscriptions or none if failure
+            // occurs - i.e. the persistence is transactional
+            // OR
+            // b) There is at least one durable subscription on a different node.
+            // In this case we need to start a transaction since we want to add a callback on the transaction
+            // to cast the message to other nodes
+            // )
+                        
+            //TODO we can optimise this out by storing this as a flag somewhere
+            boolean startInternalTx = false;
+      
+            if (tx == null)
+            {
+               if (ref.isReliable())
+               {
+                  Iterator iter = bindings.iterator();
+                  
+                  int count = 0;
+                  
+                  while (iter.hasNext())
+                  {
+                     Binding binding = (Binding)iter.next();
+                     
+                     if (binding.isDurable())
+                     {
+                        count++;
+                        
+                        if (count == 2 || !binding.getNodeId().equals(this.nodeId))
+                        {
+                           startInternalTx = true;
+                           
+                           break;
+                        }                          
+                     }
+                  }
+               }
+               
+               if (startInternalTx)
+               {
+                  tx = tr.createTransaction();
+               }
+            }
+                       
+            Iterator iter = bindings.iterator();
+            
+            boolean sendRemotely = false;
+
+            while (iter.hasNext())
+            {
+               Binding binding = (Binding)iter.next();
+               
+               if (binding.isActive())
+               {            
+                  if (binding.getNodeId().equals(this.nodeId))
+                  {
+                     //It's a local binding so we pass the message on to the subscription
+                     Queue subscription = binding.getQueue();
+                  
+                     subscription.handle(null, ref, tx);                    
+                  }
+                  else
+                  {
+                     //It's a binding on a different exchange instance on the cluster
+                     sendRemotely = true;                     
+                      
+                     if (ref.isReliable() && binding.isDurable())
+                     {
+                        //Insert the reference into the database
+                        pm.addReference(binding.getChannelId(), ref, tx);
+                     }
+                  }                     
+               }
+            } 
+            
+            //Now we've sent the message to all the local subscriptions, we might also need
+            //to multicast the message to the other exchange instances on the cluster if there are
+            //subscriptions on those nodes that need to receive the message
+            if (sendRemotely)
+            {
+               if (tx == null)
+               {
+                  //We just throw the message on the network - no need to wait for any reply            
+                  asyncSendRequest(new MessageRequest(condition, ref.getMessage()));               
+               }
+               else
+               {
+                  CastMessagesCallback callback = (CastMessagesCallback)tx.getCallback(this);
+                  
+                  if (callback == null)
+                  {
+                     callback = new CastMessagesCallback(nodeId, tx.getId(), ClusteredPostOfficeImpl.this);
+                     
+                     //This callback must be executed first
+                     tx.addFirstCallback(callback, this);
+                  }
+                      
+                  callback.addMessage(condition, ref.getMessage());                  
+               }
+            }
+            
+            if (startInternalTx)
+            {               
+               tx.commit();
+            }
+         }
+      }
+      finally
+      {                  
+         lock.readLock().release();
+      }
+         
+      // We don't care if the individual subscriptions accepted the reference
+      // We always return true
+      return true; 
+   }
+   
+   // ExchangeInternal implementation ------------------------------------------------------------------
+   
+   /*
+    * Called when another node adds a binding
+    */
+   public void addBindingFromCluster(String nodeId, String queueName, String condition,
+                                      String filterString, boolean noLocal, long channelID, boolean durable)
+      throws Exception
+   {
+      lock.writeLock().acquire();
+      
+      try
+      {                     
+         //Sanity
+         if (!nodeIdAddressMap.containsKey(nodeId))
+         {
+            throw new IllegalStateException("Cannot find address for node: " + nodeId);
+         }
+         
+         // We currently only allow one binding per name per node
+         Map nameMap = (Map)nameMaps.get(nodeId);
+         
+         Binding binding = null;
+         
+         if (nameMap != null)
+         {
+            binding = (Binding)nameMap.get(queueName);
+         }
+         
+         if (binding != null)
+         {
+            throw new IllegalArgumentException(this.nodeId + "Binding already exists for node Id " + nodeId + " queue name " + queueName);
+         }
+         
+         binding = new BindingImpl(nodeId, queueName, condition, filterString,
+                                     noLocal, channelID, durable); 
+         
+         binding.activate();
+         
+         addBinding(binding);         
+      }
+      finally
+      {
+         lock.writeLock().release();
+      }
+   }
+   
+   /*
+    * Called when another node removes a binding
+    */
+   public void removeBindingFromCluster(String nodeId, String queueName) throws Exception
+   {
+      lock.writeLock().acquire();
+      
+      try
+      {         
+         // Sanity
+         if (!nodeIdAddressMap.containsKey(nodeId))
+         {
+            throw new IllegalStateException("Cannot find address for node: " + nodeId);
+         }
+         
+         removeBinding(nodeId, queueName);         
+      }
+      finally
+      {
+         lock.writeLock().release();
+      }
+   }
+   
+   public void handleAddressNodeMapping(Address address, String nodeId) throws Exception
+   {
+      lock.writeLock().acquire();
+      
+      try
+      { 
+         nodeIdAddressMap.put(nodeId, address.toString());
+      }
+      finally
+      {
+         lock.writeLock().release();
+      }
+   }
+   
+   public void routeFromCluster(org.jboss.messaging.core.Message message, String routingKey) throws Exception
+   {
+      lock.readLock().acquire();      
+      
+      // Need to reference the message
+      MessageReference ref = null;
+      try
+      {
+         ref = ms.reference(message);
+              
+         // We route on the condition
+         List bindings = (List)conditionMap.get(routingKey);
+      
+         if (bindings != null)
+         {                                
+            Iterator iter = bindings.iterator();
+            
+            while (iter.hasNext())
+            {
+               Binding binding = (Binding)iter.next();
+               
+               if (binding.isActive())
+               {            
+                  if (binding.getNodeId().equals(this.nodeId))
+                  {  
+                     //It's a local binding so we pass the message on to the subscription
+                     Queue subscription = binding.getQueue();
+                  
+                     //TODO instead of adding a new method on the channel
+                     //we should set a header and use the same method
+                     subscription.handleDontPersist(null, ref, null);
+                  }                               
+               }
+            }                          
+         }
+      }
+      finally
+      {
+         if (ref != null)
+         {
+            ref.releaseMemoryReference();
+         }
+         lock.readLock().release();
+      }
+   }
+   
+   public void asyncSendRequest(ClusterRequest request) throws Exception
+   {            
+      //TODO - handle serialization more efficiently
+      asyncChannel.send(new Message(null, null, request));
+   }
+   
+   public void addToHoldingArea(TransactionId id, List messageHolders) throws Exception
+   {
+      synchronized (holdingArea)
+      {
+         holdingArea.put(id, messageHolders);
+      }      
+   }
+         
+   public void commitTransaction(TransactionId id) throws Exception
+   {
+      List messageHolders = null;
+      
+      synchronized (holdingArea)
+      {
+         messageHolders = (List)holdingArea.remove(id);
+      }
+      
+      if (messageHolders == null)
+      {
+         throw new IllegalStateException("Cannot find messages for transaction id: " + id);
+      }
+      
+      Iterator iter = messageHolders.iterator();
+      
+      while (iter.hasNext())
+      {
+         MessageHolder holder = (MessageHolder)iter.next();
+         
+         routeFromCluster(holder.getMessage(), holder.getRoutingKey());
+      }
+   }
+   
+   /*
+    * Called by a node if it starts and it detects that it crashed since it's last start-up.
+    * This method then checks to see if there any messages from that node in the holding area
+    * and if they are also in the database they will be processed
+    */
+   public void check(String nodeId) throws Exception
+   {
+      synchronized (holdingArea)
+      {
+         Iterator iter = holdingArea.entrySet().iterator();
+         
+         List toRemove = new ArrayList();
+         
+         while (iter.hasNext())
+         {
+            Map.Entry entry = (Map.Entry)iter.next();
+            
+            TransactionId id = (TransactionId)entry.getKey();
+            
+            if (id.getNodeId().equals(nodeId))
+            {
+               List holders = (List)entry.getValue();
+               
+               boolean wasCommitted = checkTransaction(holders);               
+               
+               if (wasCommitted)
+               {
+                  //We can process the transaction
+                  Iterator iter2 = holders.iterator();
+                  
+                  while (iter2.hasNext())
+                  {
+                     MessageHolder holder = (MessageHolder)iter2.next();
+                     
+                     routeFromCluster(holder.getMessage(), holder.getRoutingKey());
+                  }
+                  
+                  toRemove.add(id);
+               }
+            }
+         }
+         
+         //Remove the transactions from the holding area
+         
+         iter = toRemove.iterator();
+         
+         while (iter.hasNext())
+         {
+            TransactionId id = (TransactionId)iter.next();
+            
+            holdingArea.remove(id);
+         }
+      }
+   }
+   
+   private boolean checkTransaction(List messageHolders) throws Exception
+   {
+      Iterator iter = messageHolders.iterator();
+      
+      //We only need to check that one of the refs made it to the database - the refs would have
+      //been inserted into the db transactionally, so either they're all there or none are
+      MessageHolder holder = (MessageHolder)iter.next();
+      
+      List bindings = listBindingsForCondition(holder.getRoutingKey());
+      
+      if (bindings == null)
+      {
+         throw new IllegalStateException("Cannot find bindings for key: " + holder.getRoutingKey());
+      }
+      
+      Iterator iter2 = bindings.iterator();
+      
+      long channelID = -1;
+      boolean found = false;
+      
+      while (iter2.hasNext())
+      {
+         Binding binding = (Binding)iter2.next();
+         
+         if (binding.isDurable())
+         {
+            found = true;
+            
+            channelID = binding.getChannelId();
+         }
+      }
+      
+      if (!found)
+      {
+         throw new IllegalStateException("Cannot find bindings");
+      }
+      
+      if (pm.referenceExists(channelID, holder.getMessage().getMessageID()))
+      {
+         return true;
+      }
+      else
+      {
+         return false;
+      }
+   }
+   
+   //ExchangeSupport overrides -------------------------------------------------
+   
+   protected void loadBindings() throws Exception
+   {
+      // TODO I need to know whether this call times out - how do I know this??
+      boolean isState = syncChannel.getState(null, stateTimeout);
+                              
+      if (!isState)
+      {       
+         //Must be first member in group or non clustered- we load the state ourself from the database
+         super.loadBindings();      
+      }
+      else
+      {
+         //The state will be set in due course via the MessageListener - we must wait until this happens
+         
+         synchronized (setStateLock)
+         {
+            //TODO we should implement a timeout on this
+            while (!stateSet)
+            {
+               setStateLock.wait();
+            } 
+         }
+      }
+   }
+   
+   // Public ------------------------------------------------------------------------------------------
+   
+   
+   // Protected ---------------------------------------------------------------------------------------
+   
+   
+   protected void syncSendRequest(ClusterRequest request) throws Exception
+   {            
+      //TODO - handle serialization more efficiently
+      
+      Message message = new Message(null, null, request);      
+      
+      controlMessageDispatcher.castMessage(null, message, GroupRequest.GET_ALL, castTimeout);
+   }
+   
+   /*
+    * We have received a reference cast from another node - and we need to route it to our local
+    * subscriptions    
+    */
+   protected void routeFromCluster(MessageReference ref, String routingKey) throws Exception
+   {
+      lock.readLock().acquire();
+      
+      try
+      {      
+         // We route on the condition
+         List bindings = (List)conditionMap.get(routingKey);
+      
+         if (bindings != null)
+         {                                
+            Iterator iter = bindings.iterator();
+            
+            while (iter.hasNext())
+            {
+               Binding binding = (Binding)iter.next();
+               
+               if (binding.isActive())
+               {            
+                  if (binding.getNodeId().equals(this.nodeId))
+                  {  
+                     //It's a local binding so we pass the message on to the subscription
+                     Queue subscription = binding.getQueue();
+                  
+                     //TODO instead of adding a new method on the channel
+                     //we should set a header and use the same method
+                     subscription.handleDontPersist(null, ref, null);
+                  }                               
+               }
+            }                          
+         }
+      }
+      finally
+      {                  
+         lock.readLock().release();
+      }
+   }            
+       
+   // Private ------------------------------------------------------------------------------------------
+             
+   private void removeBindingsForAddress(String address) throws Exception
+   {
+      lock.writeLock().acquire();
+      
+      try
+      { 
+         Iterator iter = nodeIdAddressMap.entrySet().iterator();
+         
+         String nodeId = null;
+         while (iter.hasNext())
+         {
+            Map.Entry entry = (Map.Entry)iter.next();
+            
+            String str = (String)entry.getValue();
+            
+            if (str.equals(address))
+            {
+               nodeId = (String)entry.getKey();
+            }
+         }
+         
+         if (nodeId == null)
+         {
+            throw new IllegalStateException("Cannot find node id for address: " + address);
+         }
+         
+         Map nameMap = (Map)nameMaps.get(nodeId);
+
+         if (nameMap != null)
+         {
+            List toRemove = new ArrayList();
+            
+            iter = nameMap.values().iterator();
+            
+            while (iter.hasNext())
+            {
+               Binding binding = (Binding)iter.next();
+               
+               if (!binding.isDurable())
+               {
+                  toRemove.add(binding);
+               }
+            }
+            
+            iter = toRemove.iterator();
+            
+            while (iter.hasNext())
+            {
+               Binding binding = (Binding)iter.next();
+               
+               removeBinding(nodeId, binding.getQueueName());
+            }
+         }
+         
+         //Remove the address mapping
+         nodeIdAddressMap.remove(nodeId);
+      }
+      finally
+      {
+         lock.writeLock().release();
+      }
+   }
+      
+   //TODO - Sort out serialization properly
+   
+   private byte[] getStateAsBytes() throws Exception
+   {
+      List bindings = new ArrayList();
+      
+      Iterator iter = nameMaps.values().iterator();
+      
+      while (iter.hasNext())
+      {
+         Map map  = (Map)iter.next();
+         
+         Iterator iter2 = map.values().iterator();
+         
+         while (iter2.hasNext())
+         {
+            bindings.add(iter2.next());
+         }
+      }
+      
+      SharedState state = new SharedState(bindings, nodeIdAddressMap);
+      
+      byte[] bytes = Util.objectToByteBuffer(state);
+      
+      return bytes;
+   }
+   
+   private void processStateBytes(byte[] bytes) throws Exception
+   {
+      SharedState state = (SharedState)Util.objectFromByteBuffer(bytes);
+      
+      nameMaps.clear();
+      
+      conditionMap.clear();
+                 
+      List bindings = state.getBindings();
+      
+      Iterator iter = bindings.iterator();
+      
+      while (iter.hasNext())
+      {
+         Binding binding = (Binding)iter.next();
+         
+         addBinding(binding);
+      }
+      
+      this.nodeIdAddressMap.clear();
+      
+      this.nodeIdAddressMap.putAll(state.getNodeIdAddressMap());
+   }
+   
+   // Inner classes -------------------------------------------------------------------
+    
+   /*
+    * This class is used to manage state on the control channel
+    */
+   private class ControlMessageListener implements MessageListener
+   {
+      public byte[] getState()
+      {     
+         try
+         {
+            lock.writeLock().acquire();
+         }
+         catch (InterruptedException e)
+         {
+            log.error("Thread Interrupted", e);
+         }
+         try
+         {
+            return getStateAsBytes();
+         }
+         catch (Exception e)
+         {
+            IllegalStateException e2 = new IllegalStateException(e.getMessage());
+            e2.setStackTrace(e.getStackTrace());
+            throw e2;
+         }     
+         finally
+         {
+            lock.writeLock().release();
+         }
+      }
+      
+      public void receive(Message message)
+      {         
+         log.info("Received message on control channel: " + message);
+      }
+      
+      public void setState(byte[] bytes)
+      {
+         if (bytes != null)
+         {
+            
+            try
+            {
+               lock.writeLock().acquire();         
+            }
+            catch (InterruptedException e)
+            {
+               log.error("Thread interrupted", e);
+            }
+            try
+            {
+               processStateBytes(bytes);               
+            }
+            catch (Exception e)
+            {
+               IllegalStateException e2 = new IllegalStateException(e.getMessage());
+               e2.setStackTrace(e.getStackTrace());
+               throw e2;
+            }
+            finally
+            {
+               lock.writeLock().release();
+            }
+         }
+               
+         synchronized (setStateLock)
+         {
+            stateSet = true;
+            setStateLock.notify();
+         }
+      }      
+   }
+   
+   /*
+    * We use this class so we notice when members leave the group
+    */
+   private class ControlMembershipListener implements MembershipListener
+   {
+      public void block()
+      {
+         //NOOP
+      }
+
+      public void suspect(Address address)
+      {
+         //NOOP
+      }
+
+      public void viewAccepted(View view)
+      {
+         if (currentView != null)
+         {
+            Iterator iter = currentView.getMembers().iterator();
+            
+            while (iter.hasNext())
+            {
+               Address address = (Address)iter.next();
+               
+               if (!view.containsMember(address))
+               {
+                  //Member must have left                  
+                  //We don't remove bindings for ourself
+                  
+                  Address currentAddress = syncChannel.getLocalAddress();
+                  
+                  if (!address.equals(currentAddress))
+                  {                  
+                     try
+                     {
+                        removeBindingsForAddress(address.toString());
+                     }               
+                     catch (Exception e)
+                     {
+                        IllegalStateException e2 = new IllegalStateException(e.getMessage());
+                        e2.setStackTrace(e.getStackTrace());
+                        throw e2;
+                     }
+                  }
+               }
+            }
+         }
+         
+         currentView = view;
+      }
+
+      public byte[] getState()
+      {        
+         //NOOP
+         return null;
+      }     
+   }
+   
+   
+   /*
+    * This class is used to listen for messages on the data channel
+    */
+   private class DataReceiver implements Receiver
+   {
+      public void block()
+      {   
+         //NOOP
+      }
+
+      public void suspect(Address address)
+      { 
+         //NOOP
+      }
+
+      public void viewAccepted(View view)
+      { 
+         //NOOP
+      }
+
+      public byte[] getState()
+      {         
+         //NOOP
+         return null;
+      }
+      
+      public void receive(Message message)
+      {
+         try
+         {
+            //TODO handle deserialization more efficiently            
+            ClusterRequest request = (ClusterRequest)message.getObject();
+            
+            request.execute(ClusteredPostOfficeImpl.this);
+         }
+         catch (Exception e)
+         {
+            IllegalStateException e2 = new IllegalStateException(e.getMessage());
+            e2.setStackTrace(e.getStackTrace());
+            throw e2;
+         }         
+      }
+      
+      public void setState(byte[] bytes)
+      {
+         //NOOP         
+      }      
+   }
+          
+   /*
+    * This class is used to handle synchronous requests
+    */
+   private class ExchangeRequestHandler implements RequestHandler
+   {
+      public Object handle(Message message)
+      {
+         //TODO handle deserialization more efficiently
+         
+         log.info("REquest is: " + message.getObject());
+         
+         ClusterRequest request = (ClusterRequest)message.getObject();
+              
+         try
+         {            
+            request.execute(ClusteredPostOfficeImpl.this);
+         }
+         catch (Exception e)
+         {
+            IllegalStateException e2 = new IllegalStateException(e.getMessage());
+            e2.setStackTrace(e.getStackTrace());
+            throw e2;
+         }
+         return null;
+      }      
+   }   
+}
\ No newline at end of file

Added: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ExchangeInternal.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ExchangeInternal.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ExchangeInternal.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,59 @@
+/*
+ * 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.messaging.core.plugin.postoffice.cluster;
+
+import java.util.List;
+
+import org.jboss.messaging.core.Message;
+import org.jgroups.Address;
+
+/**
+ * A ExchangeInternal
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+interface ExchangeInternal
+{
+   void addBindingFromCluster(String nodeId, String queueName, String condition,
+                              String filterString, boolean noLocal, long channelId, boolean durable)
+      throws Exception;
+   
+   void removeBindingFromCluster(String nodeId, String queueName)
+      throws Exception;
+   
+   void handleAddressNodeMapping(Address address, String nodeId)
+      throws Exception;
+   
+   void routeFromCluster(Message message, String routingKey) throws Exception;
+   
+   void asyncSendRequest(ClusterRequest request) throws Exception;
+   
+   void addToHoldingArea(TransactionId id, List messageHolders) throws Exception;
+   
+   void commitTransaction(TransactionId id) throws Exception;
+   
+   void check(String nodeId) throws Exception;
+}

Added: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/MessageHolder.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/MessageHolder.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/MessageHolder.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,59 @@
+/*
+ * 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.messaging.core.plugin.postoffice.cluster;
+
+import java.io.Serializable;
+
+import org.jboss.messaging.core.Message;
+
+/**
+ * A MessageHolder
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+class MessageHolder implements Serializable
+{
+   String routingKey;
+   
+   Message message;
+   
+   MessageHolder(String routingKey, Message message)
+   {
+      this.routingKey = routingKey;
+      
+      this.message = message;
+   }
+   
+   String getRoutingKey()
+   {
+      return routingKey;
+   }
+   
+   Message getMessage()
+   {
+      return message;
+   }
+}     

Added: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/MessageRequest.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/MessageRequest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/MessageRequest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,56 @@
+/*
+ * 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.messaging.core.plugin.postoffice.cluster;
+
+import org.jboss.messaging.core.Message;
+
+/**
+ * A MessageRequest
+ * 
+ * Used when sending a single message non reliably across the group
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+class MessageRequest implements ClusterRequest
+{
+   private static final long serialVersionUID = 6681458404259394725L;
+   
+   private String routingKey;   
+   
+   private Message message;
+   
+   MessageRequest(String routingKey, Message message)
+   {
+      this.routingKey = routingKey;
+      
+      this.message = message;
+   }
+   
+   public void execute(ExchangeInternal exchange) throws Exception
+   {
+      exchange.routeFromCluster(message, routingKey);      
+   }   
+}

Added: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/MessagesRequest.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/MessagesRequest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/MessagesRequest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,61 @@
+/*
+ * 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.messaging.core.plugin.postoffice.cluster;
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * A MessagesRequest
+ * 
+ * Used when sending multiple messages non reliably across the group
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+class MessagesRequest implements ClusterRequest
+{
+   private static final long serialVersionUID = 3069447863470810127L;
+   
+   private List messageHolders;
+   
+   MessagesRequest(List messageHolders)
+   {
+      this.messageHolders = messageHolders;
+   }
+   
+   public void execute(ExchangeInternal exchange) throws Exception
+   {
+      Iterator iter = messageHolders.iterator();
+      
+      while (iter.hasNext())
+      {
+         MessageHolder holder = (MessageHolder)iter.next();
+         
+         exchange.routeFromCluster(holder.getMessage(), holder.getRoutingKey());
+      }
+   }   
+}
+

Added: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/SendNodeIdRequest.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/SendNodeIdRequest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/SendNodeIdRequest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,55 @@
+/*
+ * 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.messaging.core.plugin.postoffice.cluster;
+
+import org.jgroups.Address;
+
+/**
+ * A SendNodeIdRequest
+ * 
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+class SendNodeIdRequest implements ClusterRequest
+{
+   private static final long serialVersionUID = -3463428410402454526L;
+
+   private Address address;
+   
+   private String nodeId;
+   
+   SendNodeIdRequest(Address address, String nodeId)
+   {
+      this.address = address;
+      
+      this.nodeId = nodeId;      
+   }
+   
+   public void execute(ExchangeInternal exchange) throws Exception
+   {
+      exchange.handleAddressNodeMapping(address, nodeId);
+   }
+}

Added: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/SharedState.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/SharedState.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/SharedState.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,61 @@
+/*
+ * 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.messaging.core.plugin.postoffice.cluster;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A SharedState
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+class SharedState implements Serializable
+{
+   private static final long serialVersionUID = 7782131373080845107L;
+
+   private List bindings;
+   
+   private Map nodeIdAddressMap;
+   
+   SharedState(List bindings, Map nodeIdAddressMap)
+   {
+      this.bindings = bindings;
+      
+      this.nodeIdAddressMap = nodeIdAddressMap;
+   }
+   
+   List getBindings()
+   {
+      return bindings;
+   }
+   
+   Map getNodeIdAddressMap()
+   {
+      return nodeIdAddressMap;
+   }
+}

Added: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/TransactionId.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/TransactionId.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/TransactionId.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,95 @@
+/*
+ * 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.messaging.core.plugin.postoffice.cluster;
+
+/**
+ * A Transactionid
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+class TransactionId
+{
+   private String nodeId;
+   
+   private long txId;
+   
+   private int hash;
+   
+   TransactionId(String nodeId, long txId)
+   {
+      this.nodeId = nodeId;
+      
+      this.txId = txId;
+      
+      calculateHash();
+   }
+   
+   String getNodeId()
+   {
+      return nodeId;
+   }
+   
+   long getTxId()
+   {
+      return txId;
+   }
+   
+   public int hashCode()
+   {
+      return hash;
+   }
+   
+   public boolean equals(Object other)
+   {
+      if (other == this)
+      {
+         return true;
+      }
+      
+      if (!(other instanceof TransactionId))
+      {
+         return false;
+      }
+      
+      TransactionId tother = (TransactionId)other;
+      
+      return tother.txId == this.txId && tother.nodeId.equals(this.nodeId);
+   }
+   
+   public String toString()
+   {
+      return "TransactionId [" + System.identityHashCode(this) + "] nodeId: " + nodeId + " txId: " + txId;
+   }
+   
+   private void calculateHash()
+   {
+      hash = 17;
+      
+      hash = 37 * hash + (int)(txId ^ (txId >>> 32));
+      
+      hash = 37 * hash + nodeId.hashCode();
+   }
+}

Added: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/TransactionRequest.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/TransactionRequest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/TransactionRequest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,83 @@
+/*
+ * 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.messaging.core.plugin.postoffice.cluster;
+
+import java.util.List;
+
+/**
+ * A TransactionRequest
+ * 
+ * Used for sending persistent messages transactionally across the network
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+class TransactionRequest implements ClusterRequest
+{
+   private static final long serialVersionUID = 644500948910063649L;
+
+   private String nodeId;
+   
+   private long txId;
+ 
+   private List messageHolders;
+   
+   private boolean tryTransaction;
+      
+   TransactionRequest(String nodeId, long txId, List messageHolders)
+   {
+      this.nodeId = nodeId;
+      
+      this.txId= txId;
+
+      this.messageHolders = messageHolders;  
+      
+      tryTransaction = true;
+   }
+   
+   TransactionRequest(String nodeId, long txId)
+   {
+      this.nodeId = nodeId;
+      
+      this.txId= txId;
+      
+      tryTransaction = false;
+   }
+   
+   public void execute(ExchangeInternal exchange) throws Exception
+   {
+      TransactionId id = new TransactionId(nodeId, txId);
+      
+      if (tryTransaction)
+      {
+         exchange.addToHoldingArea(id, messageHolders);
+      }
+      else
+      {
+         exchange.commitTransaction(id);
+      }
+   }   
+}
+

Added: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/UnbindRequest.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/UnbindRequest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/UnbindRequest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,53 @@
+/*
+ * 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.messaging.core.plugin.postoffice.cluster;
+
+
+/**
+ * A UnbindRequest
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+class UnbindRequest implements ClusterRequest
+{
+   private static final long serialVersionUID = 6597644036507360965L;
+
+   private String nodeId;   
+   
+   private String queueName;
+
+   UnbindRequest(String nodeId, String queueName)
+   {
+      this.nodeId = nodeId;
+      
+      this.queueName = queueName;
+   }
+
+   public void execute(ExchangeInternal exchange) throws Exception
+   {
+      exchange.removeBindingFromCluster(nodeId, queueName);
+   }      
+}

Modified: trunk/src/main/org/jboss/messaging/core/tx/TransactionRepository.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/tx/TransactionRepository.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/src/main/org/jboss/messaging/core/tx/TransactionRepository.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -30,6 +30,7 @@
 
 import org.jboss.logging.Logger;
 import org.jboss.messaging.core.plugin.IdManager;
+import org.jboss.messaging.core.plugin.contract.MessagingComponent;
 import org.jboss.messaging.core.plugin.contract.PersistenceManager;
 
 import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap;
@@ -43,7 +44,7 @@
  *
  * $Id$
  */
-public class TransactionRepository
+public class TransactionRepository implements MessagingComponent
 {
    // Constants -----------------------------------------------------
 
@@ -63,19 +64,28 @@
    
    // Constructors --------------------------------------------------
    
-   public TransactionRepository() throws Exception
+   public TransactionRepository(PersistenceManager persistenceManager, IdManager idManager)
    {
+      this.persistenceManager = persistenceManager;
+      
+      this.idManager = idManager;
+   
       globalToLocalMap = new ConcurrentReaderHashMap();           
    }
    
-   // Public --------------------------------------------------------
+   // MessagingComponent implementation --------------------------------
    
-   public void injectAttributes(PersistenceManager persistenceManager, IdManager idManager)
+   public void start() throws Exception
    {
-      this.persistenceManager = persistenceManager;
-      
-      this.idManager = idManager;
+      //NOOP
    }
+   
+   public void stop() throws Exception
+   {
+      //NOOP
+   }
+   
+   // Public --------------------------------------------------------   
 
    public List getPreparedTransactions()
    {

Modified: trunk/tests/src/org/jboss/test/messaging/core/BrokenReceiver.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/BrokenReceiver.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/BrokenReceiver.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -22,23 +22,22 @@
 package org.jboss.test.messaging.core;
 
 
-import org.jboss.messaging.core.Receiver;
-import org.jboss.messaging.core.Routable;
+import java.util.ArrayList;
+import java.util.List;
+
 import org.jboss.messaging.core.Delivery;
 import org.jboss.messaging.core.DeliveryObserver;
-import org.jboss.messaging.core.SimpleDelivery;
 import org.jboss.messaging.core.MessageReference;
+import org.jboss.messaging.core.Receiver;
+import org.jboss.messaging.core.SimpleDelivery;
 import org.jboss.messaging.core.tx.Transaction;
-import org.jboss.logging.Logger;
 
-import java.util.List;
-import java.util.ArrayList;
 
-
 /**
  * A simple Receiver that "breaks" after the
  *
  * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
  * @version <tt>$Revision$</tt>
  *
  * $Id$
@@ -47,28 +46,26 @@
 {
    // Constants -----------------------------------------------------
 
-   private static final Logger log = Logger.getLogger(BrokenReceiver.class);
-
    // Static --------------------------------------------------------
 
    // Attributes ----------------------------------------------------
 
    private int counter;
    private int failurePoint;
-   private List messages;
+   private List refs;
 
 
    // Constructors --------------------------------------------------
 
    public BrokenReceiver(int failurePoint)
    {
-      messages = new ArrayList();
+      refs = new ArrayList();
       this.failurePoint = failurePoint;
    }
 
    // Receiver implementation ---------------------------------------
 
-   public Delivery handle(DeliveryObserver observer, Routable r, Transaction tx)
+   public Delivery handle(DeliveryObserver observer, MessageReference ref, Transaction tx)
    {
       counter++;
 
@@ -77,15 +74,15 @@
          throw new RuntimeException("I AM BROKEN!");
       }
 
-      messages.add(r);
-      return new SimpleDelivery(observer, (MessageReference)r, true);
+      refs.add(ref);
+      return new SimpleDelivery(observer, ref, true);
    }
 
    // Public --------------------------------------------------------
 
    public List getMessages()
    {
-      return messages;
+      return refs;
    }
 
    public String toString()

Modified: trunk/tests/src/org/jboss/test/messaging/core/SimpleChannel.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/SimpleChannel.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/SimpleChannel.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -16,8 +16,8 @@
 import org.jboss.messaging.core.Delivery;
 import org.jboss.messaging.core.DeliveryObserver;
 import org.jboss.messaging.core.Filter;
+import org.jboss.messaging.core.MessageReference;
 import org.jboss.messaging.core.Receiver;
-import org.jboss.messaging.core.Routable;
 import org.jboss.messaging.core.plugin.contract.MessageStore;
 import org.jboss.messaging.core.tx.Transaction;
 import org.jboss.messaging.util.NotYetImplementedException;
@@ -122,7 +122,7 @@
 
    // Receiver implementation ---------------------------------------
 
-   public Delivery handle(DeliveryObserver observer, Routable routable, Transaction tx)
+   public Delivery handle(DeliveryObserver observer, MessageReference ref, Transaction tx)
    {
       throw new NotYetImplementedException();
    }

Modified: trunk/tests/src/org/jboss/test/messaging/core/SimpleDeliveryTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/SimpleDeliveryTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/SimpleDeliveryTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -112,13 +112,13 @@
       sc.start();
       
       PersistenceManager pm =
-         new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager());
+         new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager(), null,
+                                    true, true, true, 100);      
+      pm.start();
       
-      ((JDBCPersistenceManager)pm).start();
+      TransactionRepository tr = new TransactionRepository(pm, new IdManager("TRANSACTION_ID", 10, pm));
+      tr.start();
       
-      TransactionRepository tr = new TransactionRepository();
-      tr.injectAttributes(pm, new IdManager("TRANSACTION_ID", 10, pm));
-      
       Transaction tx = tr.createTransaction();
       
       ((SimpleDelivery)delivery).acknowledge(tx);
@@ -126,6 +126,7 @@
       assertTrue(delivery.isDone());
       
       pm.stop();
+      tr.stop();
       
       sc.stop();
    }

Modified: trunk/tests/src/org/jboss/test/messaging/core/SimpleReceiver.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/SimpleReceiver.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/SimpleReceiver.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -118,15 +118,15 @@
 
    // Receiver implementation ---------------------------------------
 
-   public Delivery handle(DeliveryObserver observer, Routable r, Transaction tx)
+   public Delivery handle(DeliveryObserver observer, MessageReference ref, Transaction tx)
    {
-      log.info(this + " got routable:" + r);
+      log.info(this + " got routable:" + ref);
       
       try
       {
-         if (r == null)
+         if (ref == null)
          {
-            log.info("Receiver [" + name + "] is rejecting a null message");
+            log.info("Receiver [" + name + "] is rejecting a null reference");
             return null;
          }
          
@@ -139,7 +139,7 @@
          if (REJECTING.equals(state))
          {
 
-            log.info(this + " is rejecting message " + r);
+            log.info(this + " is rejecting reference " + ref);
             return null;
          }
 
@@ -153,9 +153,8 @@
         log.info("State is:" + state);
          
          boolean done = ACKING.equals(state) ? true : false;
-         log.info(this + " is " + (done ? "ACKing" : "NACKing") +  " message " + r);
+         log.info(this + " is " + (done ? "ACKing" : "NACKing") +  " message " + ref);
          
-         MessageReference ref = (MessageReference)r;
          Message m = ref.getMessage();
          
          SimpleDelivery delivery = new SimpleDelivery(observer, ref, done);

Deleted: trunk/tests/src/org/jboss/test/messaging/core/base/MessageQueueTestBase.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/base/MessageQueueTestBase.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/base/MessageQueueTestBase.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -1,6391 +0,0 @@
-/*
-* 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.test.messaging.core.base;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import javax.naming.InitialContext;
-
-import org.jboss.messaging.core.Channel;
-import org.jboss.messaging.core.Delivery;
-import org.jboss.messaging.core.Message;
-import org.jboss.messaging.core.MessageReference;
-import org.jboss.messaging.core.Receiver;
-import org.jboss.messaging.core.Routable;
-import org.jboss.messaging.core.message.MessageFactory;
-import org.jboss.messaging.core.plugin.IdManager;
-import org.jboss.messaging.core.plugin.JDBCPersistenceManager;
-import org.jboss.messaging.core.plugin.SimpleMessageStore;
-import org.jboss.messaging.core.plugin.contract.MessageStore;
-import org.jboss.messaging.core.plugin.contract.PersistenceManager;
-import org.jboss.messaging.core.tx.Transaction;
-import org.jboss.messaging.core.tx.TransactionRepository;
-import org.jboss.test.messaging.MessagingTestCase;
-import org.jboss.test.messaging.core.BrokenReceiver;
-import org.jboss.test.messaging.core.SimpleDeliveryObserver;
-import org.jboss.test.messaging.core.SimpleReceiver;
-import org.jboss.test.messaging.tools.jmx.ServiceContainer;
-
-/**
- * The MessageQueueTest test strategy is to try as many combination as it makes sense of the following
- * variables:
- *
- * 1. The MessageQueue can be non-recoverable  or
- *    recoverable. A non-recoverable channel can accept reliable messages or not.
- * 2. The MessageQueue may have zero or one receivers (the behavior for more than one receiver depends
- *    on the particular router implementation).
- * 3. The receiver may be ACKING or NACKING (the case when it throws unchecked exceptions is handled
- *    at the Router level).
- * 4. The sender can send message(s) non-transactionally or transactionally (and then can commit
- *    or rollback the transaction).
- * 5. The NACKING receiver can send acknowledgment(s) non-transactionally or transactionally (and
- *    then can commit or rollback the transaction).
- * 6. The message can be non-reliable or reliable.
- * 7. The sender can send one or multiple messages.
- * 8. A recoverable channel may be crashed and tested if it successfully recovers.
- *
- * This test base also tests the Distributor interface.
- *
- * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision: 1019 $</tt>
- *
- * $Id: ChannelTestBase.java 1019 2006-07-17 17:15:04Z timfox $
- */
-public abstract class MessageQueueTestBase extends MessagingTestCase
-{
-   // Constants -----------------------------------------------------
-
-   public static final int NUMBER_OF_MESSAGES = 10;
-
-   // Static --------------------------------------------------------
-   
-   // Attributes ----------------------------------------------------
-
-   protected PersistenceManager pm;
-   
-   protected TransactionRepository tr;
-   
-   protected MessageStore ms;
-   
-   protected ServiceContainer sc;
-
-   protected Channel messageQueue;
-
-
-   // Constructors --------------------------------------------------
-
-   public MessageQueueTestBase(String name)
-   {
-      super(name);
-   }
-
-   // Public --------------------------------------------------------
-
-   public void setUp() throws Exception
-   {
-      super.setUp();
-      
-      sc = new ServiceContainer("all,-remoting,-security");
-      sc.start();
-
-      InitialContext ic = new InitialContext();
-      tr = new TransactionRepository();
-      ic.close();
-
-      pm =
-         new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager());
-      
-      ((JDBCPersistenceManager)pm).start();
-      
-      IdManager idManager = new IdManager("TRANSACTION_ID", 10, pm);
-      
-      tr.injectAttributes(pm, idManager);
-      
-      ms = new SimpleMessageStore();
-
-   }
-
-   public void tearDown() throws Exception
-   {
-      sc.stop();
-      sc = null;
-      
-      ms = null;
-      tr = null;
-      super.tearDown();
-   }
-
-   public static void assertEqualSets(Routable[] a, List routables)
-   {
-      assertEquals(a.length, routables.size());
-      List l = new ArrayList(routables);
-
-      for(int i = 0; i < a.length; i++)
-      {
-         for(Iterator j = l.iterator(); j.hasNext(); )
-         {
-            Object o = j.next();
-            Message m = null;
-            if (o instanceof MessageReference)
-            {
-               MessageReference ref = (MessageReference)o;
-               m = ref.getMessage();
-            }
-            else
-            {
-               m = (Message)o;
-            }
-
-            if (a[i].getMessageID() == m.getMessageID() &&
-                (a[i] instanceof Message ? ((Message)a[i]).getPayload().equals(m.getPayload()) : true))
-            {
-               j.remove();
-               break;
-            }
-         }
-      }
-
-      if (!l.isEmpty())
-      {
-         fail("Messages " + l + " do not match!");
-      }
-   }
-
-   public static void assertEqualSets(Delivery[] a, List deliveries)
-   {
-      assertEquals(a.length, deliveries.size());
-      List l = new ArrayList(deliveries);
-
-      for(int i = 0; i < a.length; i++)
-      {
-         for(Iterator j = l.iterator(); j.hasNext(); )
-         {
-            Delivery d = (Delivery)j.next();
-            MessageReference ref = d.getReference();
-
-            if (a[i].getReference().getMessageID() == ref.getMessageID())
-            {
-               j.remove();
-               break;
-            }
-         }
-      }
-
-      if (!l.isEmpty())
-      {
-         fail("Deliveries " + l + " do not match!");
-      }
-   }
-
-
-   // Channel tests -------------------------------------------------
-   
-   public void testUnreliableSynchronousDeliveryTwoReceivers() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-      SimpleReceiver r1 = new SimpleReceiver("ONE", SimpleReceiver.ACKING);
-      SimpleReceiver r2 = new SimpleReceiver("TWO", SimpleReceiver.ACKING);
-      messageQueue.add(r1);
-      messageQueue.add(r2);
-
-      Delivery d = messageQueue.handle(observer, MessageFactory.createCoreMessage(0, false, "payload"), null);
-
-      assertTrue(d.isDone());
-      List l1 = r1.getMessages();
-      List l2 = r2.getMessages();
-      if (l2.isEmpty())
-      {
-         assertEquals(1, l1.size());
-         Message m = (Message)l1.get(0);
-         assertEquals("payload", m.getPayload());
-      }
-      else
-      {
-         assertTrue(l1.isEmpty());
-         assertEquals(1, l2.size());
-         Message m = (Message)l2.get(0);
-         assertEquals("payload", m.getPayload());
-      }
-   }
-
-
-   public void testReliableSynchronousDeliveryTwoReceivers() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-      SimpleReceiver r1 = new SimpleReceiver("ONE", SimpleReceiver.ACKING);
-      SimpleReceiver r2 = new SimpleReceiver("TWO", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r1));
-      assertTrue(messageQueue.add(r2));
-
-      Delivery d = messageQueue.handle(observer, MessageFactory.createCoreMessage(0, true, "payload"), null);
-
-      assertTrue(d.isDone());
-      List l1 = r1.getMessages();
-      List l2 = r2.getMessages();
-      if (l2.isEmpty())
-      {
-         assertEquals(1, l1.size());
-         Message m = (Message)l1.get(0);
-         assertEquals("payload", m.getPayload());
-      }
-      else
-      {
-         assertTrue(l1.isEmpty());
-         assertEquals(1, l2.size());
-         Message m = (Message)l2.get(0);
-         assertEquals("payload", m.getPayload());
-      }
-   }
-   
-   /*
-    * If a channel has a set a receiver and remove is called with a different receiver
-    * need to ensure the receiver is not removed (since it doesn't match)
-    */
-   public void testRemoveDifferentReceiver() throws Exception
-   {
-      Receiver receiver1 = new SimpleReceiver();
-      
-      Receiver receiver2 = new SimpleReceiver();
-      
-      assertFalse(messageQueue.iterator().hasNext());
-      
-      messageQueue.add(receiver1);
-      
-      assertTrue(messageQueue.contains(receiver1));
-      
-      messageQueue.remove(receiver1);
-      
-      assertFalse(messageQueue.iterator().hasNext());
-      
-      assertFalse(messageQueue.contains(receiver1));
-      
-      messageQueue.add(receiver1);
-      
-      assertTrue(messageQueue.contains(receiver1));
-      
-      messageQueue.remove(receiver2);
-      
-      assertTrue(messageQueue.contains(receiver1));
-                 
-   }
-
-   public void testClosedChannel() throws Exception
-   {
-      messageQueue.close();
-      try
-      {
-         messageQueue.handle(null, MessageFactory.createCoreMessage(0), null);
-         fail("should throw exception");
-      }
-      catch(IllegalStateException e)
-      {
-         //OK
-      }
-   }
-
-   public void testHandleNullRoutable() throws Exception
-   {
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-      assertNull(messageQueue.handle(observer, null, null));
-   }
-
-   //////////////////////////////////
-   ////////////////////////////////// Test matrix
-   //////////////////////////////////
-
-   //
-   // Non-recoverable channel
-   //
-
-   ////
-   //// Zero receivers
-   ////
-
-   //////
-   ////// Non-transacted send
-   //////
-
-   ////////
-   //////// Non-reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testNonRecoverableChannel_1() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, non-reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      assertTrue(delivery.isDone());
-
-      List stored = messageQueue.browse();
-      assertEquals(1, stored.size());
-
-      Message sm = (Message)stored.iterator().next();
-      assertFalse(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-
-      SimpleReceiver receiver = new SimpleReceiver("ACKING", SimpleReceiver.ACKING);
-      messageQueue.add(receiver);
-      messageQueue.deliver(true);
-      assertEquals(1, receiver.getMessages().size());
-      assertEquals(0, ((Message)receiver.getMessages().get(0)).getMessageID());
-
-      messageQueue.deliver(true);
-      assertEquals(1, receiver.getMessages().size());
-
-
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testNonRecoverableChannel_2() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, false, "payload" + i);
-
-         // non-transacted send, non-reliable message, multiple messages
-         Delivery delivery = messageQueue.handle(observer, messages[i], null);
-
-         assertTrue(delivery.isDone());
-      }
-
-      List stored = messageQueue.browse();
-      assertEqualSets(messages, stored);
-
-      SimpleReceiver receiver = new SimpleReceiver("ACKING", SimpleReceiver.ACKING);
-      messageQueue.add(receiver);
-      messageQueue.deliver(true);
-      assertEquals(10, receiver.getMessages().size());
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         assertEquals(i, ((Message)receiver.getMessages().get(i)).getMessageID());         
-      }
-      receiver.clear();
-
-      messageQueue.deliver(true);
-      assertEquals(0, receiver.getMessages().size());
-   }
-
-   ////////
-   //////// Reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   ///////////
-   /////////// Channel does NOT accept reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_3_1() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (messageQueue.acceptReliableMessages())
-      {
-         // we test channels that don't accept reliable messages
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      // the channel must not accept the message
-      assertNull(delivery);
-
-      assertTrue(messageQueue.browse().isEmpty());
-
-      messageQueue.deliver(true);
-      
-      Receiver r = new SimpleReceiver("ACKING", SimpleReceiver.ACKING);
-      
-      messageQueue.add(r);
-      
-      messageQueue.deliver(true);
-   }
-
-   ///////////
-   /////////// Channel accepts reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_3_2() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (!messageQueue.acceptReliableMessages())
-      {
-         // we test channels that accept reliable messages
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      assertTrue(delivery.isDone());
-
-      List stored = messageQueue.browse();
-      assertEquals(1, stored.size());
-
-      Message sm = (Message)stored.iterator().next();
-      assertTrue(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-
-      messageQueue.deliver(true);
-
-      SimpleReceiver receiver = new SimpleReceiver("ACKING", SimpleReceiver.ACKING);
-      messageQueue.add(receiver);
-      messageQueue.deliver(true);
-      assertEquals(1, receiver.getMessages().size());
-      assertEquals(0, ((Message)receiver.getMessages().get(0)).getMessageID());
-
-      messageQueue.deliver(true);
-      assertEquals(1, receiver.getMessages().size());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   ///////////
-   /////////// Channel does NOT accept reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_4_1() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (messageQueue.acceptReliableMessages())
-      {
-         // we test channels that don't accept reliable messages
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // non-transacted send, reliable message, multiple messages
-         Delivery delivery = messageQueue.handle(observer, messages[i], null);
-
-         // the channel must not accept the message
-         assertNull(delivery);
-
-         messageQueue.deliver(true);
-         
-         Receiver r = new SimpleReceiver("ACKING", SimpleReceiver.ACKING);
-         
-         messageQueue.add(r);
-         
-         messageQueue.deliver(true);
-      }
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-   ///////////
-   /////////// Channel accepts reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_4_2() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (!messageQueue.acceptReliableMessages())
-      {
-         // we test channels that accept reliable messages
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // non-transacted send, reliable message, multiple messages
-         Delivery delivery = messageQueue.handle(observer, messages[i], null);
-
-         assertTrue(delivery.isDone());
-      }
-
-      assertEqualSets(messages, messageQueue.browse());
-
-      SimpleReceiver receiver = new SimpleReceiver("ACKING", SimpleReceiver.ACKING);
-      messageQueue.add(receiver);
-      messageQueue.deliver(true);
-      assertEquals(10, receiver.getMessages().size());
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         assertEquals(i, ((Message)receiver.getMessages().get(i)).getMessageID());         
-      }
-      receiver.clear();
-
-      messageQueue.deliver(true);
-      assertEquals(0, receiver.getMessages().size());
-   }
-
-
-
-   //////
-   ////// Transacted send and commit
-   //////
-
-   ////////
-   //////// Non-reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testNonRecoverableChannel_5() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, non-reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      tx.commit();
-
-      List stored = messageQueue.browse();
-      assertEquals(1, stored.size());
-
-      Message sm = (Message)stored.iterator().next();
-      assertFalse(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-   }
-
-
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testNonRecoverableChannel_6() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, false, "payload" + i);
-
-         // transacted send, non-reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      tx.commit();
-
-      List stored = messageQueue.browse();
-      assertEqualSets(messages, stored);
-   }
-
-   ////////
-   //////// Reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   ///////////
-   /////////// Channel does NOT accept reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_7_1() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (messageQueue.acceptReliableMessages())
-      {
-         // we test channels that don't accept reliable messages
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      try
-      {
-         tx.commit();
-         fail("this should throw exception");
-      }
-      catch(Exception e)
-      {
-         // OK
-      }
-
-      // still no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-   }
-
-   ///////////
-   /////////// Channel accepts reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_7_2() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (!messageQueue.acceptReliableMessages())
-      {
-         // we test channels that don't accept reliable messages
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      tx.commit();
-
-      List stored = messageQueue.browse();
-      assertEquals(1, stored.size());
-
-      Message sm = (Message)stored.iterator().next();
-      assertTrue(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   ///////////
-   /////////// Channel does NOT accept reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_8_1() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (messageQueue.acceptReliableMessages())
-      {
-         // we test channels that don't accept reliable messages
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // transacted send, reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      try
-      {
-         tx.commit();
-         fail("this should throw exception");
-      }
-      catch(Exception e)
-      {
-         // OK
-      }
-
-      // still no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-   }
-
-   /**
-    * This is a variation where I send a mixture of reliable and non-reliable messages,
-    */
-   public void testNonRecoverableChannel_8_1_mixed() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (messageQueue.acceptReliableMessages())
-      {
-         // we test channels that don't accept reliable messages
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         // send a mixture of reliable and non-reliable messages
-         messages[i] = MessageFactory.createCoreMessage(i, (i % 2 == 1), "payload" + i);
-
-         // transacted send, reliable/non-reliable messages, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      try
-      {
-         tx.commit();
-         fail("this should throw exception");
-      }
-      catch(Exception e)
-      {
-         // OK
-      }
-
-      // still no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-   }
-   
-   public void testNonRecoverableChannel_8_1_mixed_1() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (messageQueue.acceptReliableMessages())
-      {
-         // we test channels that don't accept reliable messages
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES * 2];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         // send a mixture of reliable and non-reliable messages
-         messages[i] = MessageFactory.createCoreMessage(i, false, "payload" + i);
-
-         // transacted send, reliable/non-reliable messages, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         // send a mixture of reliable and non-reliable messages
-         messages[i + NUMBER_OF_MESSAGES] = MessageFactory.createCoreMessage(i + NUMBER_OF_MESSAGES , true, "payload" + i);
-
-         // transacted send, reliable/non-reliable messages, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i + NUMBER_OF_MESSAGES], tx);
-      }
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      try
-      {
-         tx.commit();
-         fail("this should throw exception");
-      }
-      catch(Exception e)
-      {
-         // OK
-      }
-
-      // still no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-   }
-   
-
-   public void testNonRecoverableChannel_8_1_mixed_2() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (messageQueue.acceptReliableMessages())
-      {
-         // we test channels that don't accept reliable messages
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES * 2];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         // send a mixture of reliable and non-reliable messages
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // transacted send, reliable/non-reliable messages, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         // send a mixture of reliable and non-reliable messages
-         messages[i + NUMBER_OF_MESSAGES] = MessageFactory.createCoreMessage(i + NUMBER_OF_MESSAGES , true, "payload" + i);
-
-         // transacted send, reliable/non-reliable messages, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i + NUMBER_OF_MESSAGES], tx);
-      }
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      try
-      {
-         tx.commit();
-         fail("this should throw exception");
-      }
-      catch(Exception e)
-      {
-         // OK
-      }
-
-      // still no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-   }
-
-   ///////////
-   /////////// Channel accepts reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_8_2() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (!messageQueue.acceptReliableMessages())
-      {
-         // we test channels that accept reliable messages
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // transacted send, reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      tx.commit();
-
-      assertEqualSets(messages, messageQueue.browse());
-   }
-
-   /**
-    * This is a variation where I send a mixture of reliable and non-reliable messages,
-    */
-   public void testNonRecoverableChannel_8_2_mixed() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (!messageQueue.acceptReliableMessages())
-      {
-         // we test channels that accept reliable messages
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         // send a mixture of reliable and non-reliable messages
-         messages[i] = MessageFactory.createCoreMessage(i, (i % 2 == 1), "payload" + i);
-
-         // transacted send, reliable/non-reliable messages, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      tx.commit();
-
-      assertEqualSets(messages, messageQueue.browse());
-   }
-
-
-   //////
-   ////// Transacted send and rollback
-   //////
-
-   ////////
-   //////// Non-reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testNonRecoverableChannel_9() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, non-reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      tx.rollback();
-
-      // still no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testNonRecoverableChannel_10() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, false, "payload" + i);
-
-         // transacted send, non-reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      tx.rollback();
-
-      // still no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-   }
-
-   ////////
-   //////// Reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testNonRecoverableChannel_11() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      tx.rollback();
-
-      // still no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testNonRecoverableChannel_12() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // transacted send, reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      tx.rollback();
-
-      // still no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-   }
-
-   /**
-    * This is a variation where I send a mixture of reliable and non-reliable messages,
-    */
-   public void testNonRecoverableChannel_12_mixed() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         // send a mixture of reliable and non-reliable messages
-         messages[i] = MessageFactory.createCoreMessage(i, (i % 2 == 1), "payload" + i);
-
-         // transacted send, reliable/non-reliable messages, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      tx.rollback();
-
-      // still no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-   }
-
-   ////
-   //// One receiver
-   ////
-
-   //////
-   ////// ACKING receiver
-   //////
-
-   //////
-   ////// Non-transacted send
-   //////
-
-   ////////
-   //////// Non-reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testNonRecoverableChannel_13() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, non-reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      assertTrue(delivery.isDone());
-      assertTrue(messageQueue.browse().isEmpty());
-
-      List received = r.getMessages();
-      assertEquals(1, received.size());
-      Message sm = (Message)received.iterator().next();
-      assertFalse(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testNonRecoverableChannel_14() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, false, "payload" + i);
-
-         // non-transacted send, non-reliable message, multiple messages
-         Delivery delivery = messageQueue.handle(observer, messages[i], null);
-
-         assertTrue(delivery.isDone());
-      }
-
-      assertTrue(messageQueue.browse().isEmpty());
-
-      List received = r.getMessages();
-      assertEqualSets(messages, received);
-   }
-
-   ////////
-   //////// Reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   ///////////
-   /////////// Channel does NOT accept reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_15_1() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (messageQueue.acceptReliableMessages())
-      {
-         // we test channels that don't accept reliable messages
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      assertNull(delivery);
-
-      assertTrue(messageQueue.browse().isEmpty());
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-   ///////////
-   /////////// Channel accepts reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_15_2() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (!messageQueue.acceptReliableMessages())
-      {
-         // we test channels that accept reliable messages
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      assertTrue(delivery.isDone());
-
-      assertTrue(messageQueue.browse().isEmpty());
-
-      List received = r.getMessages();
-      assertEquals(1, received.size());
-      Message sm = (Message)received.iterator().next();
-      assertTrue(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   ///////////
-   /////////// Channel does NOT accept reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_16_1() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (messageQueue.acceptReliableMessages())
-      {
-         // we test channels that don't accept reliable messages
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // non-transacted send, reliable message, multiple messages
-         Delivery delivery = messageQueue.handle(observer, messages[i], null);
-
-         assertNull(delivery);
-      }
-
-      assertTrue(messageQueue.browse().isEmpty());
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-   ///////////
-   /////////// Channel accepts reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_16_2() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (!messageQueue.acceptReliableMessages())
-      {
-         // we test channels that accept reliable messages
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // non-transacted send, reliable message, multiple messages
-         Delivery delivery = messageQueue.handle(observer, messages[i], null);
-
-         assertTrue(delivery.isDone());
-      }
-
-      assertTrue(messageQueue.browse().isEmpty());
-      assertEqualSets(messages, r.getMessages());
-   }
-
-   //////
-   ////// Transacted send and commit
-   //////
-
-   ////////
-   //////// Non-reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testNonRecoverableChannel_17() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, non-reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.commit();
-
-      assertTrue(messageQueue.browse().isEmpty());
-
-      List received = r.getMessages();
-      assertEquals(1, received.size());
-      Message sm = (Message)received.iterator().next();
-      assertFalse(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testNonRecoverableChannel_18() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, false, "payload" + i);
-
-         // transacted send, non-reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.commit();
-
-      assertTrue(messageQueue.browse().isEmpty());
-      assertEqualSets(messages, r.getMessages());
-   }
-
-   ////////
-   //////// Reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   ///////////
-   /////////// Channel does NOT accept reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_19_1() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (messageQueue.acceptReliableMessages())
-      {
-         // we test channels that don't accept reliable messages
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      try
-      {
-         tx.commit();
-         fail("this should throw exception");
-      }
-      catch(Exception e)
-      {
-         // OK
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-   ///////////
-   /////////// Channel accepts reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_19_2() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (!messageQueue.acceptReliableMessages())
-      {
-         // we test channels that accept reliable messages
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.commit();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      List received = r.getMessages();
-      assertEquals(1, received.size());
-      Message sm = (Message)received.iterator().next();
-      assertTrue(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   ///////////
-   /////////// Channel does NOT accept reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_20_1() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (messageQueue.acceptReliableMessages())
-      {
-         // we test channels that don't accept reliable messages
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // transacted send, reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      try
-      {
-         tx.commit();
-         fail("this should throw exception");
-      }
-      catch(Exception e)
-      {
-         // OK
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-   /**
-    * This is a variation where I send a mixture of reliable and non-reliable messages,
-    */
-   public void testNonRecoverableChannel_20_1_mixed() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (messageQueue.acceptReliableMessages())
-      {
-         // we test channels that don't accept reliable messages
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         // send a mixture of reliable and non-reliable messages
-         messages[i] = MessageFactory.createCoreMessage(i, (i % 2 == 1), "payload" + i);
-
-         // transacted send, reliable/non-reliable messages, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      try
-      {
-         tx.commit();
-         fail("this should throw exception");
-      }
-      catch(Exception e)
-      {
-         // OK
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-   ///////////
-   /////////// Channel accepts reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_20_2() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (!messageQueue.acceptReliableMessages())
-      {
-         // we test channels that accept reliable messages
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // transacted send, reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.commit();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      assertEqualSets(messages, r.getMessages());
-   }
-
-   /**
-    * This is a variation where I send a mixture of reliable and non-reliable messages,
-    */
-   public void testNonRecoverableChannel_20_2_mixed() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (!messageQueue.acceptReliableMessages())
-      {
-         // we test channels that accept reliable messages
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         // send a mixture of reliable and non-reliable messages
-         messages[i] = MessageFactory.createCoreMessage(i, (i % 2 == 1), "payload" + i);
-
-         // transacted send, reliable/non-reliable messages, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.commit();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      assertEqualSets(messages, r.getMessages());
-   }
-
-   //////
-   ////// Transacted send and rollback
-   //////
-
-   ////////
-   //////// Non-reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testNonRecoverableChannel_21() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, non-reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-
-      tx.rollback();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testNonRecoverableChannel_22() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, false, "payload" + i);
-
-         // transacted send, non-reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.rollback();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-   ////////
-   //////// Reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testNonRecoverableChannel_23() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.rollback();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testNonRecoverableChannel_24() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // transacted send, reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.rollback();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-   /**
-    * This is a variation where I send a mixture of reliable and non-reliable messages,
-    */
-   public void testNonRecoverableChannel_24_mixed() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         // send a mixture of reliable and non-reliable messages
-         messages[i] = MessageFactory.createCoreMessage(i, (i % 2 == 1), "payload" + i);
-
-         // transacted send, reliable/non-reliable messages, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.rollback();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-   //////
-   ////// NACKING receiver
-   //////
-
-   //////
-   ////// Non-transacted send
-   //////
-
-   ////////
-   //////// Non-reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   ////////////
-   //////////// Non-transacted acknowledgment
-   ////////////
-
-   public void testNonRecoverableChannel_25() throws Throwable
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, non-reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      assertTrue(delivery.isDone());
-
-      List delivering = messageQueue.browse();
-      assertEquals(1, delivering.size());
-      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
-
-      List acknowledging = r.getMessages();
-      assertEquals(1, acknowledging.size());
-      Message ackm = (Message)acknowledging.get(0);
-      assertEquals(0, ackm.getMessageID());
-
-      // non-transacted acknowledgment
-      r.acknowledge(ackm, null);
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-   /**
-    * The same test as before, but with a Receiver configured to acknowledge immediately
-    * on the Delivery. Simulates a race condition in which the acknoledgment arrives before
-    * the Delivery is returned to channel.
-    *
-    * @throws Throwable
-    */
-   public void testNonRecoverableChannel_25_race() throws Throwable
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      r.setImmediateAsynchronousAcknowledgment(true);
-      assertTrue(messageQueue.add(r));
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, non-reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      assertTrue(delivery.isDone());
-
-      // the receiver should have returned a "done" delivery
-      assertTrue(messageQueue.browse().isEmpty());
-
-      List messages = r.getMessages();
-      assertEquals(1, messages.size());
-      Message ackm = (Message)messages.get(0);
-      assertEquals(0, ackm.getMessageID());
-
-      // an extra acknowledgment should be discarded
-      r.acknowledge(ackm, null);
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-
-   ////////////
-   //////////// Transacted acknowledgment and commit
-   ////////////
-
-   public void testNonRecoverableChannel_25_1() throws Throwable
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, non-reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      assertTrue(delivery.isDone());
-
-      List delivering = messageQueue.browse();
-      assertEquals(1, delivering.size());
-      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
-
-      List acknowledging = r.getMessages();
-      assertEquals(1, acknowledging.size());
-      Message ackm = (Message)acknowledging.get(0);
-      assertEquals(0, ackm.getMessageID());
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted acknowledgment
-      r.acknowledge(ackm, tx);
-
-      delivering = messageQueue.browse();
-      assertEquals(1, delivering.size());
-      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
-
-      tx.commit();
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-
-   ////////////
-   //////////// Transacted acknowledgment and rollback
-   ////////////
-
-   public void testNonRecoverableChannel_25_2() throws Throwable
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, non-reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      assertTrue(delivery.isDone());
-
-      List delivering = messageQueue.browse();
-      assertEquals(1, delivering.size());
-      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
-
-      List acknowledging = r.getMessages();
-      assertEquals(1, acknowledging.size());
-      Message ackm = (Message)acknowledging.get(0);
-      assertEquals(0, ackm.getMessageID());
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted acknowledgment
-      r.acknowledge(ackm, tx);
-
-      delivering = messageQueue.browse();
-      assertEquals(1, delivering.size());
-      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
-
-      tx.rollback();
-
-      delivering = messageQueue.browse();
-      assertEquals(1, delivering.size());
-      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
-
-      // acknowledge non-transactionally
-      r.acknowledge(ackm, null);
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   ////////////
-   //////////// Non-transacted acknowledgment
-   ////////////
-
-   public void testNonRecoverableChannel_26() throws Throwable
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, false, "payload" + i);
-
-         // non-transacted send, non-reliable message, multiple messages
-         Delivery delivery = messageQueue.handle(observer, messages[i], null);
-
-         assertTrue(delivery.isDone());
-      }
-
-      assertEqualSets(messages, messageQueue.browse());
-      assertEqualSets(messages, r.getMessages());
-
-      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
-      {
-         Message ackm = (Message)i.next();
-         // non-transacted acknowledgment
-         r.acknowledge(ackm, null);
-      }
-
-      assertTrue(messageQueue.browse().isEmpty());
-
-   }
-
-   ////////////
-   //////////// Transacted acknowledgment and commit
-   ////////////
-
-   public void testNonRecoverableChannel_26_1() throws Throwable
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, false, "payload" + i);
-
-         // non-transacted send, non-reliable message, multiple messages
-         Delivery delivery = messageQueue.handle(observer, messages[i], null);
-
-         assertTrue(delivery.isDone());
-      }
-
-      assertEqualSets(messages, messageQueue.browse());
-      assertEqualSets(messages, r.getMessages());
-
-      Transaction tx = tr.createTransaction();
-
-      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
-      {
-         Message ackm = (Message)i.next();
-         // transacted acknowledgment
-         r.acknowledge(ackm, tx);
-      }
-
-      assertEqualSets(messages, messageQueue.browse());
-
-      tx.commit();
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-
-   ////////////
-   //////////// Transacted acknowledgment and rollback
-   ////////////
-
-   public void testNonRecoverableChannel_26_2() throws Throwable
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, false, "payload" + i);
-
-         // non-transacted send, non-reliable message, multiple messages
-         Delivery delivery = messageQueue.handle(observer, messages[i], null);
-
-         assertTrue(delivery.isDone());
-      }
-
-      assertEqualSets(messages, messageQueue.browse());
-      assertEqualSets(messages, r.getMessages());
-
-      Transaction tx = tr.createTransaction();
-
-      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
-      {
-         Message ackm = (Message)i.next();
-         // transacted acknowledgment
-         r.acknowledge(ackm, tx);
-      }
-
-      assertEqualSets(messages, messageQueue.browse());
-
-      tx.rollback();
-
-      assertEqualSets(messages, messageQueue.browse());
-
-      // acknowledge non-transactionally
-      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
-      {
-         Message ackm = (Message)i.next();
-         // non-transacted acknowledgment
-         r.acknowledge(ackm, null);
-      }
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-   ////////
-   //////// Reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   ////////////
-   //////////// Non-transacted acknowledgment
-   ////////////
-
-   ///////////
-   /////////// Channel does NOT accept reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_27_1_1() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (messageQueue.acceptReliableMessages())
-      {
-         // we test channels that don't accept reliable messages
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      // not accepted by the channel
-      assertNull(delivery);
-      assertTrue(messageQueue.browse().isEmpty());
-      assertTrue(r.getMessages().isEmpty());
-
-   }
-
-   ///////////
-   /////////// Channel accepts reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_27_1_2() throws Throwable
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (!messageQueue.acceptReliableMessages())
-      {
-         // we test channels that accept reliable messages
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      assertTrue(delivery.isDone());
-
-      List stored = messageQueue.browse();
-      assertEquals(1, stored.size());
-      Message sm = (Message)stored.iterator().next();
-      assertTrue(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-
-      List received = r.getMessages();
-      assertEquals(1, received.size());
-      Message rm = (Message)received.iterator().next();
-      assertTrue(rm.isReliable());
-      assertEquals(0, rm.getMessageID());
-
-      r.acknowledge(rm, null);
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-
-   ////////////
-   //////////// Transacted acknowledgment
-   ////////////
-
-   ///////////
-   /////////// Channel does NOT accept reliable messages
-   ///////////
-
-
-   // Doesn't make sense, the message won't be accepted anyway.
-
-   ///////////
-   /////////// Channel accepts reliable messages
-   ///////////
-
-
-   public void testNonRecoverableChannel_27_2_2() throws Throwable
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (!messageQueue.acceptReliableMessages())
-      {
-         // we test channels that accept reliable messages
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      assertTrue(delivery.isDone());
-
-      List stored = messageQueue.browse();
-      assertEquals(1, stored.size());
-      Message sm = (Message)stored.iterator().next();
-      assertTrue(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-
-      List received = r.getMessages();
-      assertEquals(1, received.size());
-      Message rm = (Message)received.iterator().next();
-      assertTrue(rm.isReliable());
-      assertEquals(0, rm.getMessageID());
-
-      Transaction tx = tr.createTransaction();
-
-      r.acknowledge(rm, tx);
-
-      stored = messageQueue.browse();
-      assertEquals(1, stored.size());
-      sm = (Message)stored.iterator().next();
-      assertTrue(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-
-      tx.commit();
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   ////////////
-   //////////// Non-transacted acknowledgment
-   ////////////
-
-   ///////////
-   /////////// Channel does NOT accept reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_28_1_1() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (messageQueue.acceptReliableMessages())
-      {
-         // we test channels that don't accept reliable messages
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // non-transacted send, reliable message, multiple messages
-         Delivery delivery = messageQueue.handle(observer, messages[i], null);
-
-         // not accepted by the channel
-         assertNull(delivery);
-      }
-
-      assertTrue(messageQueue.browse().isEmpty());
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-   ///////////
-   /////////// Channel accepts reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_28_1_2() throws Throwable
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (!messageQueue.acceptReliableMessages())
-      {
-         // we test channels that accept reliable messages
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // non-transacted send, reliable message, multiple messages
-         Delivery delivery = messageQueue.handle(observer, messages[i], null);
-
-         assertTrue(delivery.isDone());
-      }
-
-      assertEqualSets(messages, messageQueue.browse());
-      assertEqualSets(messages, r.getMessages());
-
-      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
-      {
-         Message ackm = (Message)i.next();
-         // non-transacted acknowledgment
-         r.acknowledge(ackm, null);
-      }
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-
-   ////////////
-   //////////// Transacted acknowledgment
-   ////////////
-
-   ///////////
-   /////////// Channel does NOT accept reliable messages
-   ///////////
-
-   // Doesn't make sense, the message won't be accepted anyway.
-
-   ///////////
-   /////////// Channel accepts reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_28_2_2() throws Throwable
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (!messageQueue.acceptReliableMessages())
-      {
-         // we test channels that accept reliable messages
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // non-transacted send, reliable message, multiple messages
-         Delivery delivery = messageQueue.handle(observer, messages[i], null);
-
-         assertTrue(delivery.isDone());
-      }
-
-      assertEqualSets(messages, messageQueue.browse());
-      assertEqualSets(messages, r.getMessages());
-
-      Transaction tx = tr.createTransaction();
-
-      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
-      {
-         Message ackm = (Message)i.next();
-         r.acknowledge(ackm, tx);
-      }
-
-      assertEqualSets(messages, messageQueue.browse());
-
-      tx.commit();
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-   //////
-   ////// Transacted send and commit
-   //////
-
-   ////////
-   //////// Non-reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testNonRecoverableChannel_29() throws Throwable
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, non-reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.commit();
-
-      List delivering = messageQueue.browse();
-      assertEquals(1, delivering.size());
-      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
-
-      List acknowledging = r.getMessages();
-      assertEquals(1, acknowledging.size());
-      Message ackm = (Message)acknowledging.get(0);
-      assertEquals(0, ackm.getMessageID());
-
-      // non-transacted acknowledgment
-      r.acknowledge(ackm, null);
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testNonRecoverableChannel_30() throws Throwable
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, false, "payload" + i);
-
-         // transacted send, non-reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.commit();
-
-      assertEqualSets(messages, messageQueue.browse());
-      assertEqualSets(messages, r.getMessages());
-
-      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
-      {
-         Message ackm = (Message)i.next();
-         // non-transacted acknowledgment
-         r.acknowledge(ackm, null);
-      }
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-   ////////
-   //////// Reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   ///////////
-   /////////// Channel does NOT accept reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_31_1() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (messageQueue.acceptReliableMessages())
-      {
-         // we test channels that don't accept reliable messages
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      try
-      {
-         tx.commit();
-         fail("this should throw exception");
-      }
-      catch(Exception e)
-      {
-         // OK
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-   ///////////
-   /////////// Channel does accepts reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_31_2() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (!messageQueue.acceptReliableMessages())
-      {
-         // we test channels that accept reliable messages
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.commit();
-
-      List stored = messageQueue.browse();
-      assertEquals(1, stored.size());
-      Message sm = (Message)stored.iterator().next();
-      assertTrue(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-
-      List received = r.getMessages();
-      assertEquals(1, received.size());
-      Message rm = (Message)received.iterator().next();
-      assertTrue(rm.isReliable());
-      assertEquals(0, rm.getMessageID());
-   }
-
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   ///////////
-   /////////// Channel does NOT accept reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_32_1() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (messageQueue.acceptReliableMessages())
-      {
-         // we test channels that don't accept reliable messages
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // transacted send, reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      try
-      {
-         tx.commit();
-         fail("this should throw exception");
-      }
-      catch(Exception e)
-      {
-         // OK
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-   /**
-    * This is a variation where I send a mixture of reliable and non-reliable messages,
-    */
-   public void testNonRecoverableChannel_32_1_mixed() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (messageQueue.acceptReliableMessages())
-      {
-         // we test channels that don't accept reliable messages
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         // send a mixture of reliable and non-reliable messages
-         messages[i] = MessageFactory.createCoreMessage(i, (i % 2 == 1), "payload" + i);
-
-         // transacted send, reliable/non-reliable messages, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      try
-      {
-         tx.commit();
-         fail("this should throw exception");
-      }
-      catch(Exception e)
-      {
-         // OK
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-   ///////////
-   /////////// Channel accepts reliable messages
-   ///////////
-
-   public void testNonRecoverableChannel_32_2() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (!messageQueue.acceptReliableMessages())
-      {
-         // we test channels that accept reliable messages
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // transacted send, reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.commit();
-
-      assertEqualSets(messages, messageQueue.browse());
-      assertEqualSets(messages, r.getMessages());
-   }
-
-   /**
-    * This is a variation where I send a mixture of reliable and non-reliable messages,
-    */
-   public void testNonRecoverableChannel_32_2_mixed() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      if (!messageQueue.acceptReliableMessages())
-      {
-         // we test channels that accept reliable messages
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         // send a mixture of reliable and non-reliable messages
-         messages[i] = MessageFactory.createCoreMessage(i, (i % 2 == 1), "payload" + i);
-
-         // transacted send, reliable/non-reliable messages, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.commit();
-
-      assertEqualSets(messages, messageQueue.browse());
-      assertEqualSets(messages, r.getMessages());
-   }
-
-
-
-   //////
-   ////// Transacted send and rollback
-   //////
-
-   ////////
-   //////// Non-reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testNonRecoverableChannel_33() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, non-reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-
-      tx.rollback();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testNonRecoverableChannel_34() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, false, "payload" + i);
-
-         // transacted send, non-reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.rollback();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-   ////////
-   //////// Reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testNonRecoverableChannel_35() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.rollback();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testNonRecoverableChannel_36() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // transacted send, reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.rollback();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-   /**
-    * This is a variation where I send a mixture of reliable and non-reliable messages,
-    */
-   public void testNonRecoverableChannel_36_mixed() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         // send a mixture of reliable and non-reliable messages
-         messages[i] = MessageFactory.createCoreMessage(i, (i % 2 == 1), "payload" + i);
-
-         // transacted send, reliable/non-reliable messages, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.rollback();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-
-
-
-   //
-   // Recoverable channel
-   //
-
-   public void testRecoverableChannel_0() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         assertTrue(messageQueue.acceptReliableMessages());
-      }
-   }
-
-   ////
-   //// Zero receivers
-   ////
-
-   //////
-   ////// Non-transacted send
-   //////
-
-   ////////
-   //////// Non-reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testRecoverableChannel_1() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, non-reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      assertTrue(delivery.isDone());
-
-      List stored = messageQueue.browse();
-      assertEquals(1, stored.size());
-
-      Message sm = (Message)stored.iterator().next();
-      assertFalse(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testRecoverableChannel_2() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, false, "payload" + i);
-
-         // non-transacted send, non-reliable message, multiple messages
-         Delivery delivery = messageQueue.handle(observer, messages[i], null);
-
-         assertTrue(delivery.isDone());
-      }
-
-      assertEqualSets(messages, messageQueue.browse());
-   }
-
-   ////////
-   //////// Reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testRecoverableChannel_3() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      assertTrue(delivery.isDone());
-
-      List stored = messageQueue.browse();
-      assertEquals(1, stored.size());
-
-      Message sm = (Message)stored.iterator().next();
-      assertTrue(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testRecoverableChannel_4() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // non-transacted send, reliable message, multiple messages
-         Delivery delivery = messageQueue.handle(observer, messages[i], null);
-
-         assertTrue(delivery.isDone());
-      }
-
-      assertEqualSets(messages, messageQueue.browse());
-
-   }
-
-   //////
-   ////// Transacted send and commit
-   //////
-
-   ////////
-   //////// Non-reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testRecoverableChannel_5() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, non-reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      tx.commit();
-
-      List stored = messageQueue.browse();
-      assertEquals(1, stored.size());
-
-      Message sm = (Message)stored.iterator().next();
-      assertFalse(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testRecoverableChannel_6() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, false, "payload" + i);
-
-         // transacted send, non-reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      tx.commit();
-
-      assertEqualSets(messages, messageQueue.browse());
-   }
-
-   ////////
-   //////// Reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testRecoverableChannel_7() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      tx.commit();
-
-      List stored = messageQueue.browse();
-      assertEquals(1, stored.size());
-
-      Message sm = (Message)stored.iterator().next();
-      assertTrue(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testRecoverableChannel_8() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // transacted send, reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      tx.commit();
-
-      assertEqualSets(messages, messageQueue.browse());
-   }
-
-   /**
-    * This is a variation where I send a mixture of reliable and non-reliable messages,
-    */
-   public void testRecoverableChannel_8_mixed() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         // send a mixture of reliable and non-reliable messages
-         messages[i] = MessageFactory.createCoreMessage(i, (i % 2 == 1), "payload" + i);
-
-         // transacted send, reliable/non-reliable messages, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      tx.commit();
-
-      assertEqualSets(messages, messageQueue.browse());
-   }
-
-
-   //////
-   ////// Transacted send and rollback
-   //////
-
-   ////////
-   //////// Non-reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testRecoverableChannel_9() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, non-reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      tx.rollback();
-
-      // still no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testRecoverableChannel_10() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, false, "payload" + i);
-
-         // transacted send, non-reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      tx.rollback();
-
-      // still no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-   }
-
-   ////////
-   //////// Reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testRecoverableChannel_11() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      tx.rollback();
-
-      // still no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testRecoverableChannel_12() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // transacted send, reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      tx.rollback();
-
-      // still no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-   }
-
-   /**
-    * This is a variation where I send a mixture of reliable and non-reliable messages,
-    */
-   public void testRecoverableChannel_12_mixed() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         // send a mixture of reliable and non-reliable messages
-         messages[i] = MessageFactory.createCoreMessage(i, (i % 2 == 1), "payload" + i);
-
-         // transacted send, reliable/non-reliable messages, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      tx.rollback();
-
-      // still no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-   }
-
-   ////
-   //// One receiver
-   ////
-
-   //////
-   ////// ACKING receiver
-   //////
-
-   //////
-   ////// Non-transacted send
-   //////
-
-   ////////
-   //////// Non-reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testRecoverableChannel_13() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, non-reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      assertTrue(delivery.isDone());
-      assertTrue(messageQueue.browse().isEmpty());
-
-      List received = r.getMessages();
-      assertEquals(1, received.size());
-      Message sm = (Message)received.iterator().next();
-      assertFalse(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testRecoverableChannel_14() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, false, "payload" + i);
-
-         // non-transacted send, non-reliable message, multiple messages
-         Delivery delivery = messageQueue.handle(observer, messages[i], null);
-
-         assertTrue(delivery.isDone());
-      }
-
-      assertTrue(messageQueue.browse().isEmpty());
-
-      List received = r.getMessages();
-      assertEqualSets(messages, received);
-   }
-
-   ////////
-   //////// Reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testRecoverableChannel_15() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      assertTrue(delivery.isDone());
-
-      assertTrue(messageQueue.browse().isEmpty());
-
-      List received = r.getMessages();
-      assertEquals(1, received.size());
-      Message sm = (Message)received.iterator().next();
-      assertTrue(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testRecoverableChannel_16() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // non-transacted send, reliable message, multiple messages
-         Delivery delivery = messageQueue.handle(observer, messages[i], null);
-
-         assertTrue(delivery.isDone());
-      }
-
-      assertTrue(messageQueue.browse().isEmpty());
-      assertEqualSets(messages, r.getMessages());
-   }
-
-   //////
-   ////// Transacted send and commit
-   //////
-
-   ////////
-   //////// Non-reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testRecoverableChannel_17() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, non-reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.commit();
-
-      assertTrue(messageQueue.browse().isEmpty());
-
-      List received = r.getMessages();
-      assertEquals(1, received.size());
-      Message sm = (Message)received.iterator().next();
-      assertFalse(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-   }
-
-
-   public void testRecoverableChannel_17_1() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      BrokenReceiver brokenReceiver = new BrokenReceiver(2);
-      assertTrue(messageQueue.add(brokenReceiver));
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-
-      log.debug("sending message 1");
-
-      // transacted send, non-reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      m = MessageFactory.createCoreMessage(1, false, "payload");
-
-      log.debug("sending message 2");
-      messageQueue.handle(observer, m, tx);
-
-      m = MessageFactory.createCoreMessage(2, false, "payload");
-
-      log.debug("sending message 3");
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      tx.commit();
-
-      assertEquals(2, messageQueue.browse().size());
-      assertEquals(1, brokenReceiver.getMessages().size());
-   }
-
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testRecoverableChannel_18() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, false, "payload" + i);
-
-         // transacted send, non-reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.commit();
-
-      assertTrue(messageQueue.browse().isEmpty());
-      assertEqualSets(messages, r.getMessages());
-   }
-
-   ////////
-   //////// Reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testRecoverableChannel_19() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.commit();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      List received = r.getMessages();
-      assertEquals(1, received.size());
-      Message sm = (Message)received.iterator().next();
-      assertTrue(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testRecoverableChannel_20() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // transacted send, reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.commit();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      assertEqualSets(messages, r.getMessages());
-   }
-
-   /**
-    * This is a variation where I send a mixture of reliable and non-reliable messages,
-    */
-   public void testRecoverableChannel_20_mixed() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         // send a mixture of reliable and non-reliable messages
-         messages[i] = MessageFactory.createCoreMessage(i, (i % 2 == 1), "payload" + i);
-
-         // transacted send, reliable/non-reliable messages, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.commit();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      assertEqualSets(messages, r.getMessages());
-   }
-
-
-   //////
-   ////// Transacted send and rollback
-   //////
-
-   ////////
-   //////// Non-reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testRecoverableChannel_21() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, non-reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-
-      tx.rollback();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testRecoverableChannel_22() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, false, "payload" + i);
-
-         // transacted send, non-reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.rollback();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-   ////////
-   //////// Reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testRecoverableChannel_23() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.rollback();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testRecoverableChannel_24() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // transacted send, reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.rollback();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-   /**
-    * This is a variation where I send a mixture of reliable and non-reliable messages,
-    */
-   public void testRecoverableChannel_24_mixed() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-
-      // add an ACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
-      assertTrue(messageQueue.add(r));
-
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         // send a mixture of reliable and non-reliable messages
-         messages[i] = MessageFactory.createCoreMessage(i, (i % 2 == 1), "payload" + i);
-
-         // transacted send, reliable/non-reliable messages, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.rollback();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-   //////
-   ////// NACKING receiver
-   //////
-
-   //////
-   ////// Non-transacted send
-   //////
-
-   ////////
-   //////// Non-reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   ////////////
-   //////////// Non-transacted acknowledgment
-   ////////////
-
-   public void testRecoverableChannel_25() throws Throwable
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, non-reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      assertTrue(delivery.isDone());
-
-      List delivering = messageQueue.browse();
-      assertEquals(1, delivering.size());
-      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
-
-      List acknowledging = r.getMessages();
-      assertEquals(1, acknowledging.size());
-      Message ackm = (Message)acknowledging.get(0);
-      assertEquals(0, ackm.getMessageID());
-
-      // non-transacted acknowledgment
-      r.acknowledge(ackm, null);
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-   /**
-    * The same test as before, but with a Receiver configured to acknowledge immediately
-    * on the Delivery. Simulates a race condition in which the acknoledgment arrives before
-    * the Delivery is returned to channel.
-    *
-    * @throws Throwable
-    */
-   public void testRecoverableChannel_25_race() throws Throwable
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      r.setImmediateAsynchronousAcknowledgment(true);
-      assertTrue(messageQueue.add(r));
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, non-reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      assertTrue(delivery.isDone());
-
-      // the receiver should have returned a "done" delivery
-      assertTrue(messageQueue.browse().isEmpty());
-
-      List messages = r.getMessages();
-      assertEquals(1, messages.size());
-      Message ackm = (Message)messages.get(0);
-      assertEquals(0, ackm.getMessageID());
-
-      // an extra acknowledgment should be discarded
-      r.acknowledge(ackm, null);
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-
-   ////////////
-   //////////// Transacted acknowledgment and commit
-   ////////////
-
-   public void testRecoverableChannel_25_1() throws Throwable
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, non-reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      assertTrue(delivery.isDone());
-
-      List delivering = messageQueue.browse();
-      assertEquals(1, delivering.size());
-      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
-
-      List acknowledging = r.getMessages();
-      assertEquals(1, acknowledging.size());
-      Message ackm = (Message)acknowledging.get(0);
-      assertEquals(0, ackm.getMessageID());
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted acknowledgment
-      r.acknowledge(ackm, tx);
-
-      delivering = messageQueue.browse();
-      assertEquals(1, delivering.size());
-      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
-
-      tx.commit();
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-
-   ////////////
-   //////////// Transacted acknowledgment and rollback
-   ////////////
-
-   public void testRecoverableChannel_25_2() throws Throwable
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, non-reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      assertTrue(delivery.isDone());
-
-      List delivering = messageQueue.browse();
-      assertEquals(1, delivering.size());
-      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
-
-      List acknowledging = r.getMessages();
-      assertEquals(1, acknowledging.size());
-      Message ackm = (Message)acknowledging.get(0);
-      assertEquals(0, ackm.getMessageID());
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted acknowledgment
-      r.acknowledge(ackm, tx);
-
-      delivering = messageQueue.browse();
-      assertEquals(1, delivering.size());
-      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
-
-      tx.rollback();
-
-      delivering = messageQueue.browse();
-      assertEquals(1, delivering.size());
-      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
-
-      // acknowledge non-transactionally
-      r.acknowledge(ackm, null);
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   ////////////
-   //////////// Non-transacted acknowledgment
-   ////////////
-
-   public void testRecoverableChannel_26() throws Throwable
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, false, "payload" + i);
-
-         // non-transacted send, non-reliable message, multiple messages
-         Delivery delivery = messageQueue.handle(observer, messages[i], null);
-
-         assertTrue(delivery.isDone());
-      }
-
-      assertEqualSets(messages, messageQueue.browse());
-      assertEqualSets(messages, r.getMessages());
-
-      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
-      {
-         Message ackm = (Message)i.next();
-         // non-transacted acknowledgment
-         r.acknowledge(ackm, null);
-      }
-
-      assertTrue(messageQueue.browse().isEmpty());
-
-   }
-
-   ////////////
-   //////////// Transacted acknowledgment and commit
-   ////////////
-
-   public void testRecoverableChannel_26_1() throws Throwable
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, false, "payload" + i);
-
-         // non-transacted send, non-reliable message, multiple messages
-         Delivery delivery = messageQueue.handle(observer, messages[i], null);
-
-         assertTrue(delivery.isDone());
-      }
-
-      assertEqualSets(messages, messageQueue.browse());
-      assertEqualSets(messages, r.getMessages());
-
-      Transaction tx = tr.createTransaction();
-
-      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
-      {
-         Message ackm = (Message)i.next();
-         // transacted acknowledgment
-         r.acknowledge(ackm, tx);
-      }
-
-      assertEqualSets(messages, messageQueue.browse());
-
-      tx.commit();
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-
-   ////////////
-   //////////// Transacted acknowledgment and rollback
-   ////////////
-
-   public void testRecoverableChannel_26_2() throws Throwable
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, false, "payload" + i);
-
-         // non-transacted send, non-reliable message, multiple messages
-         Delivery delivery = messageQueue.handle(observer, messages[i], null);
-
-         assertTrue(delivery.isDone());
-      }
-
-      assertEqualSets(messages, messageQueue.browse());
-      assertEqualSets(messages, r.getMessages());
-
-      Transaction tx = tr.createTransaction();
-
-      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
-      {
-         Message ackm = (Message)i.next();
-         // transacted acknowledgment
-         r.acknowledge(ackm, tx);
-      }
-
-      assertEqualSets(messages, messageQueue.browse());
-
-      tx.rollback();
-
-      assertEqualSets(messages, messageQueue.browse());
-
-      // acknowledge non-transactionally
-      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
-      {
-         Message ackm = (Message)i.next();
-         // non-transacted acknowledgment
-         r.acknowledge(ackm, null);
-      }
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-   ////////
-   //////// Reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   ////////////
-   //////////// Non-transacted acknowledgment
-   ////////////
-
-   public void testRecoverableChannel_27() throws Throwable
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      assertTrue(delivery.isDone());
-
-      List delivering = messageQueue.browse();
-      assertEquals(1, delivering.size());
-      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
-
-      List acknowledging = r.getMessages();
-      assertEquals(1, acknowledging.size());
-      Message ackm = (Message)acknowledging.get(0);
-      assertEquals(0, ackm.getMessageID());
-
-      // non-transacted acknowledgment
-      r.acknowledge(ackm, null);
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-   /**
-    * The same test as before, but with a Receiver configured to acknowledge immediately
-    * on the Delivery. Simulates a race condition in which the acknoledgment arrives before
-    * the Delivery is returned to channel.
-    *
-    * @throws Throwable
-    */
-   public void testRecoverableChannel_27_race() throws Throwable
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      r.setImmediateAsynchronousAcknowledgment(true);
-      assertTrue(messageQueue.add(r));
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      assertTrue(delivery.isDone());
-
-      // the receiver should have returned a "done" delivery
-      assertTrue(messageQueue.browse().isEmpty());
-
-      List messages = r.getMessages();
-      assertEquals(1, messages.size());
-      Message ackm = (Message)messages.get(0);
-      assertEquals(0, ackm.getMessageID());
-
-      // an extra acknowledgment should be discarded
-      
-      //TODO - why should it be discarded?
-      //If you acknowledge twice surely this is a usage error?
-      r.acknowledge(ackm, null);
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-
-   ////////////
-   //////////// Transacted acknowledgment and commit
-   ////////////
-
-   public void testRecoverableChannel_27_1() throws Throwable
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      assertTrue(delivery.isDone());
-
-      List delivering = messageQueue.browse();
-      assertEquals(1, delivering.size());
-      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
-
-      List acknowledging = r.getMessages();
-      assertEquals(1, acknowledging.size());
-      Message ackm = (Message)acknowledging.get(0);
-      assertEquals(0, ackm.getMessageID());
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted acknowledgment
-      r.acknowledge(ackm, tx);
-
-      delivering = messageQueue.browse();
-      assertEquals(1, delivering.size());
-      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
-
-      tx.commit();
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-
-   ////////////
-   //////////// Transacted acknowledgment and rollback
-   ////////////
-
-   public void testRecoverableChannel_27_2() throws Throwable
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-transacted send, reliable message, one message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-
-      assertTrue(delivery.isDone());
-
-      List delivering = messageQueue.browse();
-      assertEquals(1, delivering.size());
-      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
-
-      List acknowledging = r.getMessages();
-      assertEquals(1, acknowledging.size());
-      Message ackm = (Message)acknowledging.get(0);
-      assertEquals(0, ackm.getMessageID());
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted acknowledgment
-      r.acknowledge(ackm, tx);
-
-      delivering = messageQueue.browse();
-      assertEquals(1, delivering.size());
-      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
-
-      tx.rollback();
-
-      delivering = messageQueue.browse();
-      assertEquals(1, delivering.size());
-      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
-
-      // acknowledge non-transactionally
-      r.acknowledge(ackm, null);
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   ////////////
-   //////////// Non-transacted acknowledgment
-   ////////////
-
-   public void testRecoverableChannel_28() throws Throwable
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // non-transacted send, reliable message, multiple messages
-         Delivery delivery = messageQueue.handle(observer, messages[i], null);
-
-         assertTrue(delivery.isDone());
-      }
-
-      assertEqualSets(messages, messageQueue.browse());
-      assertEqualSets(messages, r.getMessages());
-
-      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
-      {
-         Message ackm = (Message)i.next();
-         // non-transacted acknowledgment
-         r.acknowledge(ackm, null);
-      }
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-   ////////////
-   //////////// Transacted acknowledgment and commit
-   ////////////
-
-   public void testRecoverableChannel_28_1() throws Throwable
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // non-transacted send, reliable message, multiple messages
-         Delivery delivery = messageQueue.handle(observer, messages[i], null);
-
-         assertTrue(delivery.isDone());
-      }
-
-      assertEqualSets(messages, messageQueue.browse());
-      assertEqualSets(messages, r.getMessages());
-
-      Transaction tx = tr.createTransaction();
-
-      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
-      {
-         Message ackm = (Message)i.next();
-         // transacted acknowledgment
-         r.acknowledge(ackm, tx);
-      }
-
-      assertEqualSets(messages, messageQueue.browse());
-
-      tx.commit();
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-   ////////////
-   //////////// Transacted acknowledgment and rollback
-   ////////////
-
-   public void testRecoverableChannel_28_2() throws Throwable
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // non-transacted send, reliable message, multiple messages
-         Delivery delivery = messageQueue.handle(observer, messages[i], null);
-
-         assertTrue(delivery.isDone());
-      }
-
-      assertEqualSets(messages, messageQueue.browse());
-      assertEqualSets(messages, r.getMessages());
-
-      Transaction tx = tr.createTransaction();
-
-      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
-      {
-         Message ackm = (Message)i.next();
-         // transacted acknowledgment
-         r.acknowledge(ackm, tx);
-      }
-
-      assertEqualSets(messages, messageQueue.browse());
-
-      tx.rollback();
-
-      assertEqualSets(messages, messageQueue.browse());
-
-      // acknowledge non-transactionally
-      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
-      {
-         Message ackm = (Message)i.next();
-         // non-transacted acknowledgment
-         r.acknowledge(ackm, null);
-      }
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-
-   //////
-   ////// Transacted send and commit
-   //////
-
-   ////////
-   //////// Non-reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testRecoverableChannel_29() throws Throwable
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, non-reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.commit();
-
-      List delivering = messageQueue.browse();
-      assertEquals(1, delivering.size());
-      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
-
-      List acknowledging = r.getMessages();
-      assertEquals(1, acknowledging.size());
-      Message ackm = (Message)acknowledging.get(0);
-      assertEquals(0, ackm.getMessageID());
-
-      // non-transacted acknowledgment
-      r.acknowledge(ackm, null);
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testRecoverableChannel_30() throws Throwable
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, false, "payload" + i);
-
-         // transacted send, non-reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.commit();
-
-      assertEqualSets(messages, messageQueue.browse());
-      assertEqualSets(messages, r.getMessages());
-
-      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
-      {
-         Message ackm = (Message)i.next();
-         // non-transacted acknowledgment
-         r.acknowledge(ackm, null);
-      }
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-   ////////
-   //////// Reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testRecoverableChannel_31() throws Throwable
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.commit();
-
-      List delivering = messageQueue.browse();
-      assertEquals(1, delivering.size());
-      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
-
-      List acknowledging = r.getMessages();
-      assertEquals(1, acknowledging.size());
-      Message ackm = (Message)acknowledging.get(0);
-      assertEquals(0, ackm.getMessageID());
-
-      // non-transacted acknowledgment
-      r.acknowledge(ackm, null);
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testRecoverableChannel_32() throws Throwable
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // transacted send, reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel yet
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.commit();
-
-      assertEqualSets(messages, messageQueue.browse());
-      assertEqualSets(messages, r.getMessages());
-
-      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
-      {
-         Message ackm = (Message)i.next();
-         // non-transacted acknowledgment
-         r.acknowledge(ackm, null);
-      }
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-   /**
-    * This is a variation where I send a mixture of reliable and non-reliable messages,
-    */
-   public void testRecoverableChannel_32_mixed() throws Throwable
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         // send a mixture of reliable and non-reliable messages
-         messages[i] = MessageFactory.createCoreMessage(i, (i % 2 == 1), "payload" + i);
-
-         // transacted send, reliable/non-reliable messages, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.commit();
-
-      assertEqualSets(messages, messageQueue.browse());
-      assertEqualSets(messages, r.getMessages());
-
-      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
-      {
-         Message ackm = (Message)i.next();
-         // non-transacted acknowledgment
-         r.acknowledge(ackm, null);
-      }
-
-      assertTrue(messageQueue.browse().isEmpty());
-   }
-
-
-   //////
-   ////// Transacted send and rollback
-   //////
-
-   ////////
-   //////// Non-reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testRecoverableChannel_33() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, non-reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-
-      tx.rollback();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testRecoverableChannel_34() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, false, "payload" + i);
-
-         // transacted send, non-reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.rollback();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-   ////////
-   //////// Reliable message
-   ////////
-
-   //////////
-   ////////// One message
-   //////////
-
-   public void testRecoverableChannel_35() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      // transacted send, reliable message, one message
-      // for a transactional send, handle() return value is unspecified
-      messageQueue.handle(observer, m, tx);
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.rollback();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-   //////////
-   ////////// Multiple message
-   //////////
-
-   public void testRecoverableChannel_36() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         messages[i] = MessageFactory.createCoreMessage(i, true, "payload" + i);
-
-         // transacted send, reliable message, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.rollback();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-   /**
-    * This is a variation where I send a mixture of reliable and non-reliable messages,
-    */
-   public void testRecoverableChannel_36_mixed() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // add an NACKING receiver to the channel
-      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
-      assertTrue(messageQueue.add(r));
-
-
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      Transaction tx = tr.createTransaction();
-
-      Message[] messages = new Message[NUMBER_OF_MESSAGES];
-      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
-      {
-         // send a mixture of reliable and non-reliable messages
-         messages[i] = MessageFactory.createCoreMessage(i, (i % 2 == 1), "payload" + i);
-
-         // transacted send, reliable/non-reliable messages, multiple messages
-         // for a transactional send, handle() return value is unspecified
-         messageQueue.handle(observer, messages[i], tx);
-      }
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-
-      tx.rollback();
-
-      // no messages in the channel
-      assertEquals(0, messageQueue.browse().size());
-
-      // no message at the receiver
-      assertTrue(r.getMessages().isEmpty());
-   }
-
-   ///////////////////////////////
-   /////////////////////////////// Add receiver tests
-   ///////////////////////////////
-   ///////////////////////////////
-   ///////////////////////////////
-
-   //
-   // Non-recoverable channel
-   //
-
-   ////
-   //// Non-reliable message
-   ////
-
-   //////
-   ////// Broken receiver
-   //////
-
-   public void testAddReceiver_1() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-recoverable channel, non-reliable message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-      assertTrue(delivery.isDone());
-
-      List stored = messageQueue.browse();
-      assertEquals(1, stored.size());
-
-
-      SimpleReceiver receiver = new SimpleReceiver("BrokenReceiver", SimpleReceiver.BROKEN);
-      assertTrue(messageQueue.add(receiver));
-
-      stored = messageQueue.browse();
-      assertEquals(1, stored.size());
-      Message sm = (Message)stored.iterator().next();
-      assertFalse(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-
-      assertTrue(receiver.getMessages().isEmpty());
-   }
-
-   //////
-   ////// ACKING receiver
-   //////
-
-   public void testAddReceiver_2() throws Exception
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-recoverable channel, non-reliable message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-      assertTrue(delivery.isDone());
-
-      List stored = messageQueue.browse();
-      assertEquals(1, stored.size());
-
-      SimpleReceiver receiver =
-            new SimpleReceiver("ACKINGReceiver", SimpleReceiver.ACKING, messageQueue);
-      assertTrue(messageQueue.add(receiver));
-
-      assertEquals(1, messageQueue.browse().size());
-
-      // receiver explicitely asks for message
-      receiver.requestMessages();
-
-      assertTrue(messageQueue.browse().isEmpty());
-
-      List messages = receiver.getMessages();
-      assertEquals(1, messages.size());
-      Message sm = (Message)messages.iterator().next();
-      assertFalse(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-   }
-
-   //////
-   ////// NACKING receiver
-   //////
-
-   public void testAddReceiver_3() throws Throwable
-   {
-      if (messageQueue.isRecoverable())
-      {
-         // we test only non-recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      Message m = MessageFactory.createCoreMessage(0, false, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-recoverable channel, non-reliable message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-      assertTrue(delivery.isDone());
-
-      List stored = messageQueue.browse();
-      assertEquals(1, stored.size());
-
-      SimpleReceiver receiver =
-            new SimpleReceiver("NACKINGReceiver", SimpleReceiver.ACCEPTING, messageQueue);
-      assertTrue(messageQueue.add(receiver));
-
-      assertEquals(1, messageQueue.browse().size());
-
-      // receiver explicitely asks for message
-      receiver.requestMessages();
-
-      assertEquals(1, messageQueue.browse().size());
-
-      List messages = receiver.getMessages();
-      assertEquals(1, messages.size());
-      Message sm = (Message)messages.iterator().next();
-      assertFalse(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-
-      receiver.acknowledge(sm, null);
-
-      assertTrue(messageQueue.browse().isEmpty());
-
-      messages = receiver.getMessages();
-      assertEquals(1, messages.size());
-      sm = (Message)messages.iterator().next();
-      assertFalse(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-   }
-
-   //
-   // Recoverable channel
-   //
-
-   ////
-   //// Reliable message
-   ////
-
-   public void testAddReceiver_4() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-recoverable channel, non-reliable message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-      assertTrue(delivery.isDone());
-
-      List stored = messageQueue.browse();
-      assertEquals(1, stored.size());
-
-
-      SimpleReceiver receiver = new SimpleReceiver("BrokenReceiver", SimpleReceiver.BROKEN);
-      assertTrue(messageQueue.add(receiver));
-
-      stored = messageQueue.browse();
-      assertEquals(1, stored.size());
-      Message sm = (Message)stored.iterator().next();
-      assertTrue(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-
-      assertTrue(receiver.getMessages().isEmpty());
-   }
-
-   //////
-   ////// ACKING receiver
-   //////
-
-   public void testAddReceiver_5() throws Exception
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-recoverable channel, non-reliable message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-      assertTrue(delivery.isDone());
-
-      List stored = messageQueue.browse();
-      assertEquals(1, stored.size());
-
-      SimpleReceiver receiver =
-            new SimpleReceiver("ACKINGReceiver", SimpleReceiver.ACKING, messageQueue);
-      assertTrue(messageQueue.add(receiver));
-
-      // receiver explicitely asks for message
-      receiver.requestMessages();
-
-      assertTrue(messageQueue.browse().isEmpty());
-
-      List messages = receiver.getMessages();
-      assertEquals(1, messages.size());
-      Message sm = (Message)messages.iterator().next();
-      assertTrue(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-   }
-
-   //////
-   ////// NACKING receiver
-   //////
-
-   public void testAddReceiver_6() throws Throwable
-   {
-      if (!messageQueue.isRecoverable())
-      {
-         // we test only recoverable channels now
-         return;
-      }
-
-      // the channel has no receivers
-      assertFalse(messageQueue.iterator().hasNext());
-
-      Message m = MessageFactory.createCoreMessage(0, true, "payload");
-      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-
-      // non-recoverable channel, non-reliable message
-      Delivery delivery = messageQueue.handle(observer, m, null);
-      assertTrue(delivery.isDone());
-
-      List stored = messageQueue.browse();
-      assertEquals(1, stored.size());
-
-      SimpleReceiver receiver =
-            new SimpleReceiver("NACKINGReceiver", SimpleReceiver.ACCEPTING, messageQueue);
-      assertTrue(messageQueue.add(receiver));
-
-      assertEquals(1, messageQueue.browse().size());
-
-      // receiver explicitely asks for message
-      receiver.requestMessages();
-
-      assertEquals(1, messageQueue.browse().size());
-
-      List messages = receiver.getMessages();
-      assertEquals(1, messages.size());
-      Message sm = (Message)messages.iterator().next();
-      assertTrue(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-
-      receiver.acknowledge(sm, null);
-
-      assertTrue(messageQueue.browse().isEmpty());
-
-      messages = receiver.getMessages();
-      assertEquals(1, messages.size());
-      sm = (Message)messages.iterator().next();
-      assertTrue(sm.isReliable());
-      assertEquals(0, sm.getMessageID());
-   }
-
-
-
-
-   ///////////////////////////////
-   /////////////////////////////// Channel crash tests
-   ///////////////////////////////
-
-//   public void testReliableChannelFailure() throws Throwable
-//   {
-//      if (!channel.isRecoverable())
-//      {
-//         return;
-//      }
-//
-//      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
-//      SimpleReceiver r = new SimpleReceiver("ONE", SimpleReceiver.NACKING);
-//      channel.add(r);
-//
-//      Routable m = Factory.createMessage("m0", true, "payload");
-//      Delivery d = channel.handle(observer, m, null);
-//      assertTrue(d.isDone());
-//
-//      List l = r.getMessages();
-//      assertEquals(1, l.size());
-//      Message rm  = (Message)l.get(0);
-//      assertEquals(rm.getMessageID(), m.getMessageID());
-//
-//      crashChannel();
-//
-//      recoverChannel();
-//
-//      // make sure the recovered channel still holds the message
-//
-//      l = channel.browse();
-//      assertEquals(1, l.size());
-//      MessageReference ref = (MessageReference)l.get(0);
-//      rm  = ref.getMessage();
-//      assertEquals(rm.getMessageID(), m.getMessageID());
-//
-//
-//      // TODO review this
-//      try
-//      {
-//         r.acknowledge(m, null);
-//         fail("should throw exception");
-//      }
-//      catch(IllegalStateException e)
-//      {
-//         // OK
-//      }
-//   }
-
-
-   // Distributor tests ---------------------------------------------
-
-   public void testAddOneReceiver()
-   {
-      Receiver r = new SimpleReceiver("ONE");
-
-      assertTrue(messageQueue.add(r));
-      assertFalse(messageQueue.add(r));
-
-      assertTrue(messageQueue.contains(r));
-
-      Iterator i = messageQueue.iterator();
-      assertEquals(r, i.next());
-      assertFalse(i.hasNext());
-
-      messageQueue.clear();
-      assertFalse(messageQueue.iterator().hasNext());
-   }
-
-   public void testRemoveInexistentReceiver()
-   {
-      assertFalse(messageQueue.remove(new SimpleReceiver("INEXISTENT")));
-   }
-
-
-   // Package protected ---------------------------------------------
-   
-   // Protected -----------------------------------------------------
-
-   protected abstract void crashChannel() throws Exception;
-
-   protected abstract void recoverChannel() throws Exception;
-
-   // Private -------------------------------------------------------
-   
-   // Inner classes -------------------------------------------------
-
-}

Copied: trunk/tests/src/org/jboss/test/messaging/core/base/QueueTestBase.java (from rev 1264, trunk/tests/src/org/jboss/test/messaging/core/base/MessageQueueTestBase.java)
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/base/MessageQueueTestBase.java	2006-09-06 04:04:35 UTC (rev 1264)
+++ trunk/tests/src/org/jboss/test/messaging/core/base/QueueTestBase.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,6385 @@
+/*
+* 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.test.messaging.core.base;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.jboss.messaging.core.Channel;
+import org.jboss.messaging.core.Delivery;
+import org.jboss.messaging.core.Message;
+import org.jboss.messaging.core.MessageReference;
+import org.jboss.messaging.core.Receiver;
+import org.jboss.messaging.core.plugin.IdManager;
+import org.jboss.messaging.core.plugin.JDBCPersistenceManager;
+import org.jboss.messaging.core.plugin.SimpleMessageStore;
+import org.jboss.messaging.core.plugin.contract.MessageStore;
+import org.jboss.messaging.core.plugin.contract.PersistenceManager;
+import org.jboss.messaging.core.tx.Transaction;
+import org.jboss.messaging.core.tx.TransactionRepository;
+import org.jboss.test.messaging.MessagingTestCase;
+import org.jboss.test.messaging.core.BrokenReceiver;
+import org.jboss.test.messaging.core.SimpleDeliveryObserver;
+import org.jboss.test.messaging.core.SimpleReceiver;
+import org.jboss.test.messaging.tools.jmx.ServiceContainer;
+
+/**
+ * The QueueTest test strategy is to try as many combination as it makes sense of the following
+ * variables:
+ *
+ * 1. The Queue can be non-recoverable  or
+ *    recoverable. A non-recoverable channel can accept reliable messages or not.
+ * 2. The Queue may have zero or one receivers (the behavior for more than one receiver depends
+ *    on the particular router implementation).
+ * 3. The receiver may be ACKING or NACKING (the case when it throws unchecked exceptions is handled
+ *    at the Router level).
+ * 4. The sender can send message(s) non-transactionally or transactionally (and then can commit
+ *    or rollback the transaction).
+ * 5. The NACKING receiver can send acknowledgment(s) non-transactionally or transactionally (and
+ *    then can commit or rollback the transaction).
+ * 6. The message can be non-reliable or reliable.
+ * 7. The sender can send one or multiple messages.
+ * 8. A recoverable channel may be crashed and tested if it successfully recovers.
+ *
+ * This test base also tests the Distributor interface.
+ *
+ * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1019 $</tt>
+ *
+ * $Id: ChannelTestBase.java 1019 2006-07-17 17:15:04Z timfox $
+ */
+public abstract class QueueTestBase extends MessagingTestCase
+{
+   // Constants -----------------------------------------------------
+
+   public static final int NUMBER_OF_MESSAGES = 10;
+
+   // Static --------------------------------------------------------
+   
+   // Attributes ----------------------------------------------------
+
+   protected PersistenceManager pm;
+   
+   protected TransactionRepository tr;
+   
+   protected MessageStore ms;
+   
+   protected ServiceContainer sc;
+
+   protected Channel queue;
+
+
+   // Constructors --------------------------------------------------
+
+   public QueueTestBase(String name)
+   {
+      super(name);
+   }
+
+   // Public --------------------------------------------------------
+
+   public void setUp() throws Exception
+   {
+      super.setUp();
+      
+      sc = new ServiceContainer("all,-remoting,-security");
+      sc.start();
+
+      pm =
+         new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager(), null,
+                                    true, true, true, 100);      
+      pm.start();
+      
+      tr = new TransactionRepository(pm, new IdManager("TRANSACTION_ID", 10, pm));
+      tr.start();
+      
+      ms = new SimpleMessageStore();
+      ms.start();
+   }
+
+   public void tearDown() throws Exception
+   {
+      sc.stop();
+      sc = null;
+      
+      ms = null;
+      tr = null;
+      super.tearDown();
+   }
+
+   public static void assertEqualSets(MessageReference[] a, List msgs)
+   {
+      assertEquals(a.length, msgs.size());
+      List l = new ArrayList(msgs);
+
+      for(int i = 0; i < a.length; i++)
+      {
+         for(Iterator j = l.iterator(); j.hasNext(); )
+         {
+            Object o = j.next();
+            Message m = (Message)o;
+            
+
+            if (a[i].getMessageID() == m.getMessageID() &&
+                m.getPayload().equals(a[i].getMessage().getPayload()))
+            {
+               j.remove();
+               break;
+            }
+         }
+      }
+
+      if (!l.isEmpty())
+      {
+         fail("Messages " + l + " do not match!");
+      }
+   }
+
+   public static void assertEqualSets(Delivery[] a, List deliveries)
+   {
+      assertEquals(a.length, deliveries.size());
+      List l = new ArrayList(deliveries);
+
+      for(int i = 0; i < a.length; i++)
+      {
+         for(Iterator j = l.iterator(); j.hasNext(); )
+         {
+            Delivery d = (Delivery)j.next();
+            MessageReference ref = d.getReference();
+
+            if (a[i].getReference().getMessageID() == ref.getMessageID())
+            {
+               j.remove();
+               break;
+            }
+         }
+      }
+
+      if (!l.isEmpty())
+      {
+         fail("Deliveries " + l + " do not match!");
+      }
+   }
+
+
+   // Channel tests -------------------------------------------------
+   
+   public void testUnreliableSynchronousDeliveryTwoReceivers() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+      SimpleReceiver r1 = new SimpleReceiver("ONE", SimpleReceiver.ACKING);
+      SimpleReceiver r2 = new SimpleReceiver("TWO", SimpleReceiver.ACKING);
+      queue.add(r1);
+      queue.add(r2);
+
+      Delivery d = queue.handle(observer, createReference(0, false, "payload"), null);
+
+      assertTrue(d.isDone());
+      List l1 = r1.getMessages();
+      List l2 = r2.getMessages();
+      if (l2.isEmpty())
+      {
+         assertEquals(1, l1.size());
+         Message m = (Message)l1.get(0);
+         assertEquals("payload", m.getPayload());
+      }
+      else
+      {
+         assertTrue(l1.isEmpty());
+         assertEquals(1, l2.size());
+         Message m = (Message)l2.get(0);
+         assertEquals("payload", m.getPayload());
+      }
+   }
+
+
+   public void testReliableSynchronousDeliveryTwoReceivers() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+      SimpleReceiver r1 = new SimpleReceiver("ONE", SimpleReceiver.ACKING);
+      SimpleReceiver r2 = new SimpleReceiver("TWO", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r1));
+      assertTrue(queue.add(r2));
+
+      Delivery d = queue.handle(observer, createReference(0, true, "payload"), null);
+
+      assertTrue(d.isDone());
+      List l1 = r1.getMessages();
+      List l2 = r2.getMessages();
+      if (l2.isEmpty())
+      {
+         assertEquals(1, l1.size());
+         Message m = (Message)l1.get(0);
+         assertEquals("payload", m.getPayload());
+      }
+      else
+      {
+         assertTrue(l1.isEmpty());
+         assertEquals(1, l2.size());
+         Message m = (Message)l2.get(0);
+         assertEquals("payload", m.getPayload());
+      }
+   }
+   
+   /*
+    * If a channel has a set a receiver and remove is called with a different receiver
+    * need to ensure the receiver is not removed (since it doesn't match)
+    */
+   public void testRemoveDifferentReceiver() throws Exception
+   {
+      Receiver receiver1 = new SimpleReceiver();
+      
+      Receiver receiver2 = new SimpleReceiver();
+      
+      assertFalse(queue.iterator().hasNext());
+      
+      queue.add(receiver1);
+      
+      assertTrue(queue.contains(receiver1));
+      
+      queue.remove(receiver1);
+      
+      assertFalse(queue.iterator().hasNext());
+      
+      assertFalse(queue.contains(receiver1));
+      
+      queue.add(receiver1);
+      
+      assertTrue(queue.contains(receiver1));
+      
+      queue.remove(receiver2);
+      
+      assertTrue(queue.contains(receiver1));
+                 
+   }
+
+   public void testClosedChannel() throws Exception
+   {
+      queue.close();
+      try
+      {
+         queue.handle(null, createReference(0), null);
+         fail("should throw exception");
+      }
+      catch(IllegalStateException e)
+      {
+         //OK
+      }
+   }
+
+   public void testHandleNullRoutable() throws Exception
+   {
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+      assertNull(queue.handle(observer, null, null));
+   }
+
+   //////////////////////////////////
+   ////////////////////////////////// Test matrix
+   //////////////////////////////////
+
+   //
+   // Non-recoverable channel
+   //
+
+   ////
+   //// Zero receivers
+   ////
+
+   //////
+   ////// Non-transacted send
+   //////
+
+   ////////
+   //////// Non-reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testNonRecoverableChannel_1() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, non-reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      assertTrue(delivery.isDone());
+
+      List stored = queue.browse();
+      assertEquals(1, stored.size());
+
+      Message sm = (Message)stored.iterator().next();
+      assertFalse(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+
+      SimpleReceiver receiver = new SimpleReceiver("ACKING", SimpleReceiver.ACKING);
+      queue.add(receiver);
+      queue.deliver(true);
+      assertEquals(1, receiver.getMessages().size());
+      assertEquals(0, ((Message)receiver.getMessages().get(0)).getMessageID());
+
+      queue.deliver(true);
+      assertEquals(1, receiver.getMessages().size());
+
+
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testNonRecoverableChannel_2() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, false, "payload" + i);
+
+         // non-transacted send, non-reliable message, multiple messages
+         Delivery delivery = queue.handle(observer, refs[i], null);
+
+         assertTrue(delivery.isDone());
+      }
+
+      List stored = queue.browse();
+      assertEqualSets(refs, stored);
+
+      SimpleReceiver receiver = new SimpleReceiver("ACKING", SimpleReceiver.ACKING);
+      queue.add(receiver);
+      queue.deliver(true);
+      assertEquals(10, receiver.getMessages().size());
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         assertEquals(i, ((Message)receiver.getMessages().get(i)).getMessageID());         
+      }
+      receiver.clear();
+
+      queue.deliver(true);
+      assertEquals(0, receiver.getMessages().size());
+   }
+
+   ////////
+   //////// Reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   ///////////
+   /////////// Channel does NOT accept reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_3_1() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (queue.acceptReliableMessages())
+      {
+         // we test channels that don't accept reliable messages
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      // the channel must not accept the message
+      assertNull(delivery);
+
+      assertTrue(queue.browse().isEmpty());
+
+      queue.deliver(true);
+      
+      Receiver r = new SimpleReceiver("ACKING", SimpleReceiver.ACKING);
+      
+      queue.add(r);
+      
+      queue.deliver(true);
+   }
+
+   ///////////
+   /////////// Channel accepts reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_3_2() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (!queue.acceptReliableMessages())
+      {
+         // we test channels that accept reliable messages
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      assertTrue(delivery.isDone());
+
+      List stored = queue.browse();
+      assertEquals(1, stored.size());
+
+      Message sm = (Message)stored.iterator().next();
+      assertTrue(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+
+      queue.deliver(true);
+
+      SimpleReceiver receiver = new SimpleReceiver("ACKING", SimpleReceiver.ACKING);
+      queue.add(receiver);
+      queue.deliver(true);
+      assertEquals(1, receiver.getMessages().size());
+      assertEquals(0, ((Message)receiver.getMessages().get(0)).getMessageID());
+
+      queue.deliver(true);
+      assertEquals(1, receiver.getMessages().size());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   ///////////
+   /////////// Channel does NOT accept reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_4_1() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (queue.acceptReliableMessages())
+      {
+         // we test channels that don't accept reliable messages
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // non-transacted send, reliable message, multiple messages
+         Delivery delivery = queue.handle(observer, refs[i], null);
+
+         // the channel must not accept the message
+         assertNull(delivery);
+
+         queue.deliver(true);
+         
+         Receiver r = new SimpleReceiver("ACKING", SimpleReceiver.ACKING);
+         
+         queue.add(r);
+         
+         queue.deliver(true);
+      }
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+   ///////////
+   /////////// Channel accepts reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_4_2() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (!queue.acceptReliableMessages())
+      {
+         // we test channels that accept reliable messages
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // non-transacted send, reliable message, multiple messages
+         Delivery delivery = queue.handle(observer, refs[i], null);
+
+         assertTrue(delivery.isDone());
+      }
+
+      assertEqualSets(refs, queue.browse());
+
+      SimpleReceiver receiver = new SimpleReceiver("ACKING", SimpleReceiver.ACKING);
+      queue.add(receiver);
+      queue.deliver(true);
+      assertEquals(10, receiver.getMessages().size());
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         assertEquals(i, ((Message)receiver.getMessages().get(i)).getMessageID());         
+      }
+      receiver.clear();
+
+      queue.deliver(true);
+      assertEquals(0, receiver.getMessages().size());
+   }
+
+
+
+   //////
+   ////// Transacted send and commit
+   //////
+
+   ////////
+   //////// Non-reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testNonRecoverableChannel_5() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, non-reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      tx.commit();
+
+      List stored = queue.browse();
+      assertEquals(1, stored.size());
+
+      Message sm = (Message)stored.iterator().next();
+      assertFalse(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+   }
+
+
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testNonRecoverableChannel_6() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, false, "payload" + i);
+
+         // transacted send, non-reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      tx.commit();
+
+      List stored = queue.browse();
+      assertEqualSets(refs, stored);
+   }
+
+   ////////
+   //////// Reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   ///////////
+   /////////// Channel does NOT accept reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_7_1() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (queue.acceptReliableMessages())
+      {
+         // we test channels that don't accept reliable messages
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      try
+      {
+         tx.commit();
+         fail("this should throw exception");
+      }
+      catch(Exception e)
+      {
+         // OK
+      }
+
+      // still no messages in the channel
+      assertEquals(0, queue.browse().size());
+   }
+
+   ///////////
+   /////////// Channel accepts reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_7_2() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (!queue.acceptReliableMessages())
+      {
+         // we test channels that don't accept reliable messages
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      tx.commit();
+
+      List stored = queue.browse();
+      assertEquals(1, stored.size());
+
+      Message sm = (Message)stored.iterator().next();
+      assertTrue(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   ///////////
+   /////////// Channel does NOT accept reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_8_1() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (queue.acceptReliableMessages())
+      {
+         // we test channels that don't accept reliable messages
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // transacted send, reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      try
+      {
+         tx.commit();
+         fail("this should throw exception");
+      }
+      catch(Exception e)
+      {
+         // OK
+      }
+
+      // still no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+   }
+
+   /**
+    * This is a variation where I send a mixture of reliable and non-reliable messages,
+    */
+   public void testNonRecoverableChannel_8_1_mixed() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (queue.acceptReliableMessages())
+      {
+         // we test channels that don't accept reliable messages
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         // send a mixture of reliable and non-reliable messages
+         refs[i] = createReference(i, (i % 2 == 1), "payload" + i);
+
+         // transacted send, reliable/non-reliable messages, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      try
+      {
+         tx.commit();
+         fail("this should throw exception");
+      }
+      catch(Exception e)
+      {
+         // OK
+      }
+
+      // still no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+   }
+   
+   public void testNonRecoverableChannel_8_1_mixed_1() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (queue.acceptReliableMessages())
+      {
+         // we test channels that don't accept reliable messages
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES * 2];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         // send a mixture of reliable and non-reliable messages
+         refs[i] = createReference(i, false, "payload" + i);
+
+         // transacted send, reliable/non-reliable messages, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         // send a mixture of reliable and non-reliable messages
+         refs[i + NUMBER_OF_MESSAGES] = createReference(i + NUMBER_OF_MESSAGES , true, "payload" + i);
+
+         // transacted send, reliable/non-reliable messages, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i + NUMBER_OF_MESSAGES], tx);
+      }
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      try
+      {
+         tx.commit();
+         fail("this should throw exception");
+      }
+      catch(Exception e)
+      {
+         // OK
+      }
+
+      // still no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+   }
+   
+
+   public void testNonRecoverableChannel_8_1_mixed_2() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (queue.acceptReliableMessages())
+      {
+         // we test channels that don't accept reliable messages
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES * 2];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         // send a mixture of reliable and non-reliable messages
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // transacted send, reliable/non-reliable messages, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         // send a mixture of reliable and non-reliable messages
+         refs[i + NUMBER_OF_MESSAGES] = createReference(i + NUMBER_OF_MESSAGES , true, "payload" + i);
+
+         // transacted send, reliable/non-reliable messages, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i + NUMBER_OF_MESSAGES], tx);
+      }
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      try
+      {
+         tx.commit();
+         fail("this should throw exception");
+      }
+      catch(Exception e)
+      {
+         // OK
+      }
+
+      // still no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+   }
+
+   ///////////
+   /////////// Channel accepts reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_8_2() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (!queue.acceptReliableMessages())
+      {
+         // we test channels that accept reliable messages
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // transacted send, reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      tx.commit();
+
+      assertEqualSets(refs, queue.browse());
+   }
+
+   /**
+    * This is a variation where I send a mixture of reliable and non-reliable messages,
+    */
+   public void testNonRecoverableChannel_8_2_mixed() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (!queue.acceptReliableMessages())
+      {
+         // we test channels that accept reliable messages
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         // send a mixture of reliable and non-reliable messages
+         refs[i] = createReference(i, (i % 2 == 1), "payload" + i);
+
+         // transacted send, reliable/non-reliable messages, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      tx.commit();
+
+      assertEqualSets(refs, queue.browse());
+   }
+
+
+   //////
+   ////// Transacted send and rollback
+   //////
+
+   ////////
+   //////// Non-reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testNonRecoverableChannel_9() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, non-reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      tx.rollback();
+
+      // still no messages in the channel
+      assertEquals(0, queue.browse().size());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testNonRecoverableChannel_10() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, false, "payload" + i);
+
+         // transacted send, non-reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      tx.rollback();
+
+      // still no messages in the channel
+      assertEquals(0, queue.browse().size());
+   }
+
+   ////////
+   //////// Reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testNonRecoverableChannel_11() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      tx.rollback();
+
+      // still no messages in the channel
+      assertEquals(0, queue.browse().size());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testNonRecoverableChannel_12() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // transacted send, reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      tx.rollback();
+
+      // still no messages in the channel
+      assertEquals(0, queue.browse().size());
+   }
+
+   /**
+    * This is a variation where I send a mixture of reliable and non-reliable messages,
+    */
+   public void testNonRecoverableChannel_12_mixed() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         // send a mixture of reliable and non-reliable messages
+         refs[i] = createReference(i, (i % 2 == 1), "payload" + i);
+
+         // transacted send, reliable/non-reliable messages, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      tx.rollback();
+
+      // still no messages in the channel
+      assertEquals(0, queue.browse().size());
+   }
+
+   ////
+   //// One receiver
+   ////
+
+   //////
+   ////// ACKING receiver
+   //////
+
+   //////
+   ////// Non-transacted send
+   //////
+
+   ////////
+   //////// Non-reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testNonRecoverableChannel_13() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, non-reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      assertTrue(delivery.isDone());
+      assertTrue(queue.browse().isEmpty());
+
+      List received = r.getMessages();
+      assertEquals(1, received.size());
+      Message sm = (Message)received.iterator().next();
+      assertFalse(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testNonRecoverableChannel_14() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, false, "payload" + i);
+
+         // non-transacted send, non-reliable message, multiple messages
+         Delivery delivery = queue.handle(observer, refs[i], null);
+
+         assertTrue(delivery.isDone());
+      }
+
+      assertTrue(queue.browse().isEmpty());
+
+      List received = r.getMessages();
+      assertEqualSets(refs, received);
+   }
+
+   ////////
+   //////// Reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   ///////////
+   /////////// Channel does NOT accept reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_15_1() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (queue.acceptReliableMessages())
+      {
+         // we test channels that don't accept reliable messages
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      assertNull(delivery);
+
+      assertTrue(queue.browse().isEmpty());
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+   ///////////
+   /////////// Channel accepts reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_15_2() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (!queue.acceptReliableMessages())
+      {
+         // we test channels that accept reliable messages
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      assertTrue(delivery.isDone());
+
+      assertTrue(queue.browse().isEmpty());
+
+      List received = r.getMessages();
+      assertEquals(1, received.size());
+      Message sm = (Message)received.iterator().next();
+      assertTrue(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   ///////////
+   /////////// Channel does NOT accept reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_16_1() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (queue.acceptReliableMessages())
+      {
+         // we test channels that don't accept reliable messages
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // non-transacted send, reliable message, multiple messages
+         Delivery delivery = queue.handle(observer, refs[i], null);
+
+         assertNull(delivery);
+      }
+
+      assertTrue(queue.browse().isEmpty());
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+   ///////////
+   /////////// Channel accepts reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_16_2() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (!queue.acceptReliableMessages())
+      {
+         // we test channels that accept reliable messages
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // non-transacted send, reliable message, multiple messages
+         Delivery delivery = queue.handle(observer, refs[i], null);
+
+         assertTrue(delivery.isDone());
+      }
+
+      assertTrue(queue.browse().isEmpty());
+      assertEqualSets(refs, r.getMessages());
+   }
+
+   //////
+   ////// Transacted send and commit
+   //////
+
+   ////////
+   //////// Non-reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testNonRecoverableChannel_17() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, non-reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.commit();
+
+      assertTrue(queue.browse().isEmpty());
+
+      List received = r.getMessages();
+      assertEquals(1, received.size());
+      Message sm = (Message)received.iterator().next();
+      assertFalse(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testNonRecoverableChannel_18() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, false, "payload" + i);
+
+         // transacted send, non-reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.commit();
+
+      assertTrue(queue.browse().isEmpty());
+      assertEqualSets(refs, r.getMessages());
+   }
+
+   ////////
+   //////// Reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   ///////////
+   /////////// Channel does NOT accept reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_19_1() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (queue.acceptReliableMessages())
+      {
+         // we test channels that don't accept reliable messages
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      try
+      {
+         tx.commit();
+         fail("this should throw exception");
+      }
+      catch(Exception e)
+      {
+         // OK
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+   ///////////
+   /////////// Channel accepts reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_19_2() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (!queue.acceptReliableMessages())
+      {
+         // we test channels that accept reliable messages
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.commit();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      List received = r.getMessages();
+      assertEquals(1, received.size());
+      Message sm = (Message)received.iterator().next();
+      assertTrue(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   ///////////
+   /////////// Channel does NOT accept reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_20_1() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (queue.acceptReliableMessages())
+      {
+         // we test channels that don't accept reliable messages
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // transacted send, reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      try
+      {
+         tx.commit();
+         fail("this should throw exception");
+      }
+      catch(Exception e)
+      {
+         // OK
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+   /**
+    * This is a variation where I send a mixture of reliable and non-reliable messages,
+    */
+   public void testNonRecoverableChannel_20_1_mixed() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (queue.acceptReliableMessages())
+      {
+         // we test channels that don't accept reliable messages
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         // send a mixture of reliable and non-reliable messages
+         refs[i] = createReference(i, (i % 2 == 1), "payload" + i);
+
+         // transacted send, reliable/non-reliable messages, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      try
+      {
+         tx.commit();
+         fail("this should throw exception");
+      }
+      catch(Exception e)
+      {
+         // OK
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+   ///////////
+   /////////// Channel accepts reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_20_2() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (!queue.acceptReliableMessages())
+      {
+         // we test channels that accept reliable messages
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // transacted send, reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.commit();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      assertEqualSets(refs, r.getMessages());
+   }
+
+   /**
+    * This is a variation where I send a mixture of reliable and non-reliable messages,
+    */
+   public void testNonRecoverableChannel_20_2_mixed() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (!queue.acceptReliableMessages())
+      {
+         // we test channels that accept reliable messages
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         // send a mixture of reliable and non-reliable messages
+         refs[i] = createReference(i, (i % 2 == 1), "payload" + i);
+
+         // transacted send, reliable/non-reliable messages, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.commit();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      assertEqualSets(refs, r.getMessages());
+   }
+
+   //////
+   ////// Transacted send and rollback
+   //////
+
+   ////////
+   //////// Non-reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testNonRecoverableChannel_21() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, non-reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+
+      tx.rollback();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testNonRecoverableChannel_22() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, false, "payload" + i);
+
+         // transacted send, non-reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.rollback();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+   ////////
+   //////// Reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testNonRecoverableChannel_23() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.rollback();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testNonRecoverableChannel_24() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // transacted send, reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.rollback();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+   /**
+    * This is a variation where I send a mixture of reliable and non-reliable messages,
+    */
+   public void testNonRecoverableChannel_24_mixed() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         // send a mixture of reliable and non-reliable messages
+         refs[i] = createReference(i, (i % 2 == 1), "payload" + i);
+
+         // transacted send, reliable/non-reliable messages, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.rollback();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+   //////
+   ////// NACKING receiver
+   //////
+
+   //////
+   ////// Non-transacted send
+   //////
+
+   ////////
+   //////// Non-reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   ////////////
+   //////////// Non-transacted acknowledgment
+   ////////////
+
+   public void testNonRecoverableChannel_25() throws Throwable
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, non-reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      assertTrue(delivery.isDone());
+
+      List delivering = queue.browse();
+      assertEquals(1, delivering.size());
+      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
+
+      List acknowledging = r.getMessages();
+      assertEquals(1, acknowledging.size());
+      Message ackm = (Message)acknowledging.get(0);
+      assertEquals(0, ackm.getMessageID());
+
+      // non-transacted acknowledgment
+      r.acknowledge(ackm, null);
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+   /**
+    * The same test as before, but with a Receiver configured to acknowledge immediately
+    * on the Delivery. Simulates a race condition in which the acknoledgment arrives before
+    * the Delivery is returned to channel.
+    *
+    * @throws Throwable
+    */
+   public void testNonRecoverableChannel_25_race() throws Throwable
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      r.setImmediateAsynchronousAcknowledgment(true);
+      assertTrue(queue.add(r));
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, non-reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      assertTrue(delivery.isDone());
+
+      // the receiver should have returned a "done" delivery
+      assertTrue(queue.browse().isEmpty());
+
+      List messages = r.getMessages();
+      assertEquals(1, messages.size());
+      Message ackm = (Message)messages.get(0);
+      assertEquals(0, ackm.getMessageID());
+
+      // an extra acknowledgment should be discarded
+      r.acknowledge(ackm, null);
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+
+   ////////////
+   //////////// Transacted acknowledgment and commit
+   ////////////
+
+   public void testNonRecoverableChannel_25_1() throws Throwable
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, non-reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      assertTrue(delivery.isDone());
+
+      List delivering = queue.browse();
+      assertEquals(1, delivering.size());
+      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
+
+      List acknowledging = r.getMessages();
+      assertEquals(1, acknowledging.size());
+      Message ackm = (Message)acknowledging.get(0);
+      assertEquals(0, ackm.getMessageID());
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted acknowledgment
+      r.acknowledge(ackm, tx);
+
+      delivering = queue.browse();
+      assertEquals(1, delivering.size());
+      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
+
+      tx.commit();
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+
+   ////////////
+   //////////// Transacted acknowledgment and rollback
+   ////////////
+
+   public void testNonRecoverableChannel_25_2() throws Throwable
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, non-reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      assertTrue(delivery.isDone());
+
+      List delivering = queue.browse();
+      assertEquals(1, delivering.size());
+      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
+
+      List acknowledging = r.getMessages();
+      assertEquals(1, acknowledging.size());
+      Message ackm = (Message)acknowledging.get(0);
+      assertEquals(0, ackm.getMessageID());
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted acknowledgment
+      r.acknowledge(ackm, tx);
+
+      delivering = queue.browse();
+      assertEquals(1, delivering.size());
+      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
+
+      tx.rollback();
+
+      delivering = queue.browse();
+      assertEquals(1, delivering.size());
+      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
+
+      // acknowledge non-transactionally
+      r.acknowledge(ackm, null);
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   ////////////
+   //////////// Non-transacted acknowledgment
+   ////////////
+
+   public void testNonRecoverableChannel_26() throws Throwable
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, false, "payload" + i);
+
+         // non-transacted send, non-reliable message, multiple messages
+         Delivery delivery = queue.handle(observer, refs[i], null);
+
+         assertTrue(delivery.isDone());
+      }
+
+      assertEqualSets(refs, queue.browse());
+      assertEqualSets(refs, r.getMessages());
+
+      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
+      {
+         Message ackm = (Message)i.next();
+         // non-transacted acknowledgment
+         r.acknowledge(ackm, null);
+      }
+
+      assertTrue(queue.browse().isEmpty());
+
+   }
+
+   ////////////
+   //////////// Transacted acknowledgment and commit
+   ////////////
+
+   public void testNonRecoverableChannel_26_1() throws Throwable
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, false, "payload" + i);
+
+         // non-transacted send, non-reliable message, multiple messages
+         Delivery delivery = queue.handle(observer, refs[i], null);
+
+         assertTrue(delivery.isDone());
+      }
+
+      assertEqualSets(refs, queue.browse());
+      assertEqualSets(refs, r.getMessages());
+
+      Transaction tx = tr.createTransaction();
+
+      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
+      {
+         Message ackm = (Message)i.next();
+         // transacted acknowledgment
+         r.acknowledge(ackm, tx);
+      }
+
+      assertEqualSets(refs, queue.browse());
+
+      tx.commit();
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+
+   ////////////
+   //////////// Transacted acknowledgment and rollback
+   ////////////
+
+   public void testNonRecoverableChannel_26_2() throws Throwable
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, false, "payload" + i);
+
+         // non-transacted send, non-reliable message, multiple messages
+         Delivery delivery = queue.handle(observer, refs[i], null);
+
+         assertTrue(delivery.isDone());
+      }
+
+      assertEqualSets(refs, queue.browse());
+      assertEqualSets(refs, r.getMessages());
+
+      Transaction tx = tr.createTransaction();
+
+      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
+      {
+         Message ackm = (Message)i.next();
+         // transacted acknowledgment
+         r.acknowledge(ackm, tx);
+      }
+
+      assertEqualSets(refs, queue.browse());
+
+      tx.rollback();
+
+      assertEqualSets(refs, queue.browse());
+
+      // acknowledge non-transactionally
+      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
+      {
+         Message ackm = (Message)i.next();
+         // non-transacted acknowledgment
+         r.acknowledge(ackm, null);
+      }
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+   ////////
+   //////// Reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   ////////////
+   //////////// Non-transacted acknowledgment
+   ////////////
+
+   ///////////
+   /////////// Channel does NOT accept reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_27_1_1() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (queue.acceptReliableMessages())
+      {
+         // we test channels that don't accept reliable messages
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      // not accepted by the channel
+      assertNull(delivery);
+      assertTrue(queue.browse().isEmpty());
+      assertTrue(r.getMessages().isEmpty());
+
+   }
+
+   ///////////
+   /////////// Channel accepts reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_27_1_2() throws Throwable
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (!queue.acceptReliableMessages())
+      {
+         // we test channels that accept reliable messages
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      assertTrue(delivery.isDone());
+
+      List stored = queue.browse();
+      assertEquals(1, stored.size());
+      Message sm = (Message)stored.iterator().next();
+      assertTrue(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+
+      List received = r.getMessages();
+      assertEquals(1, received.size());
+      Message rm = (Message)received.iterator().next();
+      assertTrue(rm.isReliable());
+      assertEquals(0, rm.getMessageID());
+
+      r.acknowledge(rm, null);
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+
+   ////////////
+   //////////// Transacted acknowledgment
+   ////////////
+
+   ///////////
+   /////////// Channel does NOT accept reliable messages
+   ///////////
+
+
+   // Doesn't make sense, the message won't be accepted anyway.
+
+   ///////////
+   /////////// Channel accepts reliable messages
+   ///////////
+
+
+   public void testNonRecoverableChannel_27_2_2() throws Throwable
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (!queue.acceptReliableMessages())
+      {
+         // we test channels that accept reliable messages
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      assertTrue(delivery.isDone());
+
+      List stored = queue.browse();
+      assertEquals(1, stored.size());
+      Message sm = (Message)stored.iterator().next();
+      assertTrue(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+
+      List received = r.getMessages();
+      assertEquals(1, received.size());
+      Message rm = (Message)received.iterator().next();
+      assertTrue(rm.isReliable());
+      assertEquals(0, rm.getMessageID());
+
+      Transaction tx = tr.createTransaction();
+
+      r.acknowledge(rm, tx);
+
+      stored = queue.browse();
+      assertEquals(1, stored.size());
+      sm = (Message)stored.iterator().next();
+      assertTrue(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+
+      tx.commit();
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   ////////////
+   //////////// Non-transacted acknowledgment
+   ////////////
+
+   ///////////
+   /////////// Channel does NOT accept reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_28_1_1() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (queue.acceptReliableMessages())
+      {
+         // we test channels that don't accept reliable messages
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // non-transacted send, reliable message, multiple messages
+         Delivery delivery = queue.handle(observer, refs[i], null);
+
+         // not accepted by the channel
+         assertNull(delivery);
+      }
+
+      assertTrue(queue.browse().isEmpty());
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+   ///////////
+   /////////// Channel accepts reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_28_1_2() throws Throwable
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (!queue.acceptReliableMessages())
+      {
+         // we test channels that accept reliable messages
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // non-transacted send, reliable message, multiple messages
+         Delivery delivery = queue.handle(observer, refs[i], null);
+
+         assertTrue(delivery.isDone());
+      }
+
+      assertEqualSets(refs, queue.browse());
+      assertEqualSets(refs, r.getMessages());
+
+      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
+      {
+         Message ackm = (Message)i.next();
+         // non-transacted acknowledgment
+         r.acknowledge(ackm, null);
+      }
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+
+   ////////////
+   //////////// Transacted acknowledgment
+   ////////////
+
+   ///////////
+   /////////// Channel does NOT accept reliable messages
+   ///////////
+
+   // Doesn't make sense, the message won't be accepted anyway.
+
+   ///////////
+   /////////// Channel accepts reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_28_2_2() throws Throwable
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (!queue.acceptReliableMessages())
+      {
+         // we test channels that accept reliable messages
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // non-transacted send, reliable message, multiple messages
+         Delivery delivery = queue.handle(observer, refs[i], null);
+
+         assertTrue(delivery.isDone());
+      }
+
+      assertEqualSets(refs, queue.browse());
+      assertEqualSets(refs, r.getMessages());
+
+      Transaction tx = tr.createTransaction();
+
+      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
+      {
+         Message ackm = (Message)i.next();
+         r.acknowledge(ackm, tx);
+      }
+
+      assertEqualSets(refs, queue.browse());
+
+      tx.commit();
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+   //////
+   ////// Transacted send and commit
+   //////
+
+   ////////
+   //////// Non-reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testNonRecoverableChannel_29() throws Throwable
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, non-reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.commit();
+
+      List delivering = queue.browse();
+      assertEquals(1, delivering.size());
+      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
+
+      List acknowledging = r.getMessages();
+      assertEquals(1, acknowledging.size());
+      Message ackm = (Message)acknowledging.get(0);
+      assertEquals(0, ackm.getMessageID());
+
+      // non-transacted acknowledgment
+      r.acknowledge(ackm, null);
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testNonRecoverableChannel_30() throws Throwable
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, false, "payload" + i);
+
+         // transacted send, non-reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.commit();
+
+      assertEqualSets(refs, queue.browse());
+      assertEqualSets(refs, r.getMessages());
+
+      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
+      {
+         Message ackm = (Message)i.next();
+         // non-transacted acknowledgment
+         r.acknowledge(ackm, null);
+      }
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+   ////////
+   //////// Reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   ///////////
+   /////////// Channel does NOT accept reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_31_1() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (queue.acceptReliableMessages())
+      {
+         // we test channels that don't accept reliable messages
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      try
+      {
+         tx.commit();
+         fail("this should throw exception");
+      }
+      catch(Exception e)
+      {
+         // OK
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+   ///////////
+   /////////// Channel does accepts reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_31_2() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (!queue.acceptReliableMessages())
+      {
+         // we test channels that accept reliable messages
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.commit();
+
+      List stored = queue.browse();
+      assertEquals(1, stored.size());
+      Message sm = (Message)stored.iterator().next();
+      assertTrue(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+
+      List received = r.getMessages();
+      assertEquals(1, received.size());
+      Message rm = (Message)received.iterator().next();
+      assertTrue(rm.isReliable());
+      assertEquals(0, rm.getMessageID());
+   }
+
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   ///////////
+   /////////// Channel does NOT accept reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_32_1() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (queue.acceptReliableMessages())
+      {
+         // we test channels that don't accept reliable messages
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // transacted send, reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      try
+      {
+         tx.commit();
+         fail("this should throw exception");
+      }
+      catch(Exception e)
+      {
+         // OK
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+   /**
+    * This is a variation where I send a mixture of reliable and non-reliable messages,
+    */
+   public void testNonRecoverableChannel_32_1_mixed() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (queue.acceptReliableMessages())
+      {
+         // we test channels that don't accept reliable messages
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         // send a mixture of reliable and non-reliable messages
+         refs[i] = createReference(i, (i % 2 == 1), "payload" + i);
+
+         // transacted send, reliable/non-reliable messages, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      try
+      {
+         tx.commit();
+         fail("this should throw exception");
+      }
+      catch(Exception e)
+      {
+         // OK
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+   ///////////
+   /////////// Channel accepts reliable messages
+   ///////////
+
+   public void testNonRecoverableChannel_32_2() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (!queue.acceptReliableMessages())
+      {
+         // we test channels that accept reliable messages
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // transacted send, reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.commit();
+
+      assertEqualSets(refs, queue.browse());
+      assertEqualSets(refs, r.getMessages());
+   }
+
+   /**
+    * This is a variation where I send a mixture of reliable and non-reliable messages,
+    */
+   public void testNonRecoverableChannel_32_2_mixed() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      if (!queue.acceptReliableMessages())
+      {
+         // we test channels that accept reliable messages
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         // send a mixture of reliable and non-reliable messages
+         refs[i] = createReference(i, (i % 2 == 1), "payload" + i);
+
+         // transacted send, reliable/non-reliable messages, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.commit();
+
+      assertEqualSets(refs, queue.browse());
+      assertEqualSets(refs, r.getMessages());
+   }
+
+
+
+   //////
+   ////// Transacted send and rollback
+   //////
+
+   ////////
+   //////// Non-reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testNonRecoverableChannel_33() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, non-reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+
+      tx.rollback();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testNonRecoverableChannel_34() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, false, "payload" + i);
+
+         // transacted send, non-reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.rollback();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+   ////////
+   //////// Reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testNonRecoverableChannel_35() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.rollback();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testNonRecoverableChannel_36() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // transacted send, reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.rollback();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+   /**
+    * This is a variation where I send a mixture of reliable and non-reliable messages,
+    */
+   public void testNonRecoverableChannel_36_mixed() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         // send a mixture of reliable and non-reliable messages
+         refs[i] = createReference(i, (i % 2 == 1), "payload" + i);
+
+         // transacted send, reliable/non-reliable messages, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.rollback();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+
+
+
+   //
+   // Recoverable channel
+   //
+
+   public void testRecoverableChannel_0() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         assertTrue(queue.acceptReliableMessages());
+      }
+   }
+
+   ////
+   //// Zero receivers
+   ////
+
+   //////
+   ////// Non-transacted send
+   //////
+
+   ////////
+   //////// Non-reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testRecoverableChannel_1() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, non-reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      assertTrue(delivery.isDone());
+
+      List stored = queue.browse();
+      assertEquals(1, stored.size());
+
+      Message sm = (Message)stored.iterator().next();
+      assertFalse(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testRecoverableChannel_2() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, false, "payload" + i);
+
+         // non-transacted send, non-reliable message, multiple messages
+         Delivery delivery = queue.handle(observer, refs[i], null);
+
+         assertTrue(delivery.isDone());
+      }
+
+      assertEqualSets(refs, queue.browse());
+   }
+
+   ////////
+   //////// Reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testRecoverableChannel_3() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      assertTrue(delivery.isDone());
+
+      List stored = queue.browse();
+      assertEquals(1, stored.size());
+
+      Message sm = (Message)stored.iterator().next();
+      assertTrue(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testRecoverableChannel_4() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // non-transacted send, reliable message, multiple messages
+         Delivery delivery = queue.handle(observer, refs[i], null);
+
+         assertTrue(delivery.isDone());
+      }
+
+      assertEqualSets(refs, queue.browse());
+
+   }
+
+   //////
+   ////// Transacted send and commit
+   //////
+
+   ////////
+   //////// Non-reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testRecoverableChannel_5() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, non-reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      tx.commit();
+
+      List stored = queue.browse();
+      assertEquals(1, stored.size());
+
+      Message sm = (Message)stored.iterator().next();
+      assertFalse(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testRecoverableChannel_6() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, false, "payload" + i);
+
+         // transacted send, non-reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      tx.commit();
+
+      assertEqualSets(refs, queue.browse());
+   }
+
+   ////////
+   //////// Reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testRecoverableChannel_7() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      tx.commit();
+
+      List stored = queue.browse();
+      assertEquals(1, stored.size());
+
+      Message sm = (Message)stored.iterator().next();
+      assertTrue(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testRecoverableChannel_8() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // transacted send, reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      tx.commit();
+
+      assertEqualSets(refs, queue.browse());
+   }
+
+   /**
+    * This is a variation where I send a mixture of reliable and non-reliable messages,
+    */
+   public void testRecoverableChannel_8_mixed() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         // send a mixture of reliable and non-reliable messages
+         refs[i] = createReference(i, (i % 2 == 1), "payload" + i);
+
+         // transacted send, reliable/non-reliable messages, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      tx.commit();
+
+      assertEqualSets(refs, queue.browse());
+   }
+
+
+   //////
+   ////// Transacted send and rollback
+   //////
+
+   ////////
+   //////// Non-reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testRecoverableChannel_9() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, non-reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      tx.rollback();
+
+      // still no messages in the channel
+      assertEquals(0, queue.browse().size());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testRecoverableChannel_10() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, false, "payload" + i);
+
+         // transacted send, non-reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      tx.rollback();
+
+      // still no messages in the channel
+      assertEquals(0, queue.browse().size());
+   }
+
+   ////////
+   //////// Reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testRecoverableChannel_11() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      tx.rollback();
+
+      // still no messages in the channel
+      assertEquals(0, queue.browse().size());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testRecoverableChannel_12() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // transacted send, reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      tx.rollback();
+
+      // still no messages in the channel
+      assertEquals(0, queue.browse().size());
+   }
+
+   /**
+    * This is a variation where I send a mixture of reliable and non-reliable messages,
+    */
+   public void testRecoverableChannel_12_mixed() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         // send a mixture of reliable and non-reliable messages
+         refs[i] = createReference(i, (i % 2 == 1), "payload" + i);
+
+         // transacted send, reliable/non-reliable messages, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      tx.rollback();
+
+      // still no messages in the channel
+      assertEquals(0, queue.browse().size());
+   }
+
+   ////
+   //// One receiver
+   ////
+
+   //////
+   ////// ACKING receiver
+   //////
+
+   //////
+   ////// Non-transacted send
+   //////
+
+   ////////
+   //////// Non-reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testRecoverableChannel_13() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, non-reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      assertTrue(delivery.isDone());
+      assertTrue(queue.browse().isEmpty());
+
+      List received = r.getMessages();
+      assertEquals(1, received.size());
+      Message sm = (Message)received.iterator().next();
+      assertFalse(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testRecoverableChannel_14() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, false, "payload" + i);
+
+         // non-transacted send, non-reliable message, multiple messages
+         Delivery delivery = queue.handle(observer, refs[i], null);
+
+         assertTrue(delivery.isDone());
+      }
+
+      assertTrue(queue.browse().isEmpty());
+
+      List received = r.getMessages();
+      assertEqualSets(refs, received);
+   }
+
+   ////////
+   //////// Reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testRecoverableChannel_15() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      assertTrue(delivery.isDone());
+
+      assertTrue(queue.browse().isEmpty());
+
+      List received = r.getMessages();
+      assertEquals(1, received.size());
+      Message sm = (Message)received.iterator().next();
+      assertTrue(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testRecoverableChannel_16() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // non-transacted send, reliable message, multiple messages
+         Delivery delivery = queue.handle(observer, refs[i], null);
+
+         assertTrue(delivery.isDone());
+      }
+
+      assertTrue(queue.browse().isEmpty());
+      assertEqualSets(refs, r.getMessages());
+   }
+
+   //////
+   ////// Transacted send and commit
+   //////
+
+   ////////
+   //////// Non-reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testRecoverableChannel_17() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, non-reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.commit();
+
+      assertTrue(queue.browse().isEmpty());
+
+      List received = r.getMessages();
+      assertEquals(1, received.size());
+      Message sm = (Message)received.iterator().next();
+      assertFalse(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+   }
+
+
+   public void testRecoverableChannel_17_1() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      BrokenReceiver brokenReceiver = new BrokenReceiver(2);
+      assertTrue(queue.add(brokenReceiver));
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+
+      log.debug("sending message 1");
+
+      // transacted send, non-reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      ref = createReference(1, false, "payload");
+
+      log.debug("sending message 2");
+      queue.handle(observer, ref, tx);
+
+      ref = createReference(2, false, "payload");
+
+      log.debug("sending message 3");
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      tx.commit();
+
+      assertEquals(2, queue.browse().size());
+      assertEquals(1, brokenReceiver.getMessages().size());
+   }
+
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testRecoverableChannel_18() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, false, "payload" + i);
+
+         // transacted send, non-reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.commit();
+
+      assertTrue(queue.browse().isEmpty());
+      assertEqualSets(refs, r.getMessages());
+   }
+
+   ////////
+   //////// Reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testRecoverableChannel_19() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.commit();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      List received = r.getMessages();
+      assertEquals(1, received.size());
+      Message sm = (Message)received.iterator().next();
+      assertTrue(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testRecoverableChannel_20() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // transacted send, reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.commit();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      assertEqualSets(refs, r.getMessages());
+   }
+
+   /**
+    * This is a variation where I send a mixture of reliable and non-reliable messages,
+    */
+   public void testRecoverableChannel_20_mixed() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         // send a mixture of reliable and non-reliable messages
+         refs[i] = createReference(i, (i % 2 == 1), "payload" + i);
+
+         // transacted send, reliable/non-reliable messages, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.commit();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      assertEqualSets(refs, r.getMessages());
+   }
+
+
+   //////
+   ////// Transacted send and rollback
+   //////
+
+   ////////
+   //////// Non-reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testRecoverableChannel_21() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, non-reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+
+      tx.rollback();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testRecoverableChannel_22() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, false, "payload" + i);
+
+         // transacted send, non-reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.rollback();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+   ////////
+   //////// Reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testRecoverableChannel_23() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.rollback();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testRecoverableChannel_24() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // transacted send, reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.rollback();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+   /**
+    * This is a variation where I send a mixture of reliable and non-reliable messages,
+    */
+   public void testRecoverableChannel_24_mixed() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+
+      // add an ACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("AckingReceiver", SimpleReceiver.ACKING);
+      assertTrue(queue.add(r));
+
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         // send a mixture of reliable and non-reliable messages
+         refs[i] = createReference(i, (i % 2 == 1), "payload" + i);
+
+         // transacted send, reliable/non-reliable messages, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.rollback();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+   //////
+   ////// NACKING receiver
+   //////
+
+   //////
+   ////// Non-transacted send
+   //////
+
+   ////////
+   //////// Non-reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   ////////////
+   //////////// Non-transacted acknowledgment
+   ////////////
+
+   public void testRecoverableChannel_25() throws Throwable
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, non-reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      assertTrue(delivery.isDone());
+
+      List delivering = queue.browse();
+      assertEquals(1, delivering.size());
+      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
+
+      List acknowledging = r.getMessages();
+      assertEquals(1, acknowledging.size());
+      Message ackm = (Message)acknowledging.get(0);
+      assertEquals(0, ackm.getMessageID());
+
+      // non-transacted acknowledgment
+      r.acknowledge(ackm, null);
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+   /**
+    * The same test as before, but with a Receiver configured to acknowledge immediately
+    * on the Delivery. Simulates a race condition in which the acknoledgment arrives before
+    * the Delivery is returned to channel.
+    *
+    * @throws Throwable
+    */
+   public void testRecoverableChannel_25_race() throws Throwable
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      r.setImmediateAsynchronousAcknowledgment(true);
+      assertTrue(queue.add(r));
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, non-reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      assertTrue(delivery.isDone());
+
+      // the receiver should have returned a "done" delivery
+      assertTrue(queue.browse().isEmpty());
+
+      List messages = r.getMessages();
+      assertEquals(1, messages.size());
+      Message ackm = (Message)messages.get(0);
+      assertEquals(0, ackm.getMessageID());
+
+      // an extra acknowledgment should be discarded
+      r.acknowledge(ackm, null);
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+
+   ////////////
+   //////////// Transacted acknowledgment and commit
+   ////////////
+
+   public void testRecoverableChannel_25_1() throws Throwable
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, non-reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      assertTrue(delivery.isDone());
+
+      List delivering = queue.browse();
+      assertEquals(1, delivering.size());
+      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
+
+      List acknowledging = r.getMessages();
+      assertEquals(1, acknowledging.size());
+      Message ackm = (Message)acknowledging.get(0);
+      assertEquals(0, ackm.getMessageID());
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted acknowledgment
+      r.acknowledge(ackm, tx);
+
+      delivering = queue.browse();
+      assertEquals(1, delivering.size());
+      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
+
+      tx.commit();
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+
+   ////////////
+   //////////// Transacted acknowledgment and rollback
+   ////////////
+
+   public void testRecoverableChannel_25_2() throws Throwable
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, non-reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      assertTrue(delivery.isDone());
+
+      List delivering = queue.browse();
+      assertEquals(1, delivering.size());
+      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
+
+      List acknowledging = r.getMessages();
+      assertEquals(1, acknowledging.size());
+      Message ackm = (Message)acknowledging.get(0);
+      assertEquals(0, ackm.getMessageID());
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted acknowledgment
+      r.acknowledge(ackm, tx);
+
+      delivering = queue.browse();
+      assertEquals(1, delivering.size());
+      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
+
+      tx.rollback();
+
+      delivering = queue.browse();
+      assertEquals(1, delivering.size());
+      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
+
+      // acknowledge non-transactionally
+      r.acknowledge(ackm, null);
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   ////////////
+   //////////// Non-transacted acknowledgment
+   ////////////
+
+   public void testRecoverableChannel_26() throws Throwable
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, false, "payload" + i);
+
+         // non-transacted send, non-reliable message, multiple messages
+         Delivery delivery = queue.handle(observer, refs[i], null);
+
+         assertTrue(delivery.isDone());
+      }
+
+      assertEqualSets(refs, queue.browse());
+      assertEqualSets(refs, r.getMessages());
+
+      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
+      {
+         Message ackm = (Message)i.next();
+         // non-transacted acknowledgment
+         r.acknowledge(ackm, null);
+      }
+
+      assertTrue(queue.browse().isEmpty());
+
+   }
+
+   ////////////
+   //////////// Transacted acknowledgment and commit
+   ////////////
+
+   public void testRecoverableChannel_26_1() throws Throwable
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, false, "payload" + i);
+
+         // non-transacted send, non-reliable message, multiple messages
+         Delivery delivery = queue.handle(observer, refs[i], null);
+
+         assertTrue(delivery.isDone());
+      }
+
+      assertEqualSets(refs, queue.browse());
+      assertEqualSets(refs, r.getMessages());
+
+      Transaction tx = tr.createTransaction();
+
+      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
+      {
+         Message ackm = (Message)i.next();
+         // transacted acknowledgment
+         r.acknowledge(ackm, tx);
+      }
+
+      assertEqualSets(refs, queue.browse());
+
+      tx.commit();
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+
+   ////////////
+   //////////// Transacted acknowledgment and rollback
+   ////////////
+
+   public void testRecoverableChannel_26_2() throws Throwable
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, false, "payload" + i);
+
+         // non-transacted send, non-reliable message, multiple messages
+         Delivery delivery = queue.handle(observer, refs[i], null);
+
+         assertTrue(delivery.isDone());
+      }
+
+      assertEqualSets(refs, queue.browse());
+      assertEqualSets(refs, r.getMessages());
+
+      Transaction tx = tr.createTransaction();
+
+      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
+      {
+         Message ackm = (Message)i.next();
+         // transacted acknowledgment
+         r.acknowledge(ackm, tx);
+      }
+
+      assertEqualSets(refs, queue.browse());
+
+      tx.rollback();
+
+      assertEqualSets(refs, queue.browse());
+
+      // acknowledge non-transactionally
+      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
+      {
+         Message ackm = (Message)i.next();
+         // non-transacted acknowledgment
+         r.acknowledge(ackm, null);
+      }
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+   ////////
+   //////// Reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   ////////////
+   //////////// Non-transacted acknowledgment
+   ////////////
+
+   public void testRecoverableChannel_27() throws Throwable
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      assertTrue(delivery.isDone());
+
+      List delivering = queue.browse();
+      assertEquals(1, delivering.size());
+      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
+
+      List acknowledging = r.getMessages();
+      assertEquals(1, acknowledging.size());
+      Message ackm = (Message)acknowledging.get(0);
+      assertEquals(0, ackm.getMessageID());
+
+      // non-transacted acknowledgment
+      r.acknowledge(ackm, null);
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+   /**
+    * The same test as before, but with a Receiver configured to acknowledge immediately
+    * on the Delivery. Simulates a race condition in which the acknoledgment arrives before
+    * the Delivery is returned to channel.
+    *
+    * @throws Throwable
+    */
+   public void testRecoverableChannel_27_race() throws Throwable
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      r.setImmediateAsynchronousAcknowledgment(true);
+      assertTrue(queue.add(r));
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      assertTrue(delivery.isDone());
+
+      // the receiver should have returned a "done" delivery
+      assertTrue(queue.browse().isEmpty());
+
+      List messages = r.getMessages();
+      assertEquals(1, messages.size());
+      Message ackm = (Message)messages.get(0);
+      assertEquals(0, ackm.getMessageID());
+
+      // an extra acknowledgment should be discarded
+      
+      //TODO - why should it be discarded?
+      //If you acknowledge twice surely this is a usage error?
+      r.acknowledge(ackm, null);
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+
+   ////////////
+   //////////// Transacted acknowledgment and commit
+   ////////////
+
+   public void testRecoverableChannel_27_1() throws Throwable
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      assertTrue(delivery.isDone());
+
+      List delivering = queue.browse();
+      assertEquals(1, delivering.size());
+      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
+
+      List acknowledging = r.getMessages();
+      assertEquals(1, acknowledging.size());
+      Message ackm = (Message)acknowledging.get(0);
+      assertEquals(0, ackm.getMessageID());
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted acknowledgment
+      r.acknowledge(ackm, tx);
+
+      delivering = queue.browse();
+      assertEquals(1, delivering.size());
+      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
+
+      tx.commit();
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+
+   ////////////
+   //////////// Transacted acknowledgment and rollback
+   ////////////
+
+   public void testRecoverableChannel_27_2() throws Throwable
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-transacted send, reliable message, one message
+      Delivery delivery = queue.handle(observer, ref, null);
+
+      assertTrue(delivery.isDone());
+
+      List delivering = queue.browse();
+      assertEquals(1, delivering.size());
+      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
+
+      List acknowledging = r.getMessages();
+      assertEquals(1, acknowledging.size());
+      Message ackm = (Message)acknowledging.get(0);
+      assertEquals(0, ackm.getMessageID());
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted acknowledgment
+      r.acknowledge(ackm, tx);
+
+      delivering = queue.browse();
+      assertEquals(1, delivering.size());
+      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
+
+      tx.rollback();
+
+      delivering = queue.browse();
+      assertEquals(1, delivering.size());
+      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
+
+      // acknowledge non-transactionally
+      r.acknowledge(ackm, null);
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   ////////////
+   //////////// Non-transacted acknowledgment
+   ////////////
+
+   public void testRecoverableChannel_28() throws Throwable
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // non-transacted send, reliable message, multiple messages
+         Delivery delivery = queue.handle(observer, refs[i], null);
+
+         assertTrue(delivery.isDone());
+      }
+
+      assertEqualSets(refs, queue.browse());
+      assertEqualSets(refs, r.getMessages());
+
+      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
+      {
+         Message ackm = (Message)i.next();
+         // non-transacted acknowledgment
+         r.acknowledge(ackm, null);
+      }
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+   ////////////
+   //////////// Transacted acknowledgment and commit
+   ////////////
+
+   public void testRecoverableChannel_28_1() throws Throwable
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // non-transacted send, reliable message, multiple messages
+         Delivery delivery = queue.handle(observer, refs[i], null);
+
+         assertTrue(delivery.isDone());
+      }
+
+      assertEqualSets(refs, queue.browse());
+      assertEqualSets(refs, r.getMessages());
+
+      Transaction tx = tr.createTransaction();
+
+      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
+      {
+         Message ackm = (Message)i.next();
+         // transacted acknowledgment
+         r.acknowledge(ackm, tx);
+      }
+
+      assertEqualSets(refs, queue.browse());
+
+      tx.commit();
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+   ////////////
+   //////////// Transacted acknowledgment and rollback
+   ////////////
+
+   public void testRecoverableChannel_28_2() throws Throwable
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // non-transacted send, reliable message, multiple messages
+         Delivery delivery = queue.handle(observer, refs[i], null);
+
+         assertTrue(delivery.isDone());
+      }
+
+      assertEqualSets(refs, queue.browse());
+      assertEqualSets(refs, r.getMessages());
+
+      Transaction tx = tr.createTransaction();
+
+      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
+      {
+         Message ackm = (Message)i.next();
+         // transacted acknowledgment
+         r.acknowledge(ackm, tx);
+      }
+
+      assertEqualSets(refs, queue.browse());
+
+      tx.rollback();
+
+      assertEqualSets(refs, queue.browse());
+
+      // acknowledge non-transactionally
+      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
+      {
+         Message ackm = (Message)i.next();
+         // non-transacted acknowledgment
+         r.acknowledge(ackm, null);
+      }
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+
+   //////
+   ////// Transacted send and commit
+   //////
+
+   ////////
+   //////// Non-reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testRecoverableChannel_29() throws Throwable
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, non-reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.commit();
+
+      List delivering = queue.browse();
+      assertEquals(1, delivering.size());
+      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
+
+      List acknowledging = r.getMessages();
+      assertEquals(1, acknowledging.size());
+      Message ackm = (Message)acknowledging.get(0);
+      assertEquals(0, ackm.getMessageID());
+
+      // non-transacted acknowledgment
+      r.acknowledge(ackm, null);
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testRecoverableChannel_30() throws Throwable
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, false, "payload" + i);
+
+         // transacted send, non-reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.commit();
+
+      assertEqualSets(refs, queue.browse());
+      assertEqualSets(refs, r.getMessages());
+
+      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
+      {
+         Message ackm = (Message)i.next();
+         // non-transacted acknowledgment
+         r.acknowledge(ackm, null);
+      }
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+   ////////
+   //////// Reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testRecoverableChannel_31() throws Throwable
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.commit();
+
+      List delivering = queue.browse();
+      assertEquals(1, delivering.size());
+      assertEquals(0, ((Message)delivering.get(0)).getMessageID());
+
+      List acknowledging = r.getMessages();
+      assertEquals(1, acknowledging.size());
+      Message ackm = (Message)acknowledging.get(0);
+      assertEquals(0, ackm.getMessageID());
+
+      // non-transacted acknowledgment
+      r.acknowledge(ackm, null);
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testRecoverableChannel_32() throws Throwable
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // transacted send, reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel yet
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.commit();
+
+      assertEqualSets(refs, queue.browse());
+      assertEqualSets(refs, r.getMessages());
+
+      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
+      {
+         Message ackm = (Message)i.next();
+         // non-transacted acknowledgment
+         r.acknowledge(ackm, null);
+      }
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+   /**
+    * This is a variation where I send a mixture of reliable and non-reliable messages,
+    */
+   public void testRecoverableChannel_32_mixed() throws Throwable
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         // send a mixture of reliable and non-reliable messages
+         refs[i] = createReference(i, (i % 2 == 1), "payload" + i);
+
+         // transacted send, reliable/non-reliable messages, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.commit();
+
+      assertEqualSets(refs, queue.browse());
+      assertEqualSets(refs, r.getMessages());
+
+      for(Iterator i = r.getMessages().iterator(); i.hasNext();)
+      {
+         Message ackm = (Message)i.next();
+         // non-transacted acknowledgment
+         r.acknowledge(ackm, null);
+      }
+
+      assertTrue(queue.browse().isEmpty());
+   }
+
+
+   //////
+   ////// Transacted send and rollback
+   //////
+
+   ////////
+   //////// Non-reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testRecoverableChannel_33() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, non-reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+
+      tx.rollback();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testRecoverableChannel_34() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, false, "payload" + i);
+
+         // transacted send, non-reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.rollback();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+   ////////
+   //////// Reliable message
+   ////////
+
+   //////////
+   ////////// One message
+   //////////
+
+   public void testRecoverableChannel_35() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      // transacted send, reliable message, one message
+      // for a transactional send, handle() return value is unspecified
+      queue.handle(observer, ref, tx);
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.rollback();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+   //////////
+   ////////// Multiple message
+   //////////
+
+   public void testRecoverableChannel_36() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         refs[i] = createReference(i, true, "payload" + i);
+
+         // transacted send, reliable message, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.rollback();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+   /**
+    * This is a variation where I send a mixture of reliable and non-reliable messages,
+    */
+   public void testRecoverableChannel_36_mixed() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // add an NACKING receiver to the channel
+      SimpleReceiver r = new SimpleReceiver("NackingReceiver", SimpleReceiver.ACCEPTING);
+      assertTrue(queue.add(r));
+
+
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      Transaction tx = tr.createTransaction();
+
+      MessageReference[] refs = new MessageReference[NUMBER_OF_MESSAGES];
+      for(int i = 0; i < NUMBER_OF_MESSAGES; i++)
+      {
+         // send a mixture of reliable and non-reliable messages
+         refs[i] = createReference(i, (i % 2 == 1), "payload" + i);
+
+         // transacted send, reliable/non-reliable messages, multiple messages
+         // for a transactional send, handle() return value is unspecified
+         queue.handle(observer, refs[i], tx);
+      }
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+
+      tx.rollback();
+
+      // no messages in the channel
+      assertEquals(0, queue.browse().size());
+
+      // no message at the receiver
+      assertTrue(r.getMessages().isEmpty());
+   }
+
+   ///////////////////////////////
+   /////////////////////////////// Add receiver tests
+   ///////////////////////////////
+   ///////////////////////////////
+   ///////////////////////////////
+
+   //
+   // Non-recoverable channel
+   //
+
+   ////
+   //// Non-reliable message
+   ////
+
+   //////
+   ////// Broken receiver
+   //////
+
+   public void testAddReceiver_1() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-recoverable channel, non-reliable message
+      Delivery delivery = queue.handle(observer, ref, null);
+      assertTrue(delivery.isDone());
+
+      List stored = queue.browse();
+      assertEquals(1, stored.size());
+
+
+      SimpleReceiver receiver = new SimpleReceiver("BrokenReceiver", SimpleReceiver.BROKEN);
+      assertTrue(queue.add(receiver));
+
+      stored = queue.browse();
+      assertEquals(1, stored.size());
+      Message sm = (Message)stored.iterator().next();
+      assertFalse(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+
+      assertTrue(receiver.getMessages().isEmpty());
+   }
+
+   //////
+   ////// ACKING receiver
+   //////
+
+   public void testAddReceiver_2() throws Exception
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-recoverable channel, non-reliable message
+      Delivery delivery = queue.handle(observer, ref, null);
+      assertTrue(delivery.isDone());
+
+      List stored = queue.browse();
+      assertEquals(1, stored.size());
+
+      SimpleReceiver receiver =
+            new SimpleReceiver("ACKINGReceiver", SimpleReceiver.ACKING, queue);
+      assertTrue(queue.add(receiver));
+
+      assertEquals(1, queue.browse().size());
+
+      // receiver explicitely asks for message
+      receiver.requestMessages();
+
+      assertTrue(queue.browse().isEmpty());
+
+      List messages = receiver.getMessages();
+      assertEquals(1, messages.size());
+      Message sm = (Message)messages.iterator().next();
+      assertFalse(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+   }
+
+   //////
+   ////// NACKING receiver
+   //////
+
+   public void testAddReceiver_3() throws Throwable
+   {
+      if (queue.isRecoverable())
+      {
+         // we test only non-recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      MessageReference ref = createReference(0, false, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-recoverable channel, non-reliable message
+      Delivery delivery = queue.handle(observer, ref, null);
+      assertTrue(delivery.isDone());
+
+      List stored = queue.browse();
+      assertEquals(1, stored.size());
+
+      SimpleReceiver receiver =
+            new SimpleReceiver("NACKINGReceiver", SimpleReceiver.ACCEPTING, queue);
+      assertTrue(queue.add(receiver));
+
+      assertEquals(1, queue.browse().size());
+
+      // receiver explicitely asks for message
+      receiver.requestMessages();
+
+      assertEquals(1, queue.browse().size());
+
+      List messages = receiver.getMessages();
+      assertEquals(1, messages.size());
+      Message sm = (Message)messages.iterator().next();
+      assertFalse(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+
+      receiver.acknowledge(sm, null);
+
+      assertTrue(queue.browse().isEmpty());
+
+      messages = receiver.getMessages();
+      assertEquals(1, messages.size());
+      sm = (Message)messages.iterator().next();
+      assertFalse(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+   }
+
+   //
+   // Recoverable channel
+   //
+
+   ////
+   //// Reliable message
+   ////
+
+   public void testAddReceiver_4() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-recoverable channel, non-reliable message
+      Delivery delivery = queue.handle(observer, ref, null);
+      assertTrue(delivery.isDone());
+
+      List stored = queue.browse();
+      assertEquals(1, stored.size());
+
+
+      SimpleReceiver receiver = new SimpleReceiver("BrokenReceiver", SimpleReceiver.BROKEN);
+      assertTrue(queue.add(receiver));
+
+      stored = queue.browse();
+      assertEquals(1, stored.size());
+      Message sm = (Message)stored.iterator().next();
+      assertTrue(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+
+      assertTrue(receiver.getMessages().isEmpty());
+   }
+
+   //////
+   ////// ACKING receiver
+   //////
+
+   public void testAddReceiver_5() throws Exception
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-recoverable channel, non-reliable message
+      Delivery delivery = queue.handle(observer, ref, null);
+      assertTrue(delivery.isDone());
+
+      List stored = queue.browse();
+      assertEquals(1, stored.size());
+
+      SimpleReceiver receiver =
+            new SimpleReceiver("ACKINGReceiver", SimpleReceiver.ACKING, queue);
+      assertTrue(queue.add(receiver));
+
+      // receiver explicitely asks for message
+      receiver.requestMessages();
+
+      assertTrue(queue.browse().isEmpty());
+
+      List messages = receiver.getMessages();
+      assertEquals(1, messages.size());
+      Message sm = (Message)messages.iterator().next();
+      assertTrue(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+   }
+
+   //////
+   ////// NACKING receiver
+   //////
+
+   public void testAddReceiver_6() throws Throwable
+   {
+      if (!queue.isRecoverable())
+      {
+         // we test only recoverable channels now
+         return;
+      }
+
+      // the channel has no receivers
+      assertFalse(queue.iterator().hasNext());
+
+      MessageReference ref = createReference(0, true, "payload");
+      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+
+      // non-recoverable channel, non-reliable message
+      Delivery delivery = queue.handle(observer, ref, null);
+      assertTrue(delivery.isDone());
+
+      List stored = queue.browse();
+      assertEquals(1, stored.size());
+
+      SimpleReceiver receiver =
+            new SimpleReceiver("NACKINGReceiver", SimpleReceiver.ACCEPTING, queue);
+      assertTrue(queue.add(receiver));
+
+      assertEquals(1, queue.browse().size());
+
+      // receiver explicitely asks for message
+      receiver.requestMessages();
+
+      assertEquals(1, queue.browse().size());
+
+      List messages = receiver.getMessages();
+      assertEquals(1, messages.size());
+      Message sm = (Message)messages.iterator().next();
+      assertTrue(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+
+      receiver.acknowledge(sm, null);
+
+      assertTrue(queue.browse().isEmpty());
+
+      messages = receiver.getMessages();
+      assertEquals(1, messages.size());
+      sm = (Message)messages.iterator().next();
+      assertTrue(sm.isReliable());
+      assertEquals(0, sm.getMessageID());
+   }
+
+
+
+
+   ///////////////////////////////
+   /////////////////////////////// Channel crash tests
+   ///////////////////////////////
+
+//   public void testReliableChannelFailure() throws Throwable
+//   {
+//      if (!channel.isRecoverable())
+//      {
+//         return;
+//      }
+//
+//      SimpleDeliveryObserver observer = new SimpleDeliveryObserver();
+//      SimpleReceiver r = new SimpleReceiver("ONE", SimpleReceiver.NACKING);
+//      channel.add(r);
+//
+//      Routable m = Factory.createMessage("m0", true, "payload");
+//      Delivery d = channel.handle(observer, ref, null);
+//      assertTrue(d.isDone());
+//
+//      List l = r.getMessages();
+//      assertEquals(1, l.size());
+//      Message rm  = (Message)l.get(0);
+//      assertEquals(rm.getMessageID(), m.getMessageID());
+//
+//      crashChannel();
+//
+//      recoverChannel();
+//
+//      // make sure the recovered channel still holds the message
+//
+//      l = channel.browse();
+//      assertEquals(1, l.size());
+//      MessageReference ref = (MessageReference)l.get(0);
+//      rm  = ref.getMessage();
+//      assertEquals(rm.getMessageID(), m.getMessageID());
+//
+//
+//      // TODO review this
+//      try
+//      {
+//         r.acknowledge(m, null);
+//         fail("should throw exception");
+//      }
+//      catch(IllegalStateException e)
+//      {
+//         // OK
+//      }
+//   }
+
+
+   // Distributor tests ---------------------------------------------
+
+   public void testAddOneReceiver()
+   {
+      Receiver r = new SimpleReceiver("ONE");
+
+      assertTrue(queue.add(r));
+      assertFalse(queue.add(r));
+
+      assertTrue(queue.contains(r));
+
+      Iterator i = queue.iterator();
+      assertEquals(r, i.next());
+      assertFalse(i.hasNext());
+
+      queue.clear();
+      assertFalse(queue.iterator().hasNext());
+   }
+
+   public void testRemoveInexistentReceiver()
+   {
+      assertFalse(queue.remove(new SimpleReceiver("INEXISTENT")));
+   }
+
+
+   // Package protected ---------------------------------------------
+   
+   // Protected -----------------------------------------------------
+
+   protected abstract void crashChannel() throws Exception;
+
+   protected abstract void recoverChannel() throws Exception;
+
+   // Private -------------------------------------------------------
+   
+   private MessageReference createReference(long id, boolean reliable, Serializable payload)
+   {
+      return createReference(id, reliable, payload);
+   }
+   
+   private MessageReference createReference(long id)
+   {
+      return createReference(id);
+   }
+   
+   // Inner classes -------------------------------------------------
+
+}

Deleted: trunk/tests/src/org/jboss/test/messaging/core/local/MessageQueueWithFilterTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/local/MessageQueueWithFilterTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/local/MessageQueueWithFilterTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -1,152 +0,0 @@
-/*
-  * 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.test.messaging.core.local;
-
-import org.jboss.messaging.core.Filter;
-import org.jboss.messaging.core.Message;
-import org.jboss.messaging.core.Routable;
-import org.jboss.messaging.core.local.MessageQueue;
-import org.jboss.messaging.core.message.CoreMessage;
-import org.jboss.messaging.core.plugin.JDBCPersistenceManager;
-import org.jboss.messaging.core.plugin.SimpleMessageStore;
-import org.jboss.messaging.core.plugin.contract.MessageStore;
-import org.jboss.messaging.core.plugin.contract.PersistenceManager;
-import org.jboss.test.messaging.MessagingTestCase;
-import org.jboss.test.messaging.tools.jmx.ServiceContainer;
-
-import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
-
-/**
- * 
- * A MessageQueueWithFilterTest.
- * 
- * @author <a href="tim.fox at jboss.com">Tim Fox</a>
- * @version $Revision$
- *
- * $Id$
- */
-public class MessageQueueWithFilterTest extends MessagingTestCase
-{
-   public MessageQueueWithFilterTest(String name)
-   {
-      super(name);
-   }
-
-   protected PersistenceManager pm;
-   
-   protected MessageStore ms;
-   
-   protected ServiceContainer sc;
-    
-   // ChannelTestBase overrides  ------------------------------------
-
-   public void setUp() throws Exception
-   {
-      super.setUp();
-      
-      sc = new ServiceContainer("all,-remoting,-security");
-      sc.start();
-      
-      pm = new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager());
-      pm.start();
-      
-      ms = new SimpleMessageStore();
-            
-      log.debug("setup done");
-   }
-
-   public void tearDown() throws Exception
-   {
-      pm.stop();
-      
-      sc.stop();
-
-      super.tearDown();
-   }
-   
-
-   public void testWithFilter()
-   {
-      Filter f = new SimpleFilter(3);
-      
-      MessageQueue messageQueue = new MessageQueue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(),
-                                                   f);
-       
-      Message m1 = new CoreMessage(1, false, 0, 0, (byte)0, null, null, 0);
-      Message m2 = new CoreMessage(2, false, 0, 0, (byte)0, null, null, 0);
-      Message m3 = new CoreMessage(3, false, 0, 0, (byte)0, null, null, 0);
-      Message m4 = new CoreMessage(4, false, 0, 0, (byte)0, null, null, 0);
-      Message m5 = new CoreMessage(5, false, 0, 0, (byte)0, null, null, 0);
-      
-      assertNull(messageQueue.handle(null, m1, null));
-      assertNull(messageQueue.handle(null, m2, null));
-      assertNotNull(messageQueue.handle(null, m3, null));
-      assertNull(messageQueue.handle(null, m4, null));
-      assertNull(messageQueue.handle(null, m5, null));
-      
-   }
-   
-   public void testWithoutFilter()
-   {
-      MessageQueue messageQueue = new MessageQueue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(),
-                                                   null);     
-      
-      Message m1 = new CoreMessage(1, false, 0, 0, (byte)0, null, null, 0);
-      Message m2 = new CoreMessage(2, false, 0, 0, (byte)0, null, null, 0);
-      Message m3 = new CoreMessage(3, false, 0, 0, (byte)0, null, null, 0);
-      Message m4 = new CoreMessage(4, false, 0, 0, (byte)0, null, null, 0);
-      Message m5 = new CoreMessage(5, false, 0, 0, (byte)0, null, null, 0);
-      
-      assertNotNull(messageQueue.handle(null, m1, null));
-      assertNotNull(messageQueue.handle(null, m2, null));
-      assertNotNull(messageQueue.handle(null, m3, null));
-      assertNotNull(messageQueue.handle(null, m4, null));
-      assertNotNull(messageQueue.handle(null, m5, null));
-      
-   }
-   
-   public void crashChannel() throws Exception
-   {
-   }
-
-   public void recoverChannel() throws Exception
-   {
-   }
-   
-   class SimpleFilter implements Filter
-   {
-      private long value;
-      SimpleFilter(long value)
-      {
-         this.value = value;
-      }
-      public boolean accept(Routable routable)
-      {
-         CoreMessage msg = (CoreMessage)routable;
-         return msg.getMessageID() == value;
-      }
-      public String getFilterString()
-      {
-         return null;
-      }
-   }
-}

Deleted: trunk/tests/src/org/jboss/test/messaging/core/local/NonRecoverableMessageQueueTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/local/NonRecoverableMessageQueueTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/local/NonRecoverableMessageQueueTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -1,89 +0,0 @@
-/*
-* 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.test.messaging.core.local;
-
-import org.jboss.messaging.core.local.MessageQueue;
-import org.jboss.test.messaging.core.base.MessageQueueTestBase;
-
-import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
-
-/**
- * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision$</tt>
- *
- * $Id$
- */
-public class NonRecoverableMessageQueueTest extends MessageQueueTestBase
-{
-   // Constants -----------------------------------------------------
-
-   // Static --------------------------------------------------------
-   
-   // Attributes ----------------------------------------------------
-
-  
-   // Constructors --------------------------------------------------
-
-   public NonRecoverableMessageQueueTest(String name)
-   {
-      super(name);
-   }
-
-   // ChannelTestBase overrides  ------------------------------------
-
-   public void setUp() throws Exception
-   {
-      super.setUp();
-      
-      messageQueue = new MessageQueue(1, ms, pm, true, false, 100, 20, 10, new QueuedExecutor(),
-                                      null);
-   }
-
-   public void tearDown() throws Exception
-   {
-      messageQueue.close();
-      super.tearDown();
-   }
-
-   public void crashChannel() throws Exception
-   {
-      messageQueue.close();
-   }
-
-   public void recoverChannel() throws Exception
-   {
-      messageQueue = new MessageQueue(1, ms, pm, true, false, 100, 20, 10, new QueuedExecutor(),
-                                      null);
-   }
-
-   // Public --------------------------------------------------------
-
-   // Package protected ---------------------------------------------
-   
-   // Protected -----------------------------------------------------
-   
-   // Private -------------------------------------------------------
-   
-   // Inner classes -------------------------------------------------   
-}
-

Copied: trunk/tests/src/org/jboss/test/messaging/core/local/NonRecoverableQueueTest.java (from rev 1264, trunk/tests/src/org/jboss/test/messaging/core/local/NonRecoverableMessageQueueTest.java)
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/local/NonRecoverableMessageQueueTest.java	2006-09-06 04:04:35 UTC (rev 1264)
+++ trunk/tests/src/org/jboss/test/messaging/core/local/NonRecoverableQueueTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,89 @@
+/*
+* 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.test.messaging.core.local;
+
+import org.jboss.messaging.core.local.Queue;
+import org.jboss.test.messaging.core.base.QueueTestBase;
+
+import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
+
+/**
+ * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision$</tt>
+ *
+ * $Id$
+ */
+public class NonRecoverableQueueTest extends QueueTestBase
+{
+   // Constants -----------------------------------------------------
+
+   // Static --------------------------------------------------------
+   
+   // Attributes ----------------------------------------------------
+
+  
+   // Constructors --------------------------------------------------
+
+   public NonRecoverableQueueTest(String name)
+   {
+      super(name);
+   }
+
+   // ChannelTestBase overrides  ------------------------------------
+
+   public void setUp() throws Exception
+   {
+      super.setUp();
+      
+      queue = new Queue(1, ms, pm, true, false, 100, 20, 10, new QueuedExecutor(),
+                                      null);
+   }
+
+   public void tearDown() throws Exception
+   {
+      queue.close();
+      super.tearDown();
+   }
+
+   public void crashChannel() throws Exception
+   {
+      queue.close();
+   }
+
+   public void recoverChannel() throws Exception
+   {
+      queue = new Queue(1, ms, pm, true, false, 100, 20, 10, new QueuedExecutor(),
+                                      null);
+   }
+
+   // Public --------------------------------------------------------
+
+   // Package protected ---------------------------------------------
+   
+   // Protected -----------------------------------------------------
+   
+   // Private -------------------------------------------------------
+   
+   // Inner classes -------------------------------------------------   
+}
+

Added: trunk/tests/src/org/jboss/test/messaging/core/local/QueueWithFilterTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/local/QueueWithFilterTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/local/QueueWithFilterTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,157 @@
+/*
+  * 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.test.messaging.core.local;
+
+import org.jboss.messaging.core.Filter;
+import org.jboss.messaging.core.Message;
+import org.jboss.messaging.core.Routable;
+import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.message.CoreMessage;
+import org.jboss.messaging.core.plugin.JDBCPersistenceManager;
+import org.jboss.messaging.core.plugin.SimpleMessageStore;
+import org.jboss.messaging.core.plugin.contract.MessageStore;
+import org.jboss.messaging.core.plugin.contract.PersistenceManager;
+import org.jboss.test.messaging.MessagingTestCase;
+import org.jboss.test.messaging.tools.jmx.ServiceContainer;
+
+import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
+
+/**
+ * 
+ * A QueueWithFilterTest.
+ * 
+ * @author <a href="tim.fox at jboss.com">Tim Fox</a>
+ * @version $Revision: 1237 $
+ *
+ * $Id: queueWithFilterTest.java 1237 2006-08-30 18:36:36Z timfox $
+ */
+public class QueueWithFilterTest extends MessagingTestCase
+{
+   public QueueWithFilterTest(String name)
+   {
+      super(name);
+   }
+
+   protected PersistenceManager pm;
+   
+   protected MessageStore ms;
+   
+   protected ServiceContainer sc;
+    
+   // ChannelTestBase overrides  ------------------------------------
+
+   public void setUp() throws Exception
+   {
+      super.setUp();
+      
+      sc = new ServiceContainer("all,-remoting,-security");
+      sc.start();
+      
+      pm =
+         new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager(), null,
+                                    true, true, true, 100);      
+      pm.start();
+      
+      ms = new SimpleMessageStore();
+      ms.start();
+            
+      log.debug("setup done");
+   }
+
+   public void tearDown() throws Exception
+   {
+      pm.stop();
+      
+      ms.stop();
+      
+      sc.stop();
+      
+      super.tearDown();
+   }
+   
+
+   public void testWithFilter()
+   {
+      Filter f = new SimpleFilter(3);
+      
+      Queue queue = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(),
+                                                   f);
+       
+      Message m1 = new CoreMessage(1, false, 0, 0, (byte)0, null, null, 0);
+      Message m2 = new CoreMessage(2, false, 0, 0, (byte)0, null, null, 0);
+      Message m3 = new CoreMessage(3, false, 0, 0, (byte)0, null, null, 0);
+      Message m4 = new CoreMessage(4, false, 0, 0, (byte)0, null, null, 0);
+      Message m5 = new CoreMessage(5, false, 0, 0, (byte)0, null, null, 0);
+      
+      assertNull(queue.handle(null, ms.reference(m1), null));
+      assertNull(queue.handle(null, ms.reference(m2), null));
+      assertNotNull(queue.handle(null, ms.reference(m3), null));
+      assertNull(queue.handle(null, ms.reference(m4), null));
+      assertNull(queue.handle(null, ms.reference(m5), null));
+      
+   }
+   
+   public void testWithoutFilter()
+   {
+      Queue queue = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(),
+                                                   null);     
+      
+      Message m1 = new CoreMessage(1, false, 0, 0, (byte)0, null, null, 0);
+      Message m2 = new CoreMessage(2, false, 0, 0, (byte)0, null, null, 0);
+      Message m3 = new CoreMessage(3, false, 0, 0, (byte)0, null, null, 0);
+      Message m4 = new CoreMessage(4, false, 0, 0, (byte)0, null, null, 0);
+      Message m5 = new CoreMessage(5, false, 0, 0, (byte)0, null, null, 0);
+      
+      assertNotNull(queue.handle(null, ms.reference(m1), null));
+      assertNotNull(queue.handle(null, ms.reference(m2), null));
+      assertNotNull(queue.handle(null, ms.reference(m3), null));
+      assertNotNull(queue.handle(null, ms.reference(m4), null));
+      assertNotNull(queue.handle(null, ms.reference(m5), null));
+      
+   }
+   
+   public void crashChannel() throws Exception
+   {
+   }
+
+   public void recoverChannel() throws Exception
+   {
+   }
+   
+   class SimpleFilter implements Filter
+   {
+      private long value;
+      SimpleFilter(long value)
+      {
+         this.value = value;
+      }
+      public boolean accept(Routable routable)
+      {
+         CoreMessage msg = (CoreMessage)routable;
+         return msg.getMessageID() == value;
+      }
+      public String getFilterString()
+      {
+         return null;
+      }
+   }
+}

Deleted: trunk/tests/src/org/jboss/test/messaging/core/local/RecoverableMessageQueueTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/local/RecoverableMessageQueueTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/local/RecoverableMessageQueueTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -1,88 +0,0 @@
-/*
-* 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.test.messaging.core.local;
-
-import org.jboss.messaging.core.local.MessageQueue;
-import org.jboss.test.messaging.core.base.MessageQueueTestBase;
-
-import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
-
-/**
- * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision: 1019 $</tt>
- *
- * $Id: RecoverableQueueTest.java 1019 2006-07-17 17:15:04Z timfox $
- */
-public class RecoverableMessageQueueTest extends MessageQueueTestBase
-{
-   // Constants -----------------------------------------------------
-
-   // Static --------------------------------------------------------
-   
-   // Attributes ----------------------------------------------------
-
-  
-   // Constructors --------------------------------------------------
-
-   public RecoverableMessageQueueTest(String name)
-   {
-      super(name);
-   }
-
-   // ChannelTestBase overrides  ------------------------------------
-
-   public void setUp() throws Exception
-   {
-      super.setUp();
-      
-      messageQueue = new MessageQueue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(),
-                                      null);
-   }
-
-   public void tearDown() throws Exception
-   {
-      messageQueue.close();
-      super.tearDown();
-   }
-
-   public void crashChannel() throws Exception
-   {
-      messageQueue.close();
-   }
-
-   public void recoverChannel() throws Exception
-   {
-      messageQueue = new MessageQueue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(),
-                                      null);
-   }
-
-   // Public --------------------------------------------------------
-
-   // Package protected ---------------------------------------------
-   
-   // Protected -----------------------------------------------------
-   
-   // Private -------------------------------------------------------
-   
-   // Inner classes -------------------------------------------------   
-}

Copied: trunk/tests/src/org/jboss/test/messaging/core/local/RecoverableQueueTest.java (from rev 1264, trunk/tests/src/org/jboss/test/messaging/core/local/RecoverableMessageQueueTest.java)
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/local/RecoverableMessageQueueTest.java	2006-09-06 04:04:35 UTC (rev 1264)
+++ trunk/tests/src/org/jboss/test/messaging/core/local/RecoverableQueueTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,88 @@
+/*
+* 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.test.messaging.core.local;
+
+import org.jboss.messaging.core.local.Queue;
+import org.jboss.test.messaging.core.base.QueueTestBase;
+
+import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
+
+/**
+ * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1019 $</tt>
+ *
+ * $Id: RecoverableQueueTest.java 1019 2006-07-17 17:15:04Z timfox $
+ */
+public class RecoverableQueueTest extends QueueTestBase
+{
+   // Constants -----------------------------------------------------
+
+   // Static --------------------------------------------------------
+   
+   // Attributes ----------------------------------------------------
+
+  
+   // Constructors --------------------------------------------------
+
+   public RecoverableQueueTest(String name)
+   {
+      super(name);
+   }
+
+   // ChannelTestBase overrides  ------------------------------------
+
+   public void setUp() throws Exception
+   {
+      super.setUp();
+      
+      queue = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(),
+                                      null);
+   }
+
+   public void tearDown() throws Exception
+   {
+      queue.close();
+      super.tearDown();
+   }
+
+   public void crashChannel() throws Exception
+   {
+      queue.close();
+   }
+
+   public void recoverChannel() throws Exception
+   {
+      queue = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(),
+                                      null);
+   }
+
+   // Public --------------------------------------------------------
+
+   // Package protected ---------------------------------------------
+   
+   // Protected -----------------------------------------------------
+   
+   // Private -------------------------------------------------------
+   
+   // Inner classes -------------------------------------------------   
+}

Modified: trunk/tests/src/org/jboss/test/messaging/core/local/RoundRobinPointToPointRouterTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/local/RoundRobinPointToPointRouterTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/local/RoundRobinPointToPointRouterTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -25,7 +25,6 @@
 import org.jboss.messaging.core.DeliveryObserver;
 import org.jboss.messaging.core.MessageReference;
 import org.jboss.messaging.core.Receiver;
-import org.jboss.messaging.core.Routable;
 import org.jboss.messaging.core.Router;
 import org.jboss.messaging.core.SimpleDelivery;
 import org.jboss.messaging.core.local.RoundRobinPointToPointRouter;
@@ -473,7 +472,7 @@
       
       boolean gotRef;
 
-      public Delivery handle(DeliveryObserver observer, Routable routable, Transaction tx)
+      public Delivery handle(DeliveryObserver observer, MessageReference ref, Transaction tx)
       {
          if (closed)
          {
@@ -502,7 +501,7 @@
          lock = new Object();
       }
 
-      public Delivery handle(DeliveryObserver observer, Routable routable, Transaction tx)
+      public Delivery handle(DeliveryObserver observer, MessageReference ref, Transaction tx)
       {
          // The delivering thread needs to grab the receiver's lock to complete delivery; this
          // is how Messaging receivers are written, anyway. We simulate the race condition by

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_2PCTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_2PCTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_2PCTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -25,7 +25,7 @@
 
 import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.MessageReference;
-import org.jboss.messaging.core.local.MessageQueue;
+import org.jboss.messaging.core.local.Queue;
 import org.jboss.messaging.core.message.MessageFactory;
 import org.jboss.messaging.core.plugin.LockMap;
 import org.jboss.messaging.core.tx.Transaction;
@@ -64,9 +64,9 @@
    
    public void testChannelShareNP_2PC() throws Throwable
    {
-      MessageQueue queue1 = new MessageQueue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
+      Queue queue1 = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
       
-      MessageQueue queue2 = new MessageQueue(2, ms, pm, true, true, 50, 10, 5, new QueuedExecutor(), null);
+      Queue queue2 = new Queue(2, ms, pm, true, true, 50, 10, 5, new QueuedExecutor(), null);
                       
       Message[] msgs = new Message[150];
       

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_NTTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_NTTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_NTTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -25,7 +25,7 @@
 
 import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.MessageReference;
-import org.jboss.messaging.core.local.MessageQueue;
+import org.jboss.messaging.core.local.Queue;
 import org.jboss.messaging.core.message.MessageFactory;
 import org.jboss.messaging.core.plugin.LockMap;
 
@@ -63,9 +63,9 @@
    
    public void test1() throws Throwable
    {
-      MessageQueue queue1 = new MessageQueue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
+      Queue queue1 = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
       
-      MessageQueue queue2 = new MessageQueue(2, ms, pm, true, true, 50, 10, 5, new QueuedExecutor(), null);
+      Queue queue2 = new Queue(2, ms, pm, true, true, 50, 10, 5, new QueuedExecutor(), null);
                   
       Message[] msgs = new Message[150];
       

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_TTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_TTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_TTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -25,7 +25,7 @@
 
 import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.MessageReference;
-import org.jboss.messaging.core.local.MessageQueue;
+import org.jboss.messaging.core.local.Queue;
 import org.jboss.messaging.core.message.MessageFactory;
 import org.jboss.messaging.core.plugin.LockMap;
 import org.jboss.messaging.core.tx.Transaction;
@@ -64,9 +64,9 @@
    
    public void testChannelShareNP_Transactional() throws Throwable
    {
-      MessageQueue queue1 = new MessageQueue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
+      Queue queue1 = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
       
-      MessageQueue queue2 = new MessageQueue(2, ms, pm, true, true, 50, 10, 5, new QueuedExecutor(), null);
+      Queue queue2 = new Queue(2, ms, pm, true, true, 50, 10, 5, new QueuedExecutor(), null);
                                
       Message[] msgs = new Message[150];
       

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_2PCTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_2PCTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_2PCTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -25,7 +25,7 @@
 
 import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.MessageReference;
-import org.jboss.messaging.core.local.MessageQueue;
+import org.jboss.messaging.core.local.Queue;
 import org.jboss.messaging.core.message.MessageFactory;
 import org.jboss.messaging.core.plugin.LockMap;
 import org.jboss.messaging.core.tx.Transaction;
@@ -59,9 +59,9 @@
    
    public void test1() throws Throwable
    {
-      MessageQueue queue1 = new MessageQueue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
+      Queue queue1 = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
       
-      MessageQueue queue2 = new MessageQueue(2, ms, pm, true, true, 50, 10, 5, new QueuedExecutor(), null);
+      Queue queue2 = new Queue(2, ms, pm, true, true, 50, 10, 5, new QueuedExecutor(), null);
                             
       Message[] msgs = new Message[150];
       

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_NTTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_NTTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_NTTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -25,7 +25,7 @@
 
 import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.MessageReference;
-import org.jboss.messaging.core.local.MessageQueue;
+import org.jboss.messaging.core.local.Queue;
 import org.jboss.messaging.core.message.MessageFactory;
 import org.jboss.messaging.core.plugin.LockMap;
 
@@ -63,9 +63,9 @@
    
    public void test1() throws Throwable
    {
-      MessageQueue queue1 = new MessageQueue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
+      Queue queue1 = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
       
-      MessageQueue queue2 = new MessageQueue(2, ms, pm, true, true, 50, 10, 5, new QueuedExecutor(), null);
+      Queue queue2 = new Queue(2, ms, pm, true, true, 50, 10, 5, new QueuedExecutor(), null);
                                 
       Message[] msgs = new Message[150];
       

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_TTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_TTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_TTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -25,7 +25,7 @@
 
 import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.MessageReference;
-import org.jboss.messaging.core.local.MessageQueue;
+import org.jboss.messaging.core.local.Queue;
 import org.jboss.messaging.core.message.MessageFactory;
 import org.jboss.messaging.core.plugin.LockMap;
 import org.jboss.messaging.core.tx.Transaction;
@@ -63,9 +63,9 @@
    
    public void test1() throws Throwable
    {
-      MessageQueue queue1 = new MessageQueue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
+      Queue queue1 = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
       
-      MessageQueue queue2 = new MessageQueue(2, ms, pm, true, true, 50, 10, 5, new QueuedExecutor(), null);
+      Queue queue2 = new Queue(2, ms, pm, true, true, 50, 10, 5, new QueuedExecutor(), null);
                             
       Message[] msgs = new Message[150];
       

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/PagingStateTestBase.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/PagingStateTestBase.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/PagingStateTestBase.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -37,7 +37,6 @@
 import org.jboss.messaging.core.DeliveryObserver;
 import org.jboss.messaging.core.MessageReference;
 import org.jboss.messaging.core.Receiver;
-import org.jboss.messaging.core.Routable;
 import org.jboss.messaging.core.SimpleDelivery;
 import org.jboss.messaging.core.plugin.IdManager;
 import org.jboss.messaging.core.plugin.JDBCPersistenceManager;
@@ -64,10 +63,8 @@
 {
    // Constants -----------------------------------------------------
 
-
    // Static --------------------------------------------------------
-   
-      
+         
    // Attributes ----------------------------------------------------
 
    protected ServiceContainer sc;
@@ -96,25 +93,25 @@
       sc = new ServiceContainer("all,-remoting,-security");
       sc.start();
 
-      pm = new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager());            
-        
-      ((JDBCPersistenceManager)pm).start();
-
-      ms = new SimpleMessageStore();
+      pm =
+         new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager(), null,
+                                    true, true, true, 100);      
+      pm.start();
       
-      tr = new TransactionRepository();      
+      tr = new TransactionRepository(pm, new IdManager("TRANSACTION_ID", 10, pm));
+      tr.start();
       
-      tr.injectAttributes(pm, new IdManager("TRANSACTION_ID", 10, pm));
+      ms = new SimpleMessageStore();
+      ms.start();
    }
    
    
    public void tearDown() throws Exception
    {
-      ((JDBCPersistenceManager)pm).stop();
-      pm = null;
+      pm.stop();
+      tr.stop();
+      ms.stop();
       sc.stop();
-      sc = null;
-      ms = null;
       
       super.tearDown();
    }
@@ -172,15 +169,13 @@
          this.dels = new SimpleDelivery[numToConsume];
       }
 
-      public synchronized Delivery handle(DeliveryObserver observer, Routable routable, Transaction tx)
+      public synchronized Delivery handle(DeliveryObserver observer, MessageReference ref, Transaction tx)
       {  
          if (count >= numToConsume)
          {
             return null;
          }
          
-         MessageReference ref = (MessageReference)routable;
-         
          assertEquals(refs[consumeCount + count].getMessageID(), ref.getMessageID());
          
          SimpleDelivery del = new SimpleDelivery(observer, ref);
@@ -267,15 +262,13 @@
          
       }
 
-      public synchronized Delivery handle(DeliveryObserver observer, Routable routable, Transaction tx)
+      public synchronized Delivery handle(DeliveryObserver observer, MessageReference ref, Transaction tx)
       {
          if (count == numToCancel)
          {
             return null;
          }
          
-         MessageReference ref = (MessageReference)routable;
-         
          SimpleDelivery del = new SimpleDelivery(observer, ref);
          
          toCancel[count] = del;                  

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/PagingTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/PagingTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/PagingTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -21,15 +21,15 @@
 */
 package org.jboss.test.messaging.core.paging;
 
+import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.message.CoreMessage;
+import org.jboss.messaging.core.message.MessageFactory;
+import org.jboss.messaging.core.plugin.JDBCPersistenceManager;
+import org.jboss.messaging.core.plugin.SimpleMessageStore;
+import org.jboss.messaging.core.plugin.contract.MessageStore;
+import org.jboss.messaging.core.plugin.contract.PersistenceManager;
 import org.jboss.test.messaging.MessagingTestCase;
 import org.jboss.test.messaging.tools.jmx.ServiceContainer;
-import org.jboss.messaging.core.plugin.contract.MessageStore;
-import org.jboss.messaging.core.plugin.contract.PersistenceManager;
-import org.jboss.messaging.core.plugin.JDBCPersistenceManager;
-import org.jboss.messaging.core.plugin.SimpleMessageStore;
-import org.jboss.messaging.core.message.CoreMessage;
-import org.jboss.messaging.core.message.MessageFactory;
-import org.jboss.messaging.core.local.MessageQueue;
 
 import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
 
@@ -63,15 +63,15 @@
 
    public void testPaging() throws Exception
    {
-      MessageQueue p = new MessageQueue(0, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
+      Queue p = new Queue(0, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
 
       CoreMessage m = null;
 
       m = MessageFactory.createCoreMessage(0);
-      p.handle(null, m, null);
+      p.handle(null, ms.reference(m), null);
 
       m = MessageFactory.createCoreMessage(1);
-      p.handle(null, m, null);
+      p.handle(null, ms.reference(m), null);
 
    }
 
@@ -85,17 +85,21 @@
       sc = new ServiceContainer("all,-remoting,-security");
       sc.start();
 
-      pm = new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager());
+      pm =
+         new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager(), null,
+                                    true, true, true, 100);      
       pm.start();
+            
       ms = new SimpleMessageStore();
+      ms.start();
    }
 
    public void tearDown() throws Exception
    {
-      ms = null;
-      pm = null;
+      pm.stop();
+      ms.stop();
       sc.stop();
-      sc = null;
+
       super.tearDown();
    }
 

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_2PCTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_2PCTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_2PCTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -26,7 +26,7 @@
 import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.MessageReference;
 import org.jboss.messaging.core.SimpleDelivery;
-import org.jboss.messaging.core.local.MessageQueue;
+import org.jboss.messaging.core.local.Queue;
 import org.jboss.messaging.core.message.MessageFactory;
 import org.jboss.messaging.core.plugin.LockMap;
 import org.jboss.messaging.core.tx.Transaction;
@@ -66,7 +66,7 @@
    
    public void test1() throws Throwable
    {
-      MessageQueue queue = new MessageQueue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
+      Queue queue = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
                
       Message[] msgs = new Message[241];
       

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_NTTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_NTTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_NTTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -26,7 +26,7 @@
 import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.MessageReference;
 import org.jboss.messaging.core.SimpleDelivery;
-import org.jboss.messaging.core.local.MessageQueue;
+import org.jboss.messaging.core.local.Queue;
 import org.jboss.messaging.core.message.MessageFactory;
 import org.jboss.messaging.core.plugin.LockMap;
 
@@ -65,7 +65,7 @@
    
    public void test1() throws Throwable
    {
-      MessageQueue queue = new MessageQueue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
+      Queue queue = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
                            
       Message[] msgs = new Message[241];
       

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_TTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_TTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_TTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -26,7 +26,7 @@
 import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.MessageReference;
 import org.jboss.messaging.core.SimpleDelivery;
-import org.jboss.messaging.core.local.MessageQueue;
+import org.jboss.messaging.core.local.Queue;
 import org.jboss.messaging.core.message.MessageFactory;
 import org.jboss.messaging.core.plugin.LockMap;
 import org.jboss.messaging.core.tx.Transaction;
@@ -66,7 +66,7 @@
  
    public void test1() throws Throwable
    {
-      MessageQueue queue = new MessageQueue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
+      Queue queue = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
                     
       Message[] msgs = new Message[241];
       

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_2PCTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_2PCTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_2PCTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -26,7 +26,7 @@
 import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.MessageReference;
 import org.jboss.messaging.core.SimpleDelivery;
-import org.jboss.messaging.core.local.MessageQueue;
+import org.jboss.messaging.core.local.Queue;
 import org.jboss.messaging.core.message.MessageFactory;
 import org.jboss.messaging.core.plugin.LockMap;
 import org.jboss.messaging.core.tx.Transaction;
@@ -66,7 +66,7 @@
    
    public void test1() throws Throwable
    {
-      MessageQueue queue = new MessageQueue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
+      Queue queue = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
                     
       Message[] msgs = new Message[241];
       

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_NTTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_NTTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_NTTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -26,7 +26,7 @@
 import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.MessageReference;
 import org.jboss.messaging.core.SimpleDelivery;
-import org.jboss.messaging.core.local.MessageQueue;
+import org.jboss.messaging.core.local.Queue;
 import org.jboss.messaging.core.message.MessageFactory;
 import org.jboss.messaging.core.plugin.LockMap;
 
@@ -65,7 +65,7 @@
    
    public void test1() throws Throwable
    {
-      MessageQueue queue = new MessageQueue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
+      Queue queue = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
                         
       Message[] msgs = new Message[241];
       

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_TTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_TTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_TTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -26,7 +26,7 @@
 import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.MessageReference;
 import org.jboss.messaging.core.SimpleDelivery;
-import org.jboss.messaging.core.local.MessageQueue;
+import org.jboss.messaging.core.local.Queue;
 import org.jboss.messaging.core.message.MessageFactory;
 import org.jboss.messaging.core.plugin.LockMap;
 import org.jboss.messaging.core.tx.Transaction;
@@ -66,7 +66,7 @@
    
    public void test1() throws Throwable
    {
-      MessageQueue queue = new MessageQueue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
+      Queue queue = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
                   
       Message[] msgs = new Message[241];
       

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_ReloadTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_ReloadTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_ReloadTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -25,8 +25,9 @@
 
 import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.MessageReference;
-import org.jboss.messaging.core.local.MessageQueue;
+import org.jboss.messaging.core.local.Queue;
 import org.jboss.messaging.core.message.MessageFactory;
+import org.jboss.messaging.core.plugin.IdManager;
 import org.jboss.messaging.core.plugin.JDBCPersistenceManager;
 import org.jboss.messaging.core.plugin.LockMap;
 import org.jboss.messaging.core.plugin.SimpleMessageStore;
@@ -65,7 +66,7 @@
    
    public void testRecoverableQueueCrash() throws Throwable
    {
-      MessageQueue queue = new MessageQueue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
+      Queue queue = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
       
       Message[] msgs = new Message[200];
       
@@ -111,17 +112,21 @@
       //This is what would happen if the server crashed
        
       pm.stop();
+      tr.stop();
+      ms.stop();
       
       pm =
-         new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager());
-
-      ((JDBCPersistenceManager)pm).start();
-
+         new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager(), null,
+                                    true, true, true, 100);      
+      pm.start();
+      
+      tr = new TransactionRepository(pm, new IdManager("TRANSACTION_ID", 10, pm));
+      tr.start();
+      
       ms = new SimpleMessageStore();
-      
-      tr = new TransactionRepository();
+      ms.start();
        
-      MessageQueue queue2 = new MessageQueue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
+      Queue queue2 = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
       
       queue2.load();
       
@@ -150,7 +155,7 @@
    {
       //Non recoverable queue - eg temporary queue
       
-      MessageQueue queue = new MessageQueue(1, ms, pm, true, false, 100, 20, 10, new QueuedExecutor(), null);
+      Queue queue = new Queue(1, ms, pm, true, false, 100, 20, 10, new QueuedExecutor(), null);
 
       Message[] msgs = new Message[200];
       
@@ -196,18 +201,22 @@
       //This is what would happen if the server crashed
 
       pm.stop();
+      tr.stop();
+      ms.stop();
       
       pm =
-         new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager());
-
-      ((JDBCPersistenceManager)pm).start();
-
+         new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager(), null,
+                                    true, true, true, 100);      
+      pm.start();
+      
+      tr = new TransactionRepository(pm, new IdManager("TRANSACTION_ID", 10, pm));
+      tr.start();
+      
       ms = new SimpleMessageStore();
+      ms.start();
       
-      tr = new TransactionRepository();
+      Queue queue2 = new Queue(1, ms, pm, true, false, 100, 20, 10, new QueuedExecutor(), null);
       
-      MessageQueue queue2 = new MessageQueue(1, ms, pm, true, false, 100, 20, 10, new QueuedExecutor(), null);
-      
       queue2.load();
       
       refIds = getReferenceIdsOrderedByPageOrd(queue.getChannelID());
@@ -233,7 +242,7 @@
    {
       //Non recoverable queue - eg temporary queue
       
-      MessageQueue queue = new MessageQueue(1, ms, pm, true, false, 100, 20, 10, new QueuedExecutor(), null);
+      Queue queue = new Queue(1, ms, pm, true, false, 100, 20, 10, new QueuedExecutor(), null);
       
       Message[] msgs = new Message[200];
       
@@ -297,7 +306,7 @@
    
    public void testQueueReloadWithSmallerFullSize() throws Throwable
    {
-      MessageQueue queue = new MessageQueue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
+      Queue queue = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
 
       Message[] msgs = new Message[150];
       
@@ -335,19 +344,23 @@
       //Stop and restart the persistence manager
 
       pm.stop();
+      tr.stop();
+      ms.stop();
       
       pm =
-         new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager());
-
-      ((JDBCPersistenceManager)pm).start();
-
+         new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager(), null,
+                                    true, true, true, 100);      
+      pm.start();
+      
+      tr = new TransactionRepository(pm, new IdManager("TRANSACTION_ID", 10, pm));
+      tr.start();
+      
       ms = new SimpleMessageStore();
+      ms.start();
       
-      tr = new TransactionRepository();
-      
       //Reload the queue with a smaller fullSize
       
-      MessageQueue queue2 = new MessageQueue(1, ms, pm, true, false, 50, 20, 10, new QueuedExecutor(), null);
+      Queue queue2 = new Queue(1, ms, pm, true, false, 50, 20, 10, new QueuedExecutor(), null);
       
       queue2.load();
       
@@ -391,7 +404,7 @@
    
    public void testReloadWithLargerFullSize() throws Throwable
    {
-      MessageQueue queue = new MessageQueue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
+      Queue queue = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor(), null);
 
       Message[] msgs = new Message[150];
       
@@ -429,19 +442,23 @@
       //Stop and restart the persistence manager
 
       pm.stop();
+      tr.stop();
+      ms.stop();
       
       pm =
-         new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager());
-
-      ((JDBCPersistenceManager)pm).start();
-
+         new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager(), null,
+                                    true, true, true, 100);      
+      pm.start();
+      
+      tr = new TransactionRepository(pm, new IdManager("TRANSACTION_ID", 10, pm));
+      tr.start();
+      
       ms = new SimpleMessageStore();
+      ms.start();
       
-      tr = new TransactionRepository();
-      
       //Reload the queue with a smaller fullSize
       
-      MessageQueue queue2 = new MessageQueue(1, ms, pm, true, false, 130, 20, 10, new QueuedExecutor(), null);
+      Queue queue2 = new Queue(1, ms, pm, true, false, 130, 20, 10, new QueuedExecutor(), null);
       
       queue2.load();
       

Added: trunk/tests/src/org/jboss/test/messaging/core/plugin/ClusteredPostOfficeTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/plugin/ClusteredPostOfficeTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/plugin/ClusteredPostOfficeTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,1235 @@
+/*
+  * 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.test.messaging.core.plugin;
+
+import java.util.List;
+
+import org.jboss.messaging.core.Message;
+import org.jboss.messaging.core.MessageReference;
+import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.message.MessageFactory;
+import org.jboss.messaging.core.plugin.contract.Binding;
+import org.jboss.messaging.core.plugin.contract.ClusteredPostOffice;
+import org.jboss.messaging.core.plugin.postoffice.cluster.ClusteredPostOfficeImpl;
+import org.jboss.messaging.core.tx.Transaction;
+import org.jboss.test.messaging.core.SimpleReceiver;
+
+import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
+
+/**
+ * 
+ * A ClusteredTopicExchangeTest
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class ClusteredPostOfficeTest extends SimplePostOfficeTest
+{
+   // Constants -----------------------------------------------------
+
+   // Static --------------------------------------------------------
+   
+   // Attributes ----------------------------------------------------
+   
+   // Constructors --------------------------------------------------
+
+   public ClusteredPostOfficeTest(String name)
+   {
+      super(name);
+   }
+
+   // Public --------------------------------------------------------
+
+   public void setUp() throws Exception
+   {
+      super.setUp();     
+            
+   }
+
+   public void tearDown() throws Exception
+   {           
+      super.tearDown();
+   }
+   
+   public final void testClusteredBindSameName() throws Throwable
+   {
+      ClusteredPostOffice office1 = null;
+      
+      ClusteredPostOffice office2 = null;
+      
+      try
+      {         
+         office1 = createClusteredPostOffice("node1", "testgroup");
+         
+         office2 = createClusteredPostOffice("node2", "testgroup");
+         
+         Queue queue1 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);
+         
+         Binding binding1 =
+            office1.bindQueue("sub1", "topic1", false, queue1);
+                  
+         try
+         {
+            office2.bindQueue("sub1", "topic1", false, queue1);
+            fail();
+         }
+         catch (IllegalArgumentException e)
+         {
+            //OK - this should fail
+         }
+      }
+      finally
+      {
+         if (office1 != null)
+         {
+            office1.stop();
+         }
+         
+         if (office2 != null)
+         {
+            office2.stop();
+         }
+      }
+   }
+   
+   
+   public final void testClusteredBindUnbind() throws Throwable
+   {
+      ClusteredPostOffice office1 = null;
+      
+      ClusteredPostOffice office2 = null;
+      
+      ClusteredPostOffice office3 = null;
+      
+      try
+      {         
+         //Start one exchange
+         
+         office1 = createClusteredPostOffice("node1", "testgroup");
+         
+         //Add a couple of bindings
+         
+         Queue queue1 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding1 =
+            office1.bindClusteredQueue("sub1", "topic1", false, queue1);
+         Queue queue2 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding2 =
+            office1.bindClusteredQueue("sub2", "topic1", false, queue2);
+         
+         //Start another exchange - make sure it picks up the bindings from the first node
+         
+         office2 = createClusteredPostOffice("node2", "testgroup");
+         
+         List bindings = office2.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(2, bindings.size());
+         
+         assertEquivalent(binding1, (Binding)bindings.get(0));
+         assertEquivalent(binding2, (Binding)bindings.get(1));         
+         
+         //Add another binding on node 2
+         
+         Queue queue3 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding3 =
+            office2.bindClusteredQueue("sub3", "topic1", false, queue3);
+  
+         //Make sure both nodes pick it up
+         
+         bindings = office1.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(3, bindings.size());
+         
+         assertEquivalent(binding1, (Binding)bindings.get(0));
+         assertEquivalent(binding2, (Binding)bindings.get(1));
+         assertEquivalent(binding3, (Binding)bindings.get(2));
+
+         bindings = office2.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(3, bindings.size());
+         
+         assertEquivalent(binding1, (Binding)bindings.get(0));
+         assertEquivalent(binding2, (Binding)bindings.get(1));
+         assertEquivalent(binding3, (Binding)bindings.get(2));
+
+         //Add another binding on node 1
+         
+         Queue queue4 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding4 =
+            office2.bindClusteredQueue("sub4", "topic1", false, queue4);
+         
+         // Make sure both nodes pick it up
+         
+         bindings = office1.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(4, bindings.size());
+         
+         assertEquivalent(binding1, (Binding)bindings.get(0));
+         assertEquivalent(binding2, (Binding)bindings.get(1));
+         assertEquivalent(binding3, (Binding)bindings.get(2));
+         assertEquivalent(binding4, (Binding)bindings.get(3));
+         
+         bindings = office2.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(4, bindings.size());
+         
+         assertEquivalent(binding1, (Binding)bindings.get(0));
+         assertEquivalent(binding2, (Binding)bindings.get(1));
+         assertEquivalent(binding3, (Binding)bindings.get(2));
+         assertEquivalent(binding4, (Binding)bindings.get(3));
+         
+         //Unbind binding 1 and binding 2
+         office1.unbindClusteredQueue("sub1");
+         office1.unbindClusteredQueue("sub2");
+         
+         //Make sure bindings are not longer available on either node
+         
+         bindings = office1.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(2, bindings.size());
+         
+         assertEquivalent(binding3, (Binding)bindings.get(0));
+         assertEquivalent(binding4, (Binding)bindings.get(1));
+   
+         bindings = office2.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(2, bindings.size());
+         
+         assertEquivalent(binding3, (Binding)bindings.get(0));
+         assertEquivalent(binding4, (Binding)bindings.get(1));
+         
+         //Add a third exchange
+                  
+         office3 = createClusteredPostOffice("node3", "testgroup");
+         
+         //Maks sure it picks up the bindings
+         
+         bindings = office3.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(2, bindings.size());
+         
+         assertEquivalent(binding3, (Binding)bindings.get(0));
+         assertEquivalent(binding4, (Binding)bindings.get(1));
+         
+         //Add another binding on node 3
+                  
+         Queue queue5 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding5 =
+            office3.bindClusteredQueue("sub5", "topic1", false, queue5);
+         
+         // Make sure all nodes pick it up
+         
+         bindings = office1.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(3, bindings.size());
+         
+         assertEquivalent(binding3, (Binding)bindings.get(0));
+         assertEquivalent(binding4, (Binding)bindings.get(1));
+         assertEquivalent(binding5, (Binding)bindings.get(2));
+         
+         bindings = office2.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(3, bindings.size());
+         
+         assertEquivalent(binding3, (Binding)bindings.get(0));
+         assertEquivalent(binding4, (Binding)bindings.get(1));
+         assertEquivalent(binding5, (Binding)bindings.get(2));
+         
+         bindings = office3.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(3, bindings.size());
+         
+         assertEquivalent(binding3, (Binding)bindings.get(0));
+         assertEquivalent(binding4, (Binding)bindings.get(1));
+         assertEquivalent(binding5, (Binding)bindings.get(2));
+         
+         //Add a durable and a non durable binding on node 1
+         
+         Queue queue6 = new Queue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding6 =
+            office1.bindClusteredQueue("sub6", "topic1", false, queue6);
+         
+         Queue queue7 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding7 =
+            office1.bindClusteredQueue("sub7", "topic1", false, queue7);
+         
+         // Make sure all nodes pick them up
+         
+         bindings = office1.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(5, bindings.size());
+         
+         assertEquivalent(binding3, (Binding)bindings.get(0));
+         assertEquivalent(binding4, (Binding)bindings.get(1));
+         assertEquivalent(binding5, (Binding)bindings.get(2));
+         assertEquivalent(binding6, (Binding)bindings.get(3));
+         assertEquivalent(binding7, (Binding)bindings.get(4));
+         
+         bindings = office2.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(5, bindings.size());
+         
+         assertEquivalent(binding3, (Binding)bindings.get(0));
+         assertEquivalent(binding4, (Binding)bindings.get(1));
+         assertEquivalent(binding5, (Binding)bindings.get(2));
+         assertEquivalent(binding6, (Binding)bindings.get(3));
+         assertEquivalent(binding7, (Binding)bindings.get(4));
+         
+         bindings = office3.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(5, bindings.size());
+         
+         assertEquivalent(binding3, (Binding)bindings.get(0));
+         assertEquivalent(binding4, (Binding)bindings.get(1));
+         assertEquivalent(binding5, (Binding)bindings.get(2));
+         assertEquivalent(binding6, (Binding)bindings.get(3));
+         assertEquivalent(binding7, (Binding)bindings.get(4));
+               
+         //Stop exchange 1
+         office1.stop();
+  
+         //Need to sleep since it may take some time for the view changed request to reach the
+         //members which causes the bindings to be removed
+         
+         Thread.sleep(1000);
+         
+         //All it's non durable bindings should be removed from the other nodes
+         //Durable bindings should remain
+         
+         bindings = office2.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(4, bindings.size());
+         
+         assertEquivalent(binding3, (Binding)bindings.get(0));
+         assertEquivalent(binding4, (Binding)bindings.get(1));
+         assertEquivalent(binding5, (Binding)bindings.get(2));
+         assertEquivalent(binding6, (Binding)bindings.get(3));
+         
+         bindings = office3.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(4, bindings.size());
+         
+         assertEquivalent(binding3, (Binding)bindings.get(0));
+         assertEquivalent(binding4, (Binding)bindings.get(1));
+         assertEquivalent(binding5, (Binding)bindings.get(2));
+         assertEquivalent(binding6, (Binding)bindings.get(3));
+         
+         //Stop exchange 2
+         office2.stop();
+         
+         bindings = office3.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(2, bindings.size());
+         
+         assertEquivalent(binding5, (Binding)bindings.get(0));
+         assertEquivalent(binding6, (Binding)bindings.get(1));
+         
+         //Restart exchange 1 and exchange 2
+         office1 = createClusteredPostOffice("node1", "testgroup");
+         
+         office2 = createClusteredPostOffice("node2", "testgroup");
+         
+         bindings = office1.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(2, bindings.size());
+         
+         assertEquivalent(binding5, (Binding)bindings.get(0));
+         assertEquivalent(binding6, (Binding)bindings.get(1));
+         
+         bindings = office2.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(2, bindings.size());
+         
+         assertEquivalent(binding5, (Binding)bindings.get(0));
+         assertEquivalent(binding6, (Binding)bindings.get(1));
+         
+         bindings = office3.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(2, bindings.size());
+         
+         assertEquivalent(binding5, (Binding)bindings.get(0));
+         assertEquivalent(binding6, (Binding)bindings.get(1));
+         
+         //Stop all exchanges
+         
+         office1.stop();
+         office2.stop();
+         office3.stop();
+         
+         //Start them all
+         office1 = createClusteredPostOffice("node1", "testgroup");
+         office2 = createClusteredPostOffice("node2", "testgroup");
+         office3 = createClusteredPostOffice("node3", "testgroup");
+         
+         //Only the durable queue should survive
+         
+         bindings = office1.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(1, bindings.size());
+         
+         assertEquivalent(binding6, (Binding)bindings.get(0));
+         
+         bindings = office2.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(1, bindings.size());
+         
+         assertEquivalent(binding6, (Binding)bindings.get(0));
+         
+         bindings = office3.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(1, bindings.size());
+         
+         assertEquivalent(binding6, (Binding)bindings.get(0));
+                  
+      }
+      finally
+      {
+         if (office1 != null)
+         {
+            office1.unbindClusteredQueue("sub6");
+            office1.stop();
+         }
+         
+         if (office2 != null)
+         {
+            office2.stop();
+         }
+         
+         if (office3 != null)
+         {
+            office2.stop();
+         }
+      }
+      
+   }
+   
+   public final void testClusteredRoutePersistent() throws Throwable
+   {
+      clusteredRoute(true);
+   }
+   
+   public final void testClusteredRouteNonPersistent() throws Throwable
+   {
+      clusteredRoute(false);
+   }
+   
+   public final void testClusteredTransactionalRoutePersistent() throws Throwable
+   {
+      clusteredTransactionalRoute(true);
+   }
+   
+   public final void testClusteredTransactionalRouteNonPersistent() throws Throwable
+   {
+      clusteredTransactionalRoute(false);
+   }
+   
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+   
+
+   protected void clusteredRoute(boolean persistentMessage) throws Throwable
+   {
+      ClusteredPostOffice office1 = null;
+      
+      ClusteredPostOffice office2 = null;
+          
+      try
+      {   
+         office1 = createClusteredPostOffice("node1", "testgroup");
+         office2 = createClusteredPostOffice("node2", "testgroup");
+      
+         //Two topics with a mixture of durable and non durable subscriptions
+         
+         Queue[] queues = new Queue[16];
+         Binding[] bindings = new Binding[16];
+         
+         queues[0] = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[0] = office1.bindClusteredQueue("sub1", "topic1", false, queues[0]);
+         
+         queues[1] = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[1] = office1.bindClusteredQueue("sub2", "topic1", false, queues[1]);
+         
+         queues[2] = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[2] = office2.bindClusteredQueue("sub3", "topic1", false, queues[2]);
+         
+         queues[3] = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[3] = office2.bindClusteredQueue("sub4", "topic1", false, queues[3]);
+         
+         queues[4] = new Queue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[4] = office2.bindClusteredQueue("sub5", "topic1", false, queues[4]);
+         
+         queues[5] = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[5] = office1.bindClusteredQueue("sub6", "topic1", false, queues[5]);
+         
+         queues[6] = new Queue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[6] = office1.bindClusteredQueue("sub7", "topic1", false, queues[6]);
+         
+         queues[7] = new Queue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[7] = office1.bindClusteredQueue("sub8", "topic1", false, queues[7]);
+         
+         queues[8] = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[8] = office1.bindClusteredQueue("sub9", "topic2", false, queues[8]);
+         
+         queues[9] = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[9] = office1.bindClusteredQueue("sub10", "topic2", false, queues[9]);
+         
+         queues[10] = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[10] = office2.bindClusteredQueue("sub11", "topic2", false, queues[10]);
+         
+         queues[11] = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[11] = office2.bindClusteredQueue("sub12", "topic2", false, queues[11]);
+         
+         queues[12] = new Queue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[12] = office2.bindClusteredQueue("sub13", "topic2", false, queues[12]);
+         
+         queues[13] = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[13] = office1.bindClusteredQueue("sub14", "topic2", false, queues[13]);
+         
+         queues[14] = new Queue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[14] = office1.bindClusteredQueue("sub15", "topic2", false, queues[14]);
+         
+         queues[15] = new Queue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[15] = office1.bindClusteredQueue("sub16", "topic2", false, queues[15]);
+       
+         SimpleReceiver[] receivers = new SimpleReceiver[16];
+         
+         for (int i = 0; i < 16; i++)
+         {
+            receivers[i] = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
+            queues[i].add(receivers[i]);
+         }
+         
+         Message msg = MessageFactory.createCoreMessage(1, persistentMessage, null);      
+         MessageReference ref = ms.reference(msg);         
+
+         boolean routed = office1.route(ref, "topic1", null);         
+         assertTrue(routed);
+         
+         //Messages are sent asych so may take some finite time to arrive
+         Thread.sleep(1000);
+         
+         for (int i = 0; i < 8; i++)
+         {         
+            log.info("is is: " + i);
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertEquals(1, msgs.size());
+            Message msgRec = (Message)msgs.get(0);
+            assertEquals(msg.getMessageID(), msgRec.getMessageID());
+            receivers[i].acknowledge(msgRec, null);
+            msgs = queues[i].browse();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty()); 
+            receivers[i].clear();
+         }
+         
+         for (int i = 8; i < 16; i++)
+         {
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+            msgs = queues[i].browse();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+         }
+                  
+         //Now route to topic2
+         
+         msg = MessageFactory.createCoreMessage(2, persistentMessage, null);;      
+         ref = ms.reference(msg);         
+
+         routed = office1.route(ref, "topic2", null);         
+         assertTrue(routed);
+         //Messages are sent asych so may take some finite time to arrive
+         Thread.sleep(1000);
+         
+         for (int i = 0; i < 8; i++)
+         {
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+            msgs = queues[i].browse();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+         }
+         
+         for (int i = 8; i < 16; i++)
+         {         
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertEquals(1, msgs.size());
+            Message msgRec = (Message)msgs.get(0);
+            assertEquals(msg.getMessageID(), msgRec.getMessageID());
+            receivers[i].acknowledge(msgRec, null);
+            msgs = queues[i].browse();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty()); 
+            receivers[i].clear();
+         }
+
+      }
+      finally
+      {
+         if (office1 != null)
+         {
+            office2.unbindClusteredQueue("sub5");
+            office1.unbindClusteredQueue("sub7");
+            office1.unbindClusteredQueue("sub8");
+            office2.unbindClusteredQueue("sub13");
+            office1.unbindClusteredQueue("sub15");
+            office1.unbindClusteredQueue("sub16");
+            
+            office1.stop();
+         }
+         
+         if (office2 != null)
+         {
+            office2.stop();
+         }
+      }
+   }
+   
+   
+   protected void clusteredTransactionalRoute(boolean persistent) throws Throwable
+   {
+      ClusteredPostOffice office1 = null;
+      
+      ClusteredPostOffice office2 = null;
+      
+      try
+      {   
+         //Start two offices
+         
+         office1 = createClusteredPostOffice("node1", "testgroup");
+         office2 = createClusteredPostOffice("node2", "testgroup");
+     
+         Queue[] queues = new Queue[16];
+         Binding[] bindings = new Binding[16];
+         
+         queues[0] = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[0] = office1.bindClusteredQueue("sub1", "topic1", false, queues[0]);
+         
+         queues[1] = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[1] = office1.bindClusteredQueue("sub2", "topic1", false, queues[1]);
+         
+         queues[2] = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[2] = office2.bindClusteredQueue("sub3", "topic1", false, queues[2]);
+         
+         queues[3] = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[3] = office2.bindClusteredQueue("sub4", "topic1", false, queues[3]);
+         
+         queues[4] = new Queue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[4] = office2.bindClusteredQueue("sub5", "topic1", false, queues[4]);
+         
+         queues[5] = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[5] = office1.bindClusteredQueue("sub6", "topic1", false, queues[5]);
+         
+         queues[6] = new Queue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[6] = office1.bindClusteredQueue("sub7", "topic1", false, queues[6]);
+         
+         queues[7] = new Queue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[7] = office1.bindClusteredQueue("sub8", "topic1", false, queues[7]);
+         
+         queues[8] = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[8] = office1.bindClusteredQueue("sub9", "topic2", false, queues[8]);
+         
+         queues[9] = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[9] = office1.bindClusteredQueue("sub10", "topic2", false, queues[9]);
+         
+         queues[10] = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[10] = office2.bindClusteredQueue("sub11", "topic2", false, queues[10]);
+         
+         queues[11] = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[11] = office2.bindClusteredQueue("sub12", "topic2", false, queues[11]);
+         
+         queues[12] = new Queue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[12] = office2.bindClusteredQueue("sub13", "topic2", false, queues[12]);
+         
+         queues[13] = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[13] = office1.bindClusteredQueue("sub14", "topic2", false, queues[13]);
+         
+         queues[14] = new Queue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[14] = office1.bindClusteredQueue("sub15", "topic2", false, queues[14]);
+         
+         queues[15] = new Queue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         bindings[15] = office1.bindClusteredQueue("sub16", "topic2", false, queues[15]);
+
+         SimpleReceiver[] receivers = new SimpleReceiver[16];
+         
+         for (int i = 0; i < 16; i++)
+         {
+            receivers[i] = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
+            queues[i].add(receivers[i]);
+         }
+         
+         //First for topic 1
+         
+         Message msg1 = MessageFactory.createCoreMessage(1, persistent, null);;      
+         MessageReference ref1 = ms.reference(msg1);
+         
+         Message msg2 = MessageFactory.createCoreMessage(2, persistent, null);;      
+         MessageReference ref2 = ms.reference(msg2);
+         
+         Transaction tx = tr.createTransaction();
+
+         boolean routed = office1.route(ref1, "topic1", tx);         
+         assertTrue(routed);
+         routed = office1.route(ref2, "topic1", tx);         
+         assertTrue(routed);
+
+         
+         for (int i = 0; i < 16; i++)
+         {
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+            msgs = queues[i].browse();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+         }
+         
+         tx.commit();
+         
+         //Messages are sent asych so may take some finite time to arrive
+         Thread.sleep(1000);
+         
+         for (int i = 0; i < 8; i++)
+         {         
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertEquals(2, msgs.size());
+            Message msgRec1 = (Message)msgs.get(0);
+            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
+            Message msgRec2 = (Message)msgs.get(1);
+            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());            
+            receivers[i].acknowledge(msgRec1, null);
+            receivers[i].acknowledge(msgRec2, null);
+            msgs = queues[i].browse();
+            assertNotNull(msgs);            
+            assertTrue(msgs.isEmpty());                        
+            receivers[i].clear();
+         }
+         
+         for (int i = 8; i < 16; i++)
+         {
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+            msgs = queues[i].browse();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+         }
+         
+         msg1 = MessageFactory.createCoreMessage(1, persistent, null);;      
+         ref1 = ms.reference(msg1);
+         
+         msg2 = MessageFactory.createCoreMessage(2, persistent, null);;      
+         ref2 = ms.reference(msg2);
+         
+         tx = tr.createTransaction();
+
+         routed = office1.route(ref1, "topic1", tx);         
+         assertTrue(routed);
+         routed = office1.route(ref2, "topic1", tx);         
+         assertTrue(routed);
+         
+         //Messages are sent asych so may take some finite time to arrive
+         Thread.sleep(1000);         
+         
+         for (int i = 0; i < 16; i++)
+         {
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+            msgs = queues[i].browse();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+         }
+         
+         tx.rollback();
+         
+         for (int i = 0; i < 16; i++)
+         {
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+            msgs = queues[i].browse();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+         }
+         
+         //Now send some non transactionally
+         
+         msg1 = MessageFactory.createCoreMessage(1, persistent, null);
+         ref1 = ms.reference(msg1);
+         
+         msg2 = MessageFactory.createCoreMessage(2, persistent, null);
+         ref2 = ms.reference(msg2);
+         
+         routed = office1.route(ref1, "topic1", null);         
+         assertTrue(routed);
+         routed = office1.route(ref2, "topic1", null);         
+         assertTrue(routed);
+         
+         //Messages are sent asych so may take some finite time to arrive
+         Thread.sleep(1000);         
+         
+         //And acknowledge transactionally
+         
+         tx = tr.createTransaction();
+         
+         for (int i = 0; i < 8; i++)
+         {         
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertEquals(2, msgs.size());
+            Message msgRec1 = (Message)msgs.get(0);
+            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
+            Message msgRec2 = (Message)msgs.get(1);
+            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());      
+                        
+            receivers[i].acknowledge(msgRec1, tx);
+            receivers[i].acknowledge(msgRec2, tx);
+                        
+            msgs = queues[i].browse();
+            
+            assertNotNull(msgs);
+            assertEquals(2, msgs.size());
+            msgRec1 = (Message)msgs.get(0);
+            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
+            msgRec2 = (Message)msgs.get(1);
+            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());
+            
+            receivers[i].clear();
+         }
+         
+         for (int i = 8; i < 16; i++)
+         {
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+            msgs = queues[i].browse();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+         }
+         
+         tx.commit();
+         
+         for (int i = 0; i < 16; i++)
+         {
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+            msgs = queues[i].browse();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+         }
+         
+         
+         // and the rollback
+         
+         msg1 = MessageFactory.createCoreMessage(1, persistent, null);;      
+         ref1 = ms.reference(msg1);
+         
+         msg2 = MessageFactory.createCoreMessage(2, persistent, null);;      
+         ref2 = ms.reference(msg2);
+         
+         routed = office1.route(ref1, "topic1", null);         
+         assertTrue(routed);
+         routed = office1.route(ref2, "topic1", null);         
+         assertTrue(routed);
+         
+         Thread.sleep(1000);
+                 
+         tx = tr.createTransaction();
+         
+         for (int i = 0; i < 8; i++)
+         {         
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertEquals(2, msgs.size());
+            Message msgRec1 = (Message)msgs.get(0);
+            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
+            Message msgRec2 = (Message)msgs.get(1);
+            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());      
+                        
+            receivers[i].acknowledge(msgRec1, tx);
+            receivers[i].acknowledge(msgRec2, tx);
+                        
+            msgs = queues[i].browse();
+            
+            assertNotNull(msgs);
+            assertEquals(2, msgs.size());
+            msgRec1 = (Message)msgs.get(0);
+            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
+            msgRec2 = (Message)msgs.get(1);
+            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());
+            
+         }
+         
+         for (int i = 8; i < 16; i++)
+         {
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+            msgs = queues[i].browse();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+         }
+         
+         tx.rollback();
+         
+         for (int i = 0; i < 8; i++)
+         {         
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertEquals(2, msgs.size());
+            Message msgRec1 = (Message)msgs.get(0);
+            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
+            Message msgRec2 = (Message)msgs.get(1);
+            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());      
+                                 
+            msgs = queues[i].browse();
+            
+            assertNotNull(msgs);
+            assertEquals(2, msgs.size());
+            msgRec1 = (Message)msgs.get(0);
+            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
+            msgRec2 = (Message)msgs.get(1);
+            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());
+            
+            receivers[i].acknowledge(msgRec1, null);
+            receivers[i].acknowledge(msgRec2, null);
+                           
+            receivers[i].clear();
+         }
+         
+         for (int i = 8; i < 16; i++)
+         {
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+            msgs = queues[i].browse();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+         }
+         
+         
+         // Now for topic 2
+         
+         msg1 = MessageFactory.createCoreMessage(1, persistent, null);    
+         ref1 = ms.reference(msg1);
+         
+         msg2 = MessageFactory.createCoreMessage(2, persistent, null);     
+         ref2 = ms.reference(msg2);
+         
+         tx = tr.createTransaction();
+
+         routed = office1.route(ref1, "topic2", tx);         
+         assertTrue(routed);
+         routed = office1.route(ref2, "topic2", tx);         
+         assertTrue(routed);
+         
+         
+         
+         for (int i = 0; i < 16; i++)
+         {
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+            msgs = queues[i].browse();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+         }
+         
+         tx.commit();
+         
+         //Messages are sent asych so may take some finite time to arrive
+         Thread.sleep(1000);
+         
+         for (int i = 0; i < 8; i++)
+         {
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+            msgs = queues[i].browse();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+         }
+         
+         for (int i = 8; i < 16; i++)
+         {         
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertEquals(2, msgs.size());
+            Message msgRec1 = (Message)msgs.get(0);
+            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
+            Message msgRec2 = (Message)msgs.get(1);
+            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());            
+            receivers[i].acknowledge(msgRec1, null);
+            receivers[i].acknowledge(msgRec2, null);
+            msgs = queues[i].browse();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty()); 
+            receivers[i].clear();
+         }
+         
+         msg1 = MessageFactory.createCoreMessage(1, persistent, null);;      
+         ref1 = ms.reference(msg1);
+         
+         msg2 = MessageFactory.createCoreMessage(2, persistent, null);;      
+         ref2 = ms.reference(msg2);
+         
+         tx = tr.createTransaction();
+
+         routed = office1.route(ref1, "topic1", tx);         
+         assertTrue(routed);
+         routed = office1.route(ref2, "topic1", tx);         
+         assertTrue(routed);
+         
+         for (int i = 0; i < 16; i++)
+         {
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+            msgs = queues[i].browse();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+         }
+         
+         tx.rollback();
+         
+         for (int i = 0; i < 16; i++)
+         {
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+            msgs = queues[i].browse();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+         }
+         
+         //Now send some non transactionally
+         
+         msg1 = MessageFactory.createCoreMessage(1, persistent, null);      
+         ref1 = ms.reference(msg1);
+         
+         msg2 = MessageFactory.createCoreMessage(2, persistent, null);      
+         ref2 = ms.reference(msg2);
+         
+         routed = office1.route(ref1, "topic2", null);         
+         assertTrue(routed);
+         routed = office1.route(ref2, "topic2", null);         
+         assertTrue(routed);
+         
+         Thread.sleep(1000);
+         
+         //And acknowledge transactionally
+         
+         tx = tr.createTransaction();
+         
+         for (int i = 0; i < 8; i++)
+         {
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+            msgs = queues[i].browse();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+         }
+         
+         for (int i = 8; i < 16; i++)
+         {         
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertEquals(2, msgs.size());
+            Message msgRec1 = (Message)msgs.get(0);
+            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
+            Message msgRec2 = (Message)msgs.get(1);
+            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());      
+                        
+            receivers[i].acknowledge(msgRec1, tx);
+            receivers[i].acknowledge(msgRec2, tx);
+                        
+            msgs = queues[i].browse();
+            
+            assertNotNull(msgs);
+            assertEquals(2, msgs.size());
+            msgRec1 = (Message)msgs.get(0);
+            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
+            msgRec2 = (Message)msgs.get(1);
+            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());
+            
+            receivers[i].clear();
+         }
+         
+         
+         
+         tx.commit();
+         
+         for (int i = 0; i < 16; i++)
+         {
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+            msgs = queues[i].browse();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+         }
+         
+         
+         // and the rollback
+         
+         msg1 = MessageFactory.createCoreMessage(1, persistent, null);;      
+         ref1 = ms.reference(msg1);
+         
+         msg2 = MessageFactory.createCoreMessage(2, persistent, null);;      
+         ref2 = ms.reference(msg2);
+         
+         routed = office1.route(ref1, "topic2", null);         
+         assertTrue(routed);
+         routed = office1.route(ref2, "topic2", null);         
+         assertTrue(routed);
+         
+         Thread.sleep(1000);
+          
+         tx = tr.createTransaction();
+         
+         for (int i = 0; i < 8; i++)
+         {
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+            msgs = queues[i].browse();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+         }
+         
+         for (int i = 8; i < 16; i++)
+         {         
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertEquals(2, msgs.size());
+            Message msgRec1 = (Message)msgs.get(0);
+            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
+            Message msgRec2 = (Message)msgs.get(1);
+            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());      
+            
+            
+            receivers[i].acknowledge(msgRec1, tx);
+            receivers[i].acknowledge(msgRec2, tx);
+            
+            
+            msgs = queues[i].browse();
+            
+            assertNotNull(msgs);
+            assertEquals(2, msgs.size());
+            msgRec1 = (Message)msgs.get(0);
+            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
+            msgRec2 = (Message)msgs.get(1);
+            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());
+         }
+         
+         
+         
+         tx.rollback();
+         
+         for (int i = 0; i < 8; i++)
+         {
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+            msgs = queues[i].browse();
+            assertNotNull(msgs);
+            assertTrue(msgs.isEmpty());
+         }
+         
+         for (int i = 8; i < 16; i++)
+         {         
+            List msgs = receivers[i].getMessages();
+            assertNotNull(msgs);
+            assertEquals(2, msgs.size());
+            Message msgRec1 = (Message)msgs.get(0);
+            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
+            Message msgRec2 = (Message)msgs.get(1);
+            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());      
+                                              
+            msgs = queues[i].browse();
+            
+            assertNotNull(msgs);
+            assertEquals(2, msgs.size());
+            msgRec1 = (Message)msgs.get(0);
+            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
+            msgRec2 = (Message)msgs.get(1);
+            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());
+            
+            receivers[i].acknowledge(msgRec1, null);
+            receivers[i].acknowledge(msgRec2, null);             
+            
+            receivers[i].clear();
+         }
+      }
+      finally
+      {
+         if (office1 != null)
+         {
+            office2.unbindClusteredQueue("sub5");
+            office1.unbindClusteredQueue("sub7");
+            office1.unbindClusteredQueue("sub8");
+            office2.unbindClusteredQueue("sub13");
+            office1.unbindClusteredQueue("sub15");
+            office1.unbindClusteredQueue("sub16");
+            office1.stop();
+         }
+         
+         if (office2 != null)
+         {
+            office2.stop();
+         }
+      }
+   }
+   
+   protected ClusteredPostOffice createClusteredPostOffice(String nodeId, String groupName) throws Exception
+   {
+      ClusteredPostOfficeImpl postOffice = 
+         new ClusteredPostOfficeImpl(sc.getDataSource(), sc.getTransactionManager(),
+                                 null, true, nodeId, "Clustered", ms, groupName,
+                                 JGroupsUtil.getControlStackProperties(50, 1),
+                                 JGroupsUtil.getDataStackProperties(50, 1),
+                                 tr, pm, 5000, 5000);
+      
+      postOffice.start();      
+      
+      return postOffice;
+   }
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}
+
+
+

Deleted: trunk/tests/src/org/jboss/test/messaging/core/plugin/ClusteredTopicExchangeTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/plugin/ClusteredTopicExchangeTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/plugin/ClusteredTopicExchangeTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -1,1187 +0,0 @@
-/*
-  * 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.test.messaging.core.plugin;
-
-import java.util.List;
-
-
-import org.jboss.messaging.core.Message;
-import org.jboss.messaging.core.MessageReference;
-import org.jboss.messaging.core.local.MessageQueue;
-import org.jboss.messaging.core.message.MessageFactory;
-import org.jboss.messaging.core.plugin.contract.Exchange;
-import org.jboss.messaging.core.plugin.exchange.Binding;
-import org.jboss.messaging.core.plugin.exchange.cluster.ClusteredTopicExchange;
-import org.jboss.messaging.core.tx.Transaction;
-import org.jboss.test.messaging.core.SimpleReceiver;
-import org.jgroups.Channel;
-import org.jgroups.JChannel;
-
-/**
- * 
- * A ClusteredTopicExchangeTest
- *
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision: 1.1 $</tt>
- *
- * $Id$
- *
- */
-public class ClusteredTopicExchangeTest extends TopicExchangeTest
-{
-   // Constants -----------------------------------------------------
-
-   // Static --------------------------------------------------------
-   
-   // Attributes ----------------------------------------------------
-   
-   // Constructors --------------------------------------------------
-
-   public ClusteredTopicExchangeTest(String name)
-   {
-      super(name);
-   }
-
-   // Public --------------------------------------------------------
-
-   public void setUp() throws Exception
-   {
-      super.setUp();     
-            
-   }
-
-   public void tearDown() throws Exception
-   {           
-      super.tearDown();
-   }
-   
-   public final void testBindSameName() throws Throwable
-   {
-      Exchange exchange1 = null;
-      
-      Exchange exchange2 = null;
-      
-      try
-      {         
-         exchange1 = createExchange("node1", "testgroup");
-         
-         exchange2 = createExchange("node2", "testgroup");
-         
-         exchange1.bindQueue("sub1", "topic1", null, false, false, ms, pm, 20000, 100, 100);
-         
-         try
-         {
-            exchange2.bindQueue("sub1", "topic1", null, false, false, ms, pm, 20000, 100, 100);
-            fail();
-         }
-         catch (IllegalArgumentException e)
-         {
-            //OK - this should fail
-         }
-      }
-      finally
-      {
-         if (exchange1 != null)
-         {
-            exchange1.stop();
-         }
-         
-         if (exchange2 != null)
-         {
-            exchange2.stop();
-         }
-      }
-   }
-   
-   
-   public final void testClusteredBindUnbind() throws Throwable
-   {
-      Exchange exchange1 = null;
-      
-      Exchange exchange2 = null;
-      
-      Exchange exchange3 = null;
-      
-      try
-      {         
-         //Start one exchange
-         
-         exchange1 = createExchange("node1", "testgroup");
-         
-         //Add a couple of bindings
-         
-         Binding binding1 = exchange1.bindQueue("sub1", "topic1", null, false, false, ms, pm, 20000, 100, 100);         
-         Binding binding2 = exchange1.bindQueue("sub2", "topic1", null, false, false, ms, pm, 20000, 100, 100);
-    
-         //Start another exchange - make sure it picks up the bindings from the first node
-         
-         exchange2 = createExchange("node2", "testgroup");
-         
-         List bindings = exchange2.listBindingsForWildcard("topic1");
-         assertNotNull(bindings);
-         assertEquals(2, bindings.size());
-         
-         assertEquivalent(binding1, (Binding)bindings.get(0));
-         assertEquivalent(binding2, (Binding)bindings.get(1));         
-         
-         //Add another binding on node 2
-         
-         Binding binding3 = exchange2.bindQueue("sub3", "topic1", null, false, false, ms, pm, 20000, 100, 100);
-         
-         //Make sure both nodes pick it up
-         
-         bindings = exchange1.listBindingsForWildcard("topic1");
-         assertNotNull(bindings);
-         assertEquals(3, bindings.size());
-         
-         assertEquivalent(binding1, (Binding)bindings.get(0));
-         assertEquivalent(binding2, (Binding)bindings.get(1));
-         assertEquivalent(binding3, (Binding)bindings.get(2));
-
-         bindings = exchange2.listBindingsForWildcard("topic1");
-         assertNotNull(bindings);
-         assertEquals(3, bindings.size());
-         
-         assertEquivalent(binding1, (Binding)bindings.get(0));
-         assertEquivalent(binding2, (Binding)bindings.get(1));
-         assertEquivalent(binding3, (Binding)bindings.get(2));
-
-         //Add another binding on node 1
-         
-         Binding binding4 = exchange2.bindQueue("sub4", "topic1", null, false, false, ms, pm, 20000, 100, 100);
-            
-         // Make sure both nodes pick it up
-         
-         bindings = exchange1.listBindingsForWildcard("topic1");
-         assertNotNull(bindings);
-         assertEquals(4, bindings.size());
-         
-         assertEquivalent(binding1, (Binding)bindings.get(0));
-         assertEquivalent(binding2, (Binding)bindings.get(1));
-         assertEquivalent(binding3, (Binding)bindings.get(2));
-         assertEquivalent(binding4, (Binding)bindings.get(3));
-         
-         bindings = exchange2.listBindingsForWildcard("topic1");
-         assertNotNull(bindings);
-         assertEquals(4, bindings.size());
-         
-         assertEquivalent(binding1, (Binding)bindings.get(0));
-         assertEquivalent(binding2, (Binding)bindings.get(1));
-         assertEquivalent(binding3, (Binding)bindings.get(2));
-         assertEquivalent(binding4, (Binding)bindings.get(3));
-         
-         //Unbind binding 1 and binding 2
-         exchange1.unbindQueue("sub1");
-         exchange1.unbindQueue("sub2");
-         
-         //Make sure bindings are not longer available on either node
-         
-         bindings = exchange1.listBindingsForWildcard("topic1");
-         assertNotNull(bindings);
-         assertEquals(2, bindings.size());
-         
-         assertEquivalent(binding3, (Binding)bindings.get(0));
-         assertEquivalent(binding4, (Binding)bindings.get(1));
-   
-         bindings = exchange2.listBindingsForWildcard("topic1");
-         assertNotNull(bindings);
-         assertEquals(2, bindings.size());
-         
-         assertEquivalent(binding3, (Binding)bindings.get(0));
-         assertEquivalent(binding4, (Binding)bindings.get(1));
-         
-         //Add a third exchange
-                  
-         exchange3 = createExchange("node3", "testgroup");
-         
-         //Maks sure it picks up the bindings
-         
-         bindings = exchange3.listBindingsForWildcard("topic1");
-         assertNotNull(bindings);
-         assertEquals(2, bindings.size());
-         
-         assertEquivalent(binding3, (Binding)bindings.get(0));
-         assertEquivalent(binding4, (Binding)bindings.get(1));
-         
-         //Add another binding on node 3
-                  
-         Binding binding5 = exchange3.bindQueue("sub5", "topic1", null, false, false, ms, pm, 20000, 100, 100);
-         
-         // Make sure all nodes pick it up
-         
-         bindings = exchange1.listBindingsForWildcard("topic1");
-         assertNotNull(bindings);
-         assertEquals(3, bindings.size());
-         
-         assertEquivalent(binding3, (Binding)bindings.get(0));
-         assertEquivalent(binding4, (Binding)bindings.get(1));
-         assertEquivalent(binding5, (Binding)bindings.get(2));
-         
-         bindings = exchange2.listBindingsForWildcard("topic1");
-         assertNotNull(bindings);
-         assertEquals(3, bindings.size());
-         
-         assertEquivalent(binding3, (Binding)bindings.get(0));
-         assertEquivalent(binding4, (Binding)bindings.get(1));
-         assertEquivalent(binding5, (Binding)bindings.get(2));
-         
-         bindings = exchange3.listBindingsForWildcard("topic1");
-         assertNotNull(bindings);
-         assertEquals(3, bindings.size());
-         
-         assertEquivalent(binding3, (Binding)bindings.get(0));
-         assertEquivalent(binding4, (Binding)bindings.get(1));
-         assertEquivalent(binding5, (Binding)bindings.get(2));
-         
-         //Add a durable and a non durable binding on node 1
-         
-         Binding binding6 = exchange1.bindQueue("sub6", "topic1", null, false, true, ms, pm, 20000, 100, 100);
-         
-         Binding binding7 = exchange1.bindQueue("sub7", "topic1", null, false, false, ms, pm, 20000, 100, 100);
-         
-         // Make sure all nodes pick them up
-         
-         bindings = exchange1.listBindingsForWildcard("topic1");
-         assertNotNull(bindings);
-         assertEquals(5, bindings.size());
-         
-         assertEquivalent(binding3, (Binding)bindings.get(0));
-         assertEquivalent(binding4, (Binding)bindings.get(1));
-         assertEquivalent(binding5, (Binding)bindings.get(2));
-         assertEquivalent(binding6, (Binding)bindings.get(3));
-         assertEquivalent(binding7, (Binding)bindings.get(4));
-         
-         bindings = exchange2.listBindingsForWildcard("topic1");
-         assertNotNull(bindings);
-         assertEquals(5, bindings.size());
-         
-         assertEquivalent(binding3, (Binding)bindings.get(0));
-         assertEquivalent(binding4, (Binding)bindings.get(1));
-         assertEquivalent(binding5, (Binding)bindings.get(2));
-         assertEquivalent(binding6, (Binding)bindings.get(3));
-         assertEquivalent(binding7, (Binding)bindings.get(4));
-         
-         bindings = exchange3.listBindingsForWildcard("topic1");
-         assertNotNull(bindings);
-         assertEquals(5, bindings.size());
-         
-         assertEquivalent(binding3, (Binding)bindings.get(0));
-         assertEquivalent(binding4, (Binding)bindings.get(1));
-         assertEquivalent(binding5, (Binding)bindings.get(2));
-         assertEquivalent(binding6, (Binding)bindings.get(3));
-         assertEquivalent(binding7, (Binding)bindings.get(4));
-               
-         //Stop exchange 1
-         exchange1.stop();
-  
-         //Need to sleep since it may take some time for the view changed request to reach the
-         //members which causes the bindings to be removed
-         
-         Thread.sleep(1000);
-         
-         //All it's non durable bindings should be removed from the other nodes
-         //Durable bindings should remain
-         
-         bindings = exchange2.listBindingsForWildcard("topic1");
-         assertNotNull(bindings);
-         assertEquals(4, bindings.size());
-         
-         assertEquivalent(binding3, (Binding)bindings.get(0));
-         assertEquivalent(binding4, (Binding)bindings.get(1));
-         assertEquivalent(binding5, (Binding)bindings.get(2));
-         assertEquivalent(binding6, (Binding)bindings.get(3));
-         
-         bindings = exchange3.listBindingsForWildcard("topic1");
-         assertNotNull(bindings);
-         assertEquals(4, bindings.size());
-         
-         assertEquivalent(binding3, (Binding)bindings.get(0));
-         assertEquivalent(binding4, (Binding)bindings.get(1));
-         assertEquivalent(binding5, (Binding)bindings.get(2));
-         assertEquivalent(binding6, (Binding)bindings.get(3));
-         
-         //Stop exchange 2
-         exchange2.stop();
-         
-         bindings = exchange3.listBindingsForWildcard("topic1");
-         assertNotNull(bindings);
-         assertEquals(2, bindings.size());
-         
-         assertEquivalent(binding5, (Binding)bindings.get(0));
-         assertEquivalent(binding6, (Binding)bindings.get(1));
-         
-         //Restart exchange 1 and exchange 2
-         exchange1 = createExchange("node1", "testgroup");
-         
-         exchange2 = createExchange("node2", "testgroup");
-         
-         bindings = exchange1.listBindingsForWildcard("topic1");
-         assertNotNull(bindings);
-         assertEquals(2, bindings.size());
-         
-         assertEquivalent(binding5, (Binding)bindings.get(0));
-         assertEquivalent(binding6, (Binding)bindings.get(1));
-         
-         bindings = exchange2.listBindingsForWildcard("topic1");
-         assertNotNull(bindings);
-         assertEquals(2, bindings.size());
-         
-         assertEquivalent(binding5, (Binding)bindings.get(0));
-         assertEquivalent(binding6, (Binding)bindings.get(1));
-         
-         bindings = exchange3.listBindingsForWildcard("topic1");
-         assertNotNull(bindings);
-         assertEquals(2, bindings.size());
-         
-         assertEquivalent(binding5, (Binding)bindings.get(0));
-         assertEquivalent(binding6, (Binding)bindings.get(1));
-         
-         //Stop all exchanges
-         
-         exchange1.stop();
-         exchange2.stop();
-         exchange3.stop();
-         
-         //Start them all
-         exchange1 = createExchange("node1", "testgroup");
-         exchange2 = createExchange("node2", "testgroup");
-         exchange3 = createExchange("node3", "testgroup");
-         
-         //Only the durable queue should survive
-         
-         bindings = exchange1.listBindingsForWildcard("topic1");
-         assertNotNull(bindings);
-         assertEquals(1, bindings.size());
-         
-         assertEquivalent(binding6, (Binding)bindings.get(0));
-         
-         bindings = exchange2.listBindingsForWildcard("topic1");
-         assertNotNull(bindings);
-         assertEquals(1, bindings.size());
-         
-         assertEquivalent(binding6, (Binding)bindings.get(0));
-         
-         bindings = exchange3.listBindingsForWildcard("topic1");
-         assertNotNull(bindings);
-         assertEquals(1, bindings.size());
-         
-         assertEquivalent(binding6, (Binding)bindings.get(0));
-                  
-      }
-      finally
-      {
-         if (exchange1 != null)
-         {
-            exchange1.reloadQueues("topic1", ms, pm, 1000, 20, 20);
-            exchange1.unbindQueue("sub6");
-            exchange1.stop();
-         }
-         
-         if (exchange2 != null)
-         {
-            exchange2.stop();
-         }
-         
-         if (exchange3 != null)
-         {
-            exchange2.stop();
-         }
-      }
-      
-   }
-   
-   public final void testClusteredRoutePersistent() throws Throwable
-   {
-      clusteredRoute(true);
-   }
-   
-   public final void testClusteredRouteNonPersistent() throws Throwable
-   {
-      clusteredRoute(false);
-   }
-   
-   public final void testClusteredTransactionalRoutePersistent() throws Throwable
-   {
-      clusteredTransactionalRoute(true);
-   }
-   
-   public final void testClusteredTransactionalRouteNonPersistent() throws Throwable
-   {
-      clusteredTransactionalRoute(false);
-   }
-   
-   // Package protected ---------------------------------------------
-
-   // Protected -----------------------------------------------------
-   
-
-   protected void clusteredRoute(boolean persistentMessage) throws Throwable
-   {
-      Exchange exchange1 = null;
-      
-      Exchange exchange2 = null;
-          
-      try
-      {   
-         //Start two exchanges
-         
-         exchange1 = createExchange("node1", "testgroup");
-         exchange2 = createExchange("node2", "testgroup");
-      
-         //Two topics with a mixture of durable and non durable subscriptions
-         
-         Binding[] bindings = new Binding[16];
-         
-         bindings[0] = exchange1.bindQueue("sub1", "topic1", null, false, false, ms, pm, 20000, 100, 100);         
-         bindings[1] = exchange1.bindQueue("sub2", "topic1", null, false, false, ms, pm, 20000, 100, 100);
-         
-         bindings[2] = exchange2.bindQueue("sub3", "topic1", null, false, false, ms, pm, 20000, 100, 100);         
-         bindings[3] = exchange2.bindQueue("sub4", "topic1", null, false, false, ms, pm, 20000, 100, 100);         
-         bindings[4] = exchange2.bindQueue("sub5", "topic1", null, false, true, ms, pm, 20000, 100, 100);      
-         
-         bindings[5] = exchange1.bindQueue("sub6", "topic1", null, false, false, ms, pm, 20000, 100, 100);
-         bindings[6] = exchange1.bindQueue("sub7", "topic1", null, false, true, ms, pm, 20000, 100, 100);
-         bindings[7] = exchange1.bindQueue("sub8", "topic1", null, false, true, ms, pm, 20000, 100, 100);
-                  
-         bindings[8] = exchange1.bindQueue("sub9", "topic2", null, false, false, ms, pm, 20000, 100, 100);         
-         bindings[9] = exchange1.bindQueue("sub10", "topic2", null, false, false, ms, pm, 20000, 100, 100);
-         
-         bindings[10] = exchange2.bindQueue("sub11", "topic2", null, false, false, ms, pm, 20000, 100, 100);         
-         bindings[11] = exchange2.bindQueue("sub12", "topic2", null, false, false, ms, pm, 20000, 100, 100);         
-         bindings[12] = exchange2.bindQueue("sub13", "topic2", null, false, true, ms, pm, 20000, 100, 100);      
-         
-         bindings[13] = exchange1.bindQueue("sub14", "topic2", null, false, false, ms, pm, 20000, 100, 100);
-         bindings[14] = exchange1.bindQueue("sub15", "topic2", null, false, true, ms, pm, 20000, 100, 100);
-         bindings[15] = exchange1.bindQueue("sub16", "topic2", null, false, true, ms, pm, 20000, 100, 100);
-    
-         MessageQueue[] queues = new MessageQueue[16];
-         SimpleReceiver[] receivers = new SimpleReceiver[16];
-         
-         for (int i = 0; i < 16; i++)
-         {
-            queues[i] = bindings[i].getQueue();
-            receivers[i] = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
-            queues[i].add(receivers[i]);
-         }
-         
-         Message msg = MessageFactory.createCoreMessage(1, persistentMessage, null);      
-         MessageReference ref = ms.reference(msg);         
-
-         boolean routed = exchange1.route(ref, "topic1", null);         
-         assertTrue(routed);
-         
-         //Messages are sent asych so may take some finite time to arrive
-         Thread.sleep(1000);
-         
-         for (int i = 0; i < 8; i++)
-         {         
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertEquals(1, msgs.size());
-            Message msgRec = (Message)msgs.get(0);
-            assertEquals(msg.getMessageID(), msgRec.getMessageID());
-            receivers[i].acknowledge(msgRec, null);
-            msgs = queues[i].browse();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty()); 
-            receivers[i].clear();
-         }
-         
-         for (int i = 8; i < 16; i++)
-         {
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-            msgs = queues[i].browse();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-         }
-                  
-         //Now route to topic2
-         
-         msg = MessageFactory.createCoreMessage(2, persistentMessage, null);;      
-         ref = ms.reference(msg);         
-
-         routed = exchange1.route(ref, "topic2", null);         
-         assertTrue(routed);
-         //Messages are sent asych so may take some finite time to arrive
-         Thread.sleep(1000);
-         
-         for (int i = 0; i < 8; i++)
-         {
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-            msgs = queues[i].browse();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-         }
-         
-         for (int i = 8; i < 16; i++)
-         {         
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertEquals(1, msgs.size());
-            Message msgRec = (Message)msgs.get(0);
-            assertEquals(msg.getMessageID(), msgRec.getMessageID());
-            receivers[i].acknowledge(msgRec, null);
-            msgs = queues[i].browse();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty()); 
-            receivers[i].clear();
-         }
-
-      }
-      finally
-      {
-         if (exchange1 != null)
-         {
-            exchange2.unbindQueue("sub5");
-            exchange1.unbindQueue("sub7");
-            exchange1.unbindQueue("sub8");
-            exchange2.unbindQueue("sub13");
-            exchange1.unbindQueue("sub15");
-            exchange1.unbindQueue("sub16");
-            
-            exchange1.stop();
-         }
-         
-         if (exchange2 != null)
-         {
-            exchange2.stop();
-         }
-      }
-   }
-   
-   
-   protected void clusteredTransactionalRoute(boolean persistent) throws Throwable
-   {
-      Exchange exchange1 = null;
-      
-      Exchange exchange2 = null;
-      
-      try
-      {   
-         //Start two exchanges
-         
-         exchange1 = createExchange("node1", "testgroup");
-         exchange2 = createExchange("node2", "testgroup");
-
-         
-         //Two topics with a mixture of durable and non durable subscriptions
-         
-         Binding[] bindings = new Binding[16];
-         
-         bindings[0] = exchange1.bindQueue("sub1", "topic1", null, false, false, ms, pm, 20000, 100, 100);         
-         bindings[1] = exchange1.bindQueue("sub2", "topic1", null, false, false, ms, pm, 20000, 100, 100);
-         
-         bindings[2] = exchange2.bindQueue("sub3", "topic1", null, false, false, ms, pm, 20000, 100, 100);         
-         bindings[3] = exchange2.bindQueue("sub4", "topic1", null, false, false, ms, pm, 20000, 100, 100);         
-         bindings[4] = exchange2.bindQueue("sub5", "topic1", null, false, true, ms, pm, 20000, 100, 100);      
-         
-         bindings[5] = exchange1.bindQueue("sub6", "topic1", null, false, false, ms, pm, 20000, 100, 100);
-         bindings[6] = exchange1.bindQueue("sub7", "topic1", null, false, true, ms, pm, 20000, 100, 100);
-         bindings[7] = exchange1.bindQueue("sub8", "topic1", null, false, true, ms, pm, 20000, 100, 100);
-                  
-         bindings[8] = exchange1.bindQueue("sub9", "topic2", null, false, false, ms, pm, 20000, 100, 100);         
-         bindings[9] = exchange1.bindQueue("sub10", "topic2", null, false, false, ms, pm, 20000, 100, 100);
-         
-         bindings[10] = exchange2.bindQueue("sub11", "topic2", null, false, false, ms, pm, 20000, 100, 100);         
-         bindings[11] = exchange2.bindQueue("sub12", "topic2", null, false, false, ms, pm, 20000, 100, 100);         
-         bindings[12] = exchange2.bindQueue("sub13", "topic2", null, false, true, ms, pm, 20000, 100, 100);      
-         
-         bindings[13] = exchange1.bindQueue("sub14", "topic2", null, false, false, ms, pm, 20000, 100, 100);
-         bindings[14] = exchange1.bindQueue("sub15", "topic2", null, false, true, ms, pm, 20000, 100, 100);
-         bindings[15] = exchange1.bindQueue("sub16", "topic2", null, false, true, ms, pm, 20000, 100, 100);
-    
-         MessageQueue[] queues = new MessageQueue[16];
-         SimpleReceiver[] receivers = new SimpleReceiver[16];
-         
-         for (int i = 0; i < 16; i++)
-         {
-            queues[i] = bindings[i].getQueue();
-            receivers[i] = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
-            queues[i].add(receivers[i]);
-         }
-         
-         //First for topic 1
-         
-         Message msg1 = MessageFactory.createCoreMessage(1, persistent, null);;      
-         MessageReference ref1 = ms.reference(msg1);
-         
-         Message msg2 = MessageFactory.createCoreMessage(2, persistent, null);;      
-         MessageReference ref2 = ms.reference(msg2);
-         
-         Transaction tx = tr.createTransaction();
-
-         boolean routed = exchange1.route(ref1, "topic1", tx);         
-         assertTrue(routed);
-         routed = exchange1.route(ref2, "topic1", tx);         
-         assertTrue(routed);
-
-         
-         for (int i = 0; i < 16; i++)
-         {
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-            msgs = queues[i].browse();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-         }
-         
-         tx.commit();
-         
-         //Messages are sent asych so may take some finite time to arrive
-         Thread.sleep(1000);
-         
-         for (int i = 0; i < 8; i++)
-         {         
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertEquals(2, msgs.size());
-            Message msgRec1 = (Message)msgs.get(0);
-            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
-            Message msgRec2 = (Message)msgs.get(1);
-            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());            
-            receivers[i].acknowledge(msgRec1, null);
-            receivers[i].acknowledge(msgRec2, null);
-            msgs = queues[i].browse();
-            assertNotNull(msgs);            
-            assertTrue(msgs.isEmpty());                        
-            receivers[i].clear();
-         }
-         
-         for (int i = 8; i < 16; i++)
-         {
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-            msgs = queues[i].browse();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-         }
-         
-         msg1 = MessageFactory.createCoreMessage(1, persistent, null);;      
-         ref1 = ms.reference(msg1);
-         
-         msg2 = MessageFactory.createCoreMessage(2, persistent, null);;      
-         ref2 = ms.reference(msg2);
-         
-         tx = tr.createTransaction();
-
-         routed = exchange1.route(ref1, "topic1", tx);         
-         assertTrue(routed);
-         routed = exchange1.route(ref2, "topic1", tx);         
-         assertTrue(routed);
-         
-         //Messages are sent asych so may take some finite time to arrive
-         Thread.sleep(1000);         
-         
-         for (int i = 0; i < 16; i++)
-         {
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-            msgs = queues[i].browse();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-         }
-         
-         tx.rollback();
-         
-         for (int i = 0; i < 16; i++)
-         {
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-            msgs = queues[i].browse();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-         }
-         
-         //Now send some non transactionally
-         
-         msg1 = MessageFactory.createCoreMessage(1, persistent, null);
-         ref1 = ms.reference(msg1);
-         
-         msg2 = MessageFactory.createCoreMessage(2, persistent, null);
-         ref2 = ms.reference(msg2);
-         
-         routed = exchange1.route(ref1, "topic1", null);         
-         assertTrue(routed);
-         routed = exchange1.route(ref2, "topic1", null);         
-         assertTrue(routed);
-         
-         //Messages are sent asych so may take some finite time to arrive
-         Thread.sleep(1000);         
-         
-         //And acknowledge transactionally
-         
-         tx = tr.createTransaction();
-         
-         for (int i = 0; i < 8; i++)
-         {         
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertEquals(2, msgs.size());
-            Message msgRec1 = (Message)msgs.get(0);
-            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
-            Message msgRec2 = (Message)msgs.get(1);
-            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());      
-                        
-            receivers[i].acknowledge(msgRec1, tx);
-            receivers[i].acknowledge(msgRec2, tx);
-                        
-            msgs = queues[i].browse();
-            
-            assertNotNull(msgs);
-            assertEquals(2, msgs.size());
-            msgRec1 = (Message)msgs.get(0);
-            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
-            msgRec2 = (Message)msgs.get(1);
-            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());
-            
-            receivers[i].clear();
-         }
-         
-         for (int i = 8; i < 16; i++)
-         {
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-            msgs = queues[i].browse();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-         }
-         
-         tx.commit();
-         
-         for (int i = 0; i < 16; i++)
-         {
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-            msgs = queues[i].browse();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-         }
-         
-         
-         // and the rollback
-         
-         msg1 = MessageFactory.createCoreMessage(1, persistent, null);;      
-         ref1 = ms.reference(msg1);
-         
-         msg2 = MessageFactory.createCoreMessage(2, persistent, null);;      
-         ref2 = ms.reference(msg2);
-         
-         routed = exchange1.route(ref1, "topic1", null);         
-         assertTrue(routed);
-         routed = exchange1.route(ref2, "topic1", null);         
-         assertTrue(routed);
-         
-         Thread.sleep(1000);
-                 
-         tx = tr.createTransaction();
-         
-         for (int i = 0; i < 8; i++)
-         {         
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertEquals(2, msgs.size());
-            Message msgRec1 = (Message)msgs.get(0);
-            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
-            Message msgRec2 = (Message)msgs.get(1);
-            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());      
-                        
-            receivers[i].acknowledge(msgRec1, tx);
-            receivers[i].acknowledge(msgRec2, tx);
-                        
-            msgs = queues[i].browse();
-            
-            assertNotNull(msgs);
-            assertEquals(2, msgs.size());
-            msgRec1 = (Message)msgs.get(0);
-            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
-            msgRec2 = (Message)msgs.get(1);
-            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());
-            
-         }
-         
-         for (int i = 8; i < 16; i++)
-         {
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-            msgs = queues[i].browse();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-         }
-         
-         tx.rollback();
-         
-         for (int i = 0; i < 8; i++)
-         {         
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertEquals(2, msgs.size());
-            Message msgRec1 = (Message)msgs.get(0);
-            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
-            Message msgRec2 = (Message)msgs.get(1);
-            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());      
-                                 
-            msgs = queues[i].browse();
-            
-            assertNotNull(msgs);
-            assertEquals(2, msgs.size());
-            msgRec1 = (Message)msgs.get(0);
-            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
-            msgRec2 = (Message)msgs.get(1);
-            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());
-            
-            receivers[i].acknowledge(msgRec1, null);
-            receivers[i].acknowledge(msgRec2, null);
-                           
-            receivers[i].clear();
-         }
-         
-         for (int i = 8; i < 16; i++)
-         {
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-            msgs = queues[i].browse();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-         }
-         
-         
-         // Now for topic 2
-         
-         msg1 = MessageFactory.createCoreMessage(1, persistent, null);    
-         ref1 = ms.reference(msg1);
-         
-         msg2 = MessageFactory.createCoreMessage(2, persistent, null);     
-         ref2 = ms.reference(msg2);
-         
-         tx = tr.createTransaction();
-
-         routed = exchange1.route(ref1, "topic2", tx);         
-         assertTrue(routed);
-         routed = exchange1.route(ref2, "topic2", tx);         
-         assertTrue(routed);
-         
-         
-         
-         for (int i = 0; i < 16; i++)
-         {
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-            msgs = queues[i].browse();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-         }
-         
-         tx.commit();
-         
-         //Messages are sent asych so may take some finite time to arrive
-         Thread.sleep(1000);
-         
-         for (int i = 0; i < 8; i++)
-         {
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-            msgs = queues[i].browse();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-         }
-         
-         for (int i = 8; i < 16; i++)
-         {         
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertEquals(2, msgs.size());
-            Message msgRec1 = (Message)msgs.get(0);
-            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
-            Message msgRec2 = (Message)msgs.get(1);
-            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());            
-            receivers[i].acknowledge(msgRec1, null);
-            receivers[i].acknowledge(msgRec2, null);
-            msgs = queues[i].browse();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty()); 
-            receivers[i].clear();
-         }
-         
-         msg1 = MessageFactory.createCoreMessage(1, persistent, null);;      
-         ref1 = ms.reference(msg1);
-         
-         msg2 = MessageFactory.createCoreMessage(2, persistent, null);;      
-         ref2 = ms.reference(msg2);
-         
-         tx = tr.createTransaction();
-
-         routed = exchange1.route(ref1, "topic1", tx);         
-         assertTrue(routed);
-         routed = exchange1.route(ref2, "topic1", tx);         
-         assertTrue(routed);
-         
-         for (int i = 0; i < 16; i++)
-         {
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-            msgs = queues[i].browse();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-         }
-         
-         tx.rollback();
-         
-         for (int i = 0; i < 16; i++)
-         {
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-            msgs = queues[i].browse();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-         }
-         
-         //Now send some non transactionally
-         
-         msg1 = MessageFactory.createCoreMessage(1, persistent, null);      
-         ref1 = ms.reference(msg1);
-         
-         msg2 = MessageFactory.createCoreMessage(2, persistent, null);      
-         ref2 = ms.reference(msg2);
-         
-         routed = exchange1.route(ref1, "topic2", null);         
-         assertTrue(routed);
-         routed = exchange1.route(ref2, "topic2", null);         
-         assertTrue(routed);
-         
-         Thread.sleep(1000);
-         
-         //And acknowledge transactionally
-         
-         tx = tr.createTransaction();
-         
-         for (int i = 0; i < 8; i++)
-         {
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-            msgs = queues[i].browse();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-         }
-         
-         for (int i = 8; i < 16; i++)
-         {         
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertEquals(2, msgs.size());
-            Message msgRec1 = (Message)msgs.get(0);
-            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
-            Message msgRec2 = (Message)msgs.get(1);
-            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());      
-                        
-            receivers[i].acknowledge(msgRec1, tx);
-            receivers[i].acknowledge(msgRec2, tx);
-                        
-            msgs = queues[i].browse();
-            
-            assertNotNull(msgs);
-            assertEquals(2, msgs.size());
-            msgRec1 = (Message)msgs.get(0);
-            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
-            msgRec2 = (Message)msgs.get(1);
-            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());
-            
-            receivers[i].clear();
-         }
-         
-         
-         
-         tx.commit();
-         
-         for (int i = 0; i < 16; i++)
-         {
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-            msgs = queues[i].browse();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-         }
-         
-         
-         // and the rollback
-         
-         msg1 = MessageFactory.createCoreMessage(1, persistent, null);;      
-         ref1 = ms.reference(msg1);
-         
-         msg2 = MessageFactory.createCoreMessage(2, persistent, null);;      
-         ref2 = ms.reference(msg2);
-         
-         routed = exchange1.route(ref1, "topic2", null);         
-         assertTrue(routed);
-         routed = exchange1.route(ref2, "topic2", null);         
-         assertTrue(routed);
-         
-         Thread.sleep(1000);
-          
-         tx = tr.createTransaction();
-         
-         for (int i = 0; i < 8; i++)
-         {
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-            msgs = queues[i].browse();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-         }
-         
-         for (int i = 8; i < 16; i++)
-         {         
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertEquals(2, msgs.size());
-            Message msgRec1 = (Message)msgs.get(0);
-            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
-            Message msgRec2 = (Message)msgs.get(1);
-            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());      
-            
-            
-            receivers[i].acknowledge(msgRec1, tx);
-            receivers[i].acknowledge(msgRec2, tx);
-            
-            
-            msgs = queues[i].browse();
-            
-            assertNotNull(msgs);
-            assertEquals(2, msgs.size());
-            msgRec1 = (Message)msgs.get(0);
-            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
-            msgRec2 = (Message)msgs.get(1);
-            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());
-         }
-         
-         
-         
-         tx.rollback();
-         
-         for (int i = 0; i < 8; i++)
-         {
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-            msgs = queues[i].browse();
-            assertNotNull(msgs);
-            assertTrue(msgs.isEmpty());
-         }
-         
-         for (int i = 8; i < 16; i++)
-         {         
-            List msgs = receivers[i].getMessages();
-            assertNotNull(msgs);
-            assertEquals(2, msgs.size());
-            Message msgRec1 = (Message)msgs.get(0);
-            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
-            Message msgRec2 = (Message)msgs.get(1);
-            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());      
-                                              
-            msgs = queues[i].browse();
-            
-            assertNotNull(msgs);
-            assertEquals(2, msgs.size());
-            msgRec1 = (Message)msgs.get(0);
-            assertEquals(msg1.getMessageID(), msgRec1.getMessageID());
-            msgRec2 = (Message)msgs.get(1);
-            assertEquals(msg2.getMessageID(), msgRec2.getMessageID());
-            
-            receivers[i].acknowledge(msgRec1, null);
-            receivers[i].acknowledge(msgRec2, null);             
-            
-            receivers[i].clear();
-         }
-      }
-      finally
-      {
-         if (exchange1 != null)
-         {
-            exchange2.unbindQueue("sub5");
-            exchange1.unbindQueue("sub7");
-            exchange1.unbindQueue("sub8");
-            exchange2.unbindQueue("sub13");
-            exchange1.unbindQueue("sub15");
-            exchange1.unbindQueue("sub16");
-            exchange1.stop();
-         }
-         
-         if (exchange2 != null)
-         {
-            exchange2.stop();
-         }
-      }
-   }
-   
-   protected Exchange createExchange() throws Exception
-   {
-      ClusteredTopicExchange exchange = new ClusteredTopicExchange(sc.getDataSource(), sc.getTransactionManager());
-      
-      Channel controlChannel = new JChannel(JGroupsUtil.getControlStackProperties(50, 1));
-      Channel dataChannel = new JChannel(JGroupsUtil.getDataStackProperties(50, 1));
-      exchange.start();
-      
-      ((ClusteredTopicExchange)exchange).injectAttributes(controlChannel, dataChannel, "group1", "Topic", "node1", ms, im, pool, tr, pm);
-                  
-      return exchange;
-   }
-   
-   protected Exchange createExchange(String nodeId, String groupName) throws Exception
-   {
-      ClusteredTopicExchange exchange = new ClusteredTopicExchange(sc.getDataSource(), sc.getTransactionManager());
-      
-      Channel controlChannel = new JChannel(JGroupsUtil.getControlStackProperties(50, 1));
-      Channel dataChannel = new JChannel(JGroupsUtil.getDataStackProperties(50, 1));
-      
-      exchange.start();      
-      
-      ((ClusteredTopicExchange)exchange).injectAttributes(controlChannel, dataChannel, groupName, "Topic", nodeId, ms, im, pool, tr, pm);
-            
-      return exchange;
-   }
-
-   // Private -------------------------------------------------------
-
-   // Inner classes -------------------------------------------------
-
-}
-
-
-

Deleted: trunk/tests/src/org/jboss/test/messaging/core/plugin/DirectExchangeTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/plugin/DirectExchangeTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/plugin/DirectExchangeTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -1,453 +0,0 @@
-/*
-  * 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.test.messaging.core.plugin;
-
-import java.util.List;
-
-import org.jboss.messaging.core.Message;
-import org.jboss.messaging.core.MessageReference;
-import org.jboss.messaging.core.local.MessageQueue;
-import org.jboss.messaging.core.message.MessageFactory;
-import org.jboss.messaging.core.plugin.contract.Exchange;
-import org.jboss.messaging.core.plugin.exchange.Binding;
-import org.jboss.messaging.core.plugin.exchange.DirectExchange;
-import org.jboss.messaging.core.tx.Transaction;
-import org.jboss.test.messaging.core.SimpleReceiver;
-import org.jboss.test.messaging.core.plugin.base.ExchangeTestBase;
-
-/**
- * 
- * A DirectExchangeTest
-
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision: 1.1 $</tt>
- *
- * $Id$
- *
- */
-public class DirectExchangeTest extends ExchangeTestBase
-{
-   // Constants -----------------------------------------------------
-
-   // Static --------------------------------------------------------
-   
-   // Attributes ----------------------------------------------------
-
-   // Constructors --------------------------------------------------
-
-   public DirectExchangeTest(String name)
-   {
-      super(name);
-   }
-
-   // Public --------------------------------------------------------
-
-   public void setUp() throws Exception
-   {
-      super.setUp();            
-   }
-
-   public void tearDown() throws Exception
-   {      
-     
-      super.tearDown();
-   }
-   
-   public final void testRouteNPMessageNDQueue() throws Throwable
-   {
-      route(false, false);
-   }
-   
-   public final void testRouteNPMessageDQueue() throws Throwable
-   {
-      route(false, true);
-   }
-   
-   public final void testRoutePMessageNDQueue() throws Throwable
-   {
-      route(true, false);
-   }
-   
-   public final void testRoutePMessageDQueue() throws Throwable
-   {
-      route(true, true);
-   }
-      
-   public final void testRouteTransactionalNPMessageNDQueue() throws Throwable
-   {
-      routeTransactional(false, false);
-   }
-   
-   public final void testRouteTransactionalNPMessageDQueue() throws Throwable
-   {
-      routeTransactional(false, true);
-   }
-   
-   public final void testRouteTransactionalPMessageNDQueue() throws Throwable
-   {
-      routeTransactional(true, false);
-   }
-   
-   public final void testRouteTransactionalPMessageDQueue() throws Throwable
-   {
-      routeTransactional(true, true);
-   }
-      
-   public final void testRouteInactive() throws Throwable
-   {
-      Exchange exchange = createExchange();
-      
-      Binding binding1 =
-         exchange.bindQueue("queue1", "queue1", null, false, true, ms, pm, 1000, 20, 20);      
-      Binding binding2 =
-         exchange.bindQueue("queue2", "queue2", null, false, true, ms, pm, 1000, 20, 20);
-      
-      MessageQueue queue1 = binding1.getQueue();
-      MessageQueue queue2 = binding2.getQueue();
-      SimpleReceiver receiver1 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
-      queue1.add(receiver1);
-      SimpleReceiver receiver2 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
-      queue2.add(receiver2);
-      
-      //Now make one bindings inactive
-      binding1.deactivate();
-      
-      assertFalse(binding1.isActive());
-      assertTrue(binding2.isActive());
-      
-      Message msg1 = MessageFactory.createCoreMessage(1);      
-      MessageReference ref1 = ms.reference(msg1);
-      
-      boolean routed = exchange.route(ref1, "queue1", null);      
-      assertFalse(routed);
-      
-      List msgs = receiver1.getMessages();
-      assertNotNull(msgs);
-      assertTrue(msgs.isEmpty());
-      
-      msgs = receiver2.getMessages();
-      assertNotNull(msgs);
-      assertTrue(msgs.isEmpty());
-                  
-      Message msg2 = MessageFactory.createCoreMessage(2);      
-      MessageReference ref2 = ms.reference(msg2);
-      
-      routed = exchange.route(ref2, "queue2", null);      
-      assertTrue(routed);
-      
-      msgs = receiver2.getMessages();
-      assertNotNull(msgs);
-      assertEquals(1, msgs.size());
-      Message msgRec = (Message)msgs.get(0);
-      assertTrue(msg2 == msgRec);
-      receiver2.acknowledge(msgRec, null);
-      msgs = queue2.browse();
-      assertNotNull(msgs);
-      assertTrue(msgs.isEmpty());    
-      
-      msgs = receiver1.getMessages();
-      assertNotNull(msgs);
-      assertTrue(msgs.isEmpty());     
-   
-   }
-   
-   public final void testRouteNoBinding() throws Throwable
-   {
-      Exchange exchange = createExchange();
-      
-      Binding binding1 =
-         exchange.bindQueue("queue1", "queue1", null, false, true, ms, pm, 1000, 20, 20);      
-
-      MessageQueue queue1 = binding1.getQueue();
-      SimpleReceiver receiver1 = new SimpleReceiver(SimpleReceiver.ACCEPTING);
-      queue1.add(receiver1);
-
-      assertTrue(binding1.isActive());
-
-      Message msg1 = MessageFactory.createCoreMessage(1);      
-      MessageReference ref1 = ms.reference(msg1);
-      
-      boolean routed = exchange.route(ref1, "this won't match anything", null);      
-      
-      //A direct exchange should return false if there is no binding
-      assertFalse(routed);
-            
-      List msgs = queue1.browse();
-      assertNotNull(msgs);
-      assertTrue(msgs.isEmpty());             
-   }
-   
-   
-   
-
-   // Package protected ---------------------------------------------
-    
-   // Protected -----------------------------------------------------
-   
-   protected void routeTransactional(boolean persistentMessage, boolean durableQueue) throws Throwable
-   {
-      Exchange exchange = createExchange();
-      
-      Binding binding1 =
-         exchange.bindQueue("queue1", "queue1", null, false, durableQueue, ms, pm, 1000, 20, 20);      
-
-      MessageQueue queue1 = binding1.getQueue();
-      SimpleReceiver receiver1 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
-      queue1.add(receiver1);
-
-      assertTrue(binding1.isActive());
-
-      Message msg1 = MessageFactory.createCoreMessage(1, persistentMessage, null);      
-      MessageReference ref1 = ms.reference(msg1);
-      
-      Message msg2 = MessageFactory.createCoreMessage(2, persistentMessage, null);      
-      MessageReference ref2 = ms.reference(msg2);
-      
-      Transaction tx = tr.createTransaction();
-      
-      boolean routed = exchange.route(ref1, "queue1", tx);            
-      assertTrue(routed);
-      routed = exchange.route(ref2, "queue1", tx);            
-      assertTrue(routed);
-      
-      
-      List msgs = queue1.browse();
-      assertNotNull(msgs);
-      assertTrue(msgs.isEmpty());
-      
-      tx.commit();
-      
-      msgs = receiver1.getMessages();
-      assertNotNull(msgs);
-      assertEquals(2, msgs.size());
-      Message msgRec1 = (Message)msgs.get(0);
-      Message msgRec2 = (Message)msgs.get(1);
-      assertTrue(msgRec1 == msg1);
-      assertTrue(msgRec2 == msg2);
-      
-      //Acknowledge non transactionally
-      receiver1.acknowledge(msgRec1, null);
-      receiver1.acknowledge(msgRec2, null);
-
-      msgs = queue1.browse();
-      assertNotNull(msgs);
-      assertTrue(msgs.isEmpty()); 
-      
-      receiver1.clear();
-           
-      Message msg3 = MessageFactory.createCoreMessage(3, persistentMessage, null);      
-      MessageReference ref3 = ms.reference(msg3);
-      
-      Message msg4 = MessageFactory.createCoreMessage(4, persistentMessage, null);      
-      MessageReference ref4 = ms.reference(msg4);
-      
-      tx = tr.createTransaction();
-      
-      routed = exchange.route(ref3, "queue1", tx);            
-      assertTrue(routed);
-      routed = exchange.route(ref4, "queue1", tx);            
-      assertTrue(routed);
-            
-      msgs = queue1.browse();
-      assertNotNull(msgs);
-      assertTrue(msgs.isEmpty()); 
-      
-      tx.rollback();
-      
-      msgs = receiver1.getMessages();
-      assertNotNull(msgs);
-      assertTrue(msgs.isEmpty());
-      
-      receiver1.clear();
-      
-      
-      Message msg5 = MessageFactory.createCoreMessage(5, persistentMessage, null);      
-      MessageReference ref5 = ms.reference(msg5);
-      
-      Message msg6 = MessageFactory.createCoreMessage(6, persistentMessage, null);      
-      MessageReference ref6 = ms.reference(msg6);
-            
-      routed = exchange.route(ref5, "queue1", null);            
-      assertTrue(routed);
-      routed = exchange.route(ref6, "queue1", null);            
-      assertTrue(routed);
-      
-      msgs = receiver1.getMessages();
-      assertNotNull(msgs);
-      assertEquals(2, msgs.size());
-      msgRec1 = (Message)msgs.get(0);
-      msgRec2 = (Message)msgs.get(1);
-      assertTrue(msgRec1 == msg5);
-      assertTrue(msgRec2 == msg6);
-      
-      //Acknowledge transactionally
-      
-      tx = tr.createTransaction();
-      
-      receiver1.acknowledge(msgRec1, tx);
-      receiver1.acknowledge(msgRec2, tx);
-      
-      msgs = queue1.browse();
-      assertNotNull(msgs);
-      assertEquals(2, msgs.size());
-      msgRec1 = (Message)msgs.get(0);
-      msgRec2 = (Message)msgs.get(1);
-      assertTrue(msgRec1 == msg5);
-      assertTrue(msgRec2 == msg6);
-      
-      tx.commit();
-      
-      msgs = queue1.browse();
-      assertNotNull(msgs);
-      assertTrue(msgs.isEmpty());
-      
-      
-      receiver1.clear();
-      
-      Message msg7 = MessageFactory.createCoreMessage(7, persistentMessage, null);      
-      MessageReference ref7 = ms.reference(msg7);
-      
-      Message msg8 = MessageFactory.createCoreMessage(8, persistentMessage, null);      
-      MessageReference ref8 = ms.reference(msg8);
-            
-      routed = exchange.route(ref7, "queue1", null);            
-      assertTrue(routed);
-      routed = exchange.route(ref8, "queue1", null);            
-      assertTrue(routed);
-      
-      msgs = receiver1.getMessages();
-      assertNotNull(msgs);
-      assertEquals(2, msgs.size());
-      msgRec1 = (Message)msgs.get(0);
-      msgRec2 = (Message)msgs.get(1);
-      assertTrue(msgRec1 == msg7);
-      assertTrue(msgRec2 == msg8);
-      
-      //Acknowledge transactionally
-      
-      tx = tr.createTransaction();
-      
-      receiver1.acknowledge(msgRec1, tx);
-      receiver1.acknowledge(msgRec2, tx);
-      
-      msgs = queue1.browse();
-      assertNotNull(msgs);
-      assertEquals(2, msgs.size());
-      msgRec1 = (Message)msgs.get(0);
-      msgRec2 = (Message)msgs.get(1);
-      assertTrue(msgRec1 == msg7);
-      assertTrue(msgRec2 == msg8);
-      
-      tx.rollback();
-      
-      msgs = queue1.browse();
-      assertNotNull(msgs);
-      assertEquals(2, msgs.size());
-      msgRec1 = (Message)msgs.get(0);
-      msgRec2 = (Message)msgs.get(1);
-      assertTrue(msgRec1 == msg7);
-      assertTrue(msgRec2 == msg8);
-
-   }
-   
-   protected void route(boolean persistentMessage, boolean durableQueue) throws Throwable
-   {
-      Exchange exchange = createExchange();
-      
-      Binding binding1 =
-         exchange.bindQueue("queue1", "queue1", null, false, durableQueue, ms, pm, 1000, 20, 20);      
-      Binding binding2 =
-         exchange.bindQueue("queue2", "queue2", null, false, durableQueue, ms, pm, 1000, 20, 20);
-      
-      MessageQueue queue1 = binding1.getQueue();      
-      MessageQueue queue2 = binding2.getQueue();
-      SimpleReceiver receiver1 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
-      queue1.add(receiver1);
-      SimpleReceiver receiver2 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
-      queue2.add(receiver2);
-      
-      assertTrue(binding1.isActive());      
-      assertTrue(binding2.isActive());
-      
-      Message msg1 = MessageFactory.createCoreMessage(1, persistentMessage, null);     
-      MessageReference ref1 = ms.reference(msg1);
-      
-      boolean routed = exchange.route(ref1, "queue1", null);      
-      assertTrue(routed);
-      
-      List msgs = receiver1.getMessages();
-      assertNotNull(msgs);
-      assertEquals(1, msgs.size());
-      Message msgRec = (Message)msgs.get(0);
-      assertTrue(msg1 == msgRec);
-           
-      receiver1.acknowledge(msgRec, null);
-      msgs = queue1.browse();
-      assertNotNull(msgs);
-      assertTrue(msgs.isEmpty());      
-      
-      msgs = receiver2.getMessages();
-      assertNotNull(msgs);
-      assertTrue(msgs.isEmpty());
-      
-      receiver1.clear();
-      receiver2.clear();
-      
-      Message msg2 = MessageFactory.createCoreMessage(2);      
-      MessageReference ref2 = ms.reference(msg2);
-      
-      routed = exchange.route(ref2, "queue2", null);      
-      assertTrue(routed);
-      
-      msgs = receiver2.getMessages();
-      assertNotNull(msgs);
-      assertEquals(1, msgs.size());
-      msgRec = (Message)msgs.get(0);
-      assertTrue(msg2 == msgRec);
-      receiver2.acknowledge(msgRec, null);
-      msgs = queue2.browse();
-      assertNotNull(msgs);
-      assertTrue(msgs.isEmpty());
-      
-      msgs = receiver1.getMessages();
-      assertNotNull(msgs);
-      assertTrue(msgs.isEmpty());
-   }
-   
-   protected Exchange createExchange() throws Exception
-   {
-      DirectExchange exchange = new DirectExchange(sc.getDataSource(), sc.getTransactionManager());
-      
-      exchange.start();            
-      
-      ((DirectExchange)exchange).injectAttributes("Direct", "node1", ms, im, pool);
-            
-      return exchange;
-   }
-
-   // Private -------------------------------------------------------
-
-   // Inner classes -------------------------------------------------
-
-}
-
-

Modified: trunk/tests/src/org/jboss/test/messaging/core/plugin/IdManagerTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/plugin/IdManagerTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/plugin/IdManagerTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -66,7 +66,10 @@
       sc = new ServiceContainer("all");
       sc.start();                
       
-      pm = new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager());
+      pm =
+         new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager(), null,
+                                    true, true, true, 100);      
+      pm.start();
       
       pm.start();
             

Modified: trunk/tests/src/org/jboss/test/messaging/core/plugin/JDBCPersistenceManagerTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/plugin/JDBCPersistenceManagerTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/plugin/JDBCPersistenceManagerTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -93,16 +93,17 @@
       
    }
    
-   protected void doSetup(boolean batch) throws Throwable
+   protected void doSetup(boolean batch, int maxParams) throws Throwable
    {
-      pm = createPM();      
-      pm.setUsingBatchUpdates(batch);      
+      pm = createPM(batch, maxParams);         
       ms = new SimpleMessageStore();      
    }
    
-   protected JDBCPersistenceManager createPM() throws Throwable
-   {
-      JDBCPersistenceManager p = new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager());
+   protected JDBCPersistenceManager createPM(boolean batch, int maxParams) throws Throwable
+   {      
+      JDBCPersistenceManager p =
+         new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager(), null,
+                                    true, batch, true, maxParams);      
       p.start();
       return p;
    }
@@ -115,6 +116,7 @@
          sc = null;
       }
       pm.stop();
+      ms.stop();
       super.tearDown();
    }
    
@@ -134,7 +136,7 @@
          
    public void testAddRemoveReference() throws Throwable
    {
-      doSetup(false);
+      doSetup(false, 100);
       
       Channel channel1 = new SimpleChannel(0, ms);
       Channel channel2 = new SimpleChannel(1, ms);
@@ -296,7 +298,7 @@
    
    protected void addRemoveGetReferences(boolean batch) throws Throwable
    {
-      doSetup(false);
+      doSetup(false, 100);
       
       Channel channel1 = new SimpleChannel(0, ms);
       
@@ -480,7 +482,7 @@
    
    public void testPageOrders() throws Throwable
    {
-      doSetup(false);
+      doSetup(false, 100);
       
       Channel channel = new SimpleChannel(0, ms);
       
@@ -571,7 +573,7 @@
      
    public void testGetMessages() throws Throwable
    {
-      doSetup(false);
+      doSetup(false, 100);
       
       Channel channel = new SimpleChannel(0, ms);
       
@@ -648,7 +650,7 @@
    
    public void testGetInitialRefInfos() throws Throwable
    {
-      doSetup(false);
+      doSetup(false, 100);
       
       Channel channel = new SimpleChannel(0, ms);
       
@@ -840,10 +842,8 @@
    
    public void testGetMessagesMaxParams() throws Throwable
    {
-      doSetup(false);
+      doSetup(false, 5);
       
-      pm.setMaxParams(5);
-      
       Channel channel = new SimpleChannel(0, ms);
       
       Message[] m = createMessages(10);
@@ -918,13 +918,12 @@
 
    public void testRetrievePreparedTransactions() throws Throwable
    {
-      doSetup(false);
+      doSetup(false, 100);
       
       Channel channel = new SimpleChannel(0, ms);
       
-      TransactionRepository txRep = new TransactionRepository();
-      IdManager idMgr = new IdManager("TRANSCTION_ID", 10, pm);
-      txRep.injectAttributes(pm, idMgr);
+      TransactionRepository txRep = new TransactionRepository(pm, new IdManager("TRANSACTION_ID", 10, pm));
+      txRep.start();
 
       Message[] messages = createMessages(10);
       
@@ -1274,12 +1273,11 @@
    
    protected void doTransactionCommit(boolean xa, boolean batch) throws Throwable
    {
-      doSetup(batch);
+      doSetup(batch, 100);
 
       Channel channel = new SimpleChannel(0, ms);
-      TransactionRepository txRep = new TransactionRepository();
-      IdManager idMgr = new IdManager("TRANSCTION_ID", 10, pm);
-      txRep.injectAttributes(pm, idMgr);
+      TransactionRepository txRep = new TransactionRepository(pm, new IdManager("TRANSACTION_ID", 10, pm));
+      txRep.start();
 
       log.debug("transaction log started");
 
@@ -1371,12 +1369,11 @@
          
    protected void doTransactionRollback(boolean xa, boolean batch) throws Throwable
    {
-      doSetup(batch);
+      doSetup(batch, 100);
 
       Channel channel = new SimpleChannel(0, ms);
-      TransactionRepository txRep = new TransactionRepository();
-      IdManager idMgr = new IdManager("TRANSCTION_ID", 10, pm);
-      txRep.injectAttributes(pm, idMgr);
+      TransactionRepository txRep = new TransactionRepository(pm, new IdManager("TRANSACTION_ID", 10, pm));
+      txRep.start();
  
       Message[] messages = createMessages(10);     
       

Added: trunk/tests/src/org/jboss/test/messaging/core/plugin/SimplePostOfficeTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/plugin/SimplePostOfficeTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/plugin/SimplePostOfficeTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -0,0 +1,987 @@
+/*
+  * 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.test.messaging.core.plugin;
+
+import java.util.List;
+
+import org.jboss.jms.selector.Selector;
+import org.jboss.jms.server.QueuedExecutorPool;
+import org.jboss.messaging.core.Filter;
+import org.jboss.messaging.core.Message;
+import org.jboss.messaging.core.MessageReference;
+import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.message.MessageFactory;
+import org.jboss.messaging.core.plugin.IdManager;
+import org.jboss.messaging.core.plugin.JDBCPersistenceManager;
+import org.jboss.messaging.core.plugin.SimpleMessageStore;
+import org.jboss.messaging.core.plugin.contract.Binding;
+import org.jboss.messaging.core.plugin.contract.MessageStore;
+import org.jboss.messaging.core.plugin.contract.PersistenceManager;
+import org.jboss.messaging.core.plugin.contract.PostOffice;
+import org.jboss.messaging.core.plugin.postoffice.PostOfficeImpl;
+import org.jboss.messaging.core.tx.Transaction;
+import org.jboss.messaging.core.tx.TransactionRepository;
+import org.jboss.test.messaging.MessagingTestCase;
+import org.jboss.test.messaging.core.SimpleReceiver;
+import org.jboss.test.messaging.tools.ServerManagement;
+import org.jboss.test.messaging.tools.jmx.ServiceContainer;
+
+import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
+
+/**
+ * 
+ * A PostOfficeTestBase
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class SimplePostOfficeTest extends MessagingTestCase
+{
+   // Constants -----------------------------------------------------
+
+   // Static --------------------------------------------------------
+   
+   // Attributes ----------------------------------------------------
+
+   protected ServiceContainer sc;
+
+   protected IdManager im;   
+   
+   protected PersistenceManager pm;
+      
+   protected MessageStore ms;
+   
+   protected TransactionRepository tr;
+   
+   protected QueuedExecutorPool pool;
+   
+   // Constructors --------------------------------------------------
+
+   public SimplePostOfficeTest(String name)
+   {
+      super(name);
+   }
+
+   // Public --------------------------------------------------------
+
+   public void setUp() throws Exception
+   {
+      super.setUp();
+
+      sc = new ServiceContainer("all");
+      
+      sc.start();                
+      
+      pm =
+         new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager(), null,
+                                    true, true, true, 100);      
+      pm.start();
+      
+      tr = new TransactionRepository(pm, new IdManager("TRANSACTION_ID", 10, pm));
+      tr.start();
+      
+      ms = new SimpleMessageStore();
+      ms.start();
+      
+      pool = new QueuedExecutorPool(10);
+      
+      im = new IdManager("CHANNEL_ID", 10, pm);
+            
+      log.debug("setup done");
+   }
+
+   public void tearDown() throws Exception
+   {      
+      if (!ServerManagement.isRemote())
+      {
+         sc.stop();
+         sc = null;
+      }
+      pm.stop();
+      tr.stop();
+      ms.stop();
+      
+      super.tearDown();
+   }
+   
+   // Public --------------------------------------------------------
+   
+   
+   public final void testBind() throws Throwable
+   {
+      PostOffice office1 = null;
+      
+      PostOffice office2 = null;
+      
+      PostOffice office3 = null;
+      
+      try
+      {             
+         office1 = createPostOffice();
+         
+         //Bind one durable
+         
+         Filter filter1 = new Selector("x = 'cheese'");
+         Filter filter2 = new Selector("y = 'bread'");
+         
+         Queue queue1 = new Queue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get(), null);
+         
+         Binding binding1 =
+            office1.bindQueue("durableQueue", "condition1", false, queue1);
+         
+         //Binding twice with the same name should fail      
+         try
+         {
+            Binding bindFail = office1.bindQueue("durableQueue", "condition1", false, queue1);
+            fail();
+         }
+         catch (IllegalArgumentException e)
+         {
+            //Ok
+         }
+               
+         //Bind one non durable
+         Queue queue2 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);
+         Binding binding2 =
+            office1.bindQueue("nonDurableQueue", "condition2", false, queue2);
+         
+         //Check they're there
+         
+         Binding binding3 = office1.getBindingForQueueName("durableQueue");
+         assertNotNull(binding3);
+         assertTrue(binding1 == binding3);
+         assertEquivalent(binding1, binding3);
+         assertNotNull(binding3.getQueue());
+         assertEquals(true, binding3.getQueue().isRecoverable());
+         
+         
+         Binding binding4 = office1.getBindingForQueueName("nonDurableQueue");
+         assertNotNull(binding4);
+         assertTrue(binding2 == binding4);
+         assertEquivalent(binding2, binding4);
+         assertNotNull(binding4.getQueue());
+         assertEquals(false, binding4.getQueue().isRecoverable());
+         
+         office1.stop();
+         
+         //Throw away the exchange and create another
+         office2 = createPostOffice();
+         
+         //Only one binding should be there
+         Binding binding5 = office2.getBindingForQueueName("durableQueue");
+         assertNotNull(binding5);
+         assertEquivalent(binding1, binding5);
+         //Should be unloaded
+         assertNull(binding5.getQueue());
+         
+         Binding binding6 = office2.getBindingForQueueName("nonDurableQueue");
+         assertNull(binding6);
+         
+         //Unbind the binding
+         Binding binding7 = office2.unbindQueue("durableQueue");
+         assertNotNull(binding7);
+         assertEquivalent(binding1, binding7);
+         
+         //Make sure no longer there
+         Binding binding8 = office2.getBindingForQueueName("durableQueue");
+         assertNull(binding8);
+         
+         office2.stop();
+         
+         //Throw away exchange and start another
+         office3 = createPostOffice();
+         
+         //Make sure not there
+         Binding binding9 = office3.getBindingForQueueName("durableQueue");
+         assertNull(binding9);
+         
+         office3.stop();
+      }
+      finally
+      {
+         if (office1 != null)
+         {
+            office1.stop();
+         }
+         
+         if (office2 != null)
+         {
+            office2.stop();
+         }
+         
+         if (office3 != null)
+         {
+            office2.stop();
+         }
+      }
+            
+   }
+   
+   public final void testListBindings() throws Throwable
+   {
+      PostOffice office = null;
+      
+      try
+      {      
+         office = createPostOffice();
+         
+         Queue queue1 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding1 =
+            office.bindQueue("queue1", "condition1", false, queue1);
+         
+         Queue queue2 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding2 =
+            office.bindQueue("queue2", "condition1",false, queue2);
+         
+         Queue queue3 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding3 =
+            office.bindQueue("queue3", "condition1", false, queue3);
+         
+         Queue queue4 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding4 =
+            office.bindQueue("queue4", "condition1", false, queue4);
+         
+         Queue queue5 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding5 =
+            office.bindQueue("queue5", "condition2", false, queue5);
+         
+         Queue queue6 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding6 =
+            office.bindQueue("queue6", "condition2", false, queue6);
+         
+         Queue queue7 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding7 =
+            office.bindQueue("queue7", "condition2", false, queue7);
+         
+         Queue queue8 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding8 =
+            office.bindQueue("queue8", "condition2", false, queue8);
+         
+         
+         List bindings = office.listBindingsForCondition("dummy");
+         assertNotNull(bindings);
+         assertTrue(bindings.isEmpty());
+         
+         //We don't match on substrings
+         bindings = office.listBindingsForCondition("condition123");
+         assertNotNull(bindings);
+         assertTrue(bindings.isEmpty());
+         
+         //We don't currently support hierarchies
+         bindings = office.listBindingsForCondition("condition1.subcondition");
+         assertNotNull(bindings);
+         assertTrue(bindings.isEmpty());
+         
+         //We currently just do an exact match
+         bindings = office.listBindingsForCondition("condition1");
+         assertNotNull(bindings);
+         assertEquals(4, bindings.size());
+         
+         assertEquivalent((Binding)bindings.get(0), binding1);
+         assertEquivalent((Binding)bindings.get(1), binding2);
+         assertEquivalent((Binding)bindings.get(2), binding3);
+         assertEquivalent((Binding)bindings.get(3), binding4);
+         
+         bindings = office.listBindingsForCondition("condition2");
+         assertNotNull(bindings);
+         assertEquals(4, bindings.size());
+         
+         assertEquivalent((Binding)bindings.get(0), binding5);
+         assertEquivalent((Binding)bindings.get(1), binding6);
+         assertEquivalent((Binding)bindings.get(2), binding7);
+         assertEquivalent((Binding)bindings.get(3), binding8);
+      }
+      finally
+      {
+         if (office != null)
+         {
+            office.stop();
+         }
+      }
+         
+   }
+   
+   public final void testRoutePersistent() throws Throwable
+   {
+      route(true);
+   }
+   
+   public final void testRouteNonPersistent() throws Throwable
+   {
+      route(false);
+   }
+   
+   public final void testRouteTransactionalPersistent() throws Throwable
+   {
+      routeTransactional(true);
+   }
+   
+   public final void testRouteTransactionalNonPersistent() throws Throwable
+   {
+      routeTransactional(false);
+   }
+   
+      
+   public final void testRouteInactive() throws Throwable
+   {
+      PostOffice postOffice = null;
+      
+      try
+      {
+      
+         postOffice = createPostOffice();
+         
+         Queue queue1 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding1 =
+            postOffice.bindQueue("queue1", "topic1", false, queue1);
+         
+         Queue queue2 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding2 =
+            postOffice.bindQueue("queue2", "topic1",false, queue2);
+         
+         Queue queue3 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding3 =
+            postOffice.bindQueue("queue3", "topic1", false, queue3);
+         
+         Queue queue4 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding4 =
+            postOffice.bindQueue("queue4", "topic2", false, queue4);
+         
+         Queue queue5 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding5 =
+            postOffice.bindQueue("queue5", "topic2", false, queue5);
+         
+         Queue queue6 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding6 =
+            postOffice.bindQueue("queue6", "topic2", false, queue6);
+      
+         SimpleReceiver receiver1 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
+         queue1.add(receiver1);
+         SimpleReceiver receiver2 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
+         queue2.add(receiver2);
+         SimpleReceiver receiver3 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
+         queue3.add(receiver3);
+         SimpleReceiver receiver4 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
+         queue4.add(receiver4);
+         SimpleReceiver receiver5 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
+         queue5.add(receiver5);
+         SimpleReceiver receiver6 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
+         queue6.add(receiver6);
+         
+         binding1.deactivate();
+         binding2.deactivate();
+         binding5.deactivate();
+         binding6.deactivate();
+         
+         assertFalse(binding1.isActive());      
+         assertFalse(binding2.isActive());
+         assertFalse(binding5.isActive());
+         assertFalse(binding6.isActive()); 
+         assertTrue(binding3.isActive());
+         assertTrue(binding4.isActive());      
+         
+         Message msg1 = MessageFactory.createCoreMessage(1);      
+         MessageReference ref1 = ms.reference(msg1);
+         
+         boolean routed = postOffice.route(ref1, "topic1", null);      
+         assertTrue(routed);
+         
+         List msgs = receiver1.getMessages();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+         
+         msgs = receiver2.getMessages();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+         
+         msgs = receiver3.getMessages();
+         assertNotNull(msgs);
+         assertEquals(1, msgs.size());
+         Message msgRec = (Message)msgs.get(0);
+         assertTrue(msg1 == msgRec);
+         receiver3.acknowledge(msgRec, null);
+         msgs = queue3.browse();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());  
+         
+         msgs = receiver4.getMessages();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+         
+         msgs = receiver5.getMessages();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+         
+         msgs = receiver6.getMessages();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+         
+         receiver3.clear();
+                     
+         Message msg2 = MessageFactory.createCoreMessage(2);      
+         MessageReference ref2 = ms.reference(msg2);
+         
+         routed = postOffice.route(ref2, "topic2", null);      
+         assertTrue(routed);
+         
+         msgs = receiver1.getMessages();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+         
+         msgs = receiver2.getMessages();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+         
+         msgs = receiver3.getMessages();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());      
+         
+         msgs = receiver4.getMessages();
+         assertNotNull(msgs);
+         assertEquals(1, msgs.size());
+         msgRec = (Message)msgs.get(0);
+         assertTrue(msg2 == msgRec);
+         receiver4.acknowledge(msgRec, null);
+         msgs = queue4.browse();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());  
+         
+         msgs = receiver5.getMessages();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+         
+         msgs = receiver6.getMessages();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+      }
+      finally
+      {
+         if (postOffice != null)
+         {
+            postOffice.stop();
+         }
+      }
+   
+   }
+
+   public final void testRouteNoBinding() throws Throwable
+   {
+      PostOffice postOffice = null;
+      
+      try
+      {      
+         postOffice = createPostOffice();
+         
+         Queue queue1 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding1 =
+            postOffice.bindQueue("queue1", "condition1", false, queue1);
+              
+         SimpleReceiver receiver1 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
+         queue1.add(receiver1);
+   
+         assertTrue(binding1.isActive());
+   
+         Message msg1 = MessageFactory.createCoreMessage(1);      
+         MessageReference ref1 = ms.reference(msg1);
+         
+         boolean routed = postOffice.route(ref1, "this won't match anything", null);      
+         
+         assertFalse(routed);
+               
+         List msgs = receiver1.getMessages();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());             
+         
+      }
+      finally
+      {
+         if (postOffice != null)
+         {
+            postOffice.stop();
+         }
+      }
+   }
+   
+   
+   
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+   
+   protected void route(boolean persistentMessage) throws Throwable
+   {
+      PostOffice postOffice = null;
+      
+      try
+      {      
+         postOffice = createPostOffice();
+      
+         Queue queue1 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding1 =
+            postOffice.bindQueue("queue1", "topic1", false, queue1);
+         
+         Queue queue2 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding2 =
+            postOffice.bindQueue("queue2", "topic1",false, queue2);
+         
+         Queue queue3 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding3 =
+            postOffice.bindQueue("queue3", "topic1", false, queue3);
+         
+         Queue queue4 = new Queue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding4 =
+            postOffice.bindQueue("queue4", "topic2", false, queue4);
+         
+         Queue queue5 = new Queue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding5 =
+            postOffice.bindQueue("queue5", "topic2", false, queue5);
+         
+         Queue queue6 = new Queue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding6 =
+            postOffice.bindQueue("queue6", "topic2", false, queue6);
+      
+         SimpleReceiver receiver1 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
+         queue1.add(receiver1);
+         SimpleReceiver receiver2 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
+         queue2.add(receiver2);
+         SimpleReceiver receiver3 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
+         queue3.add(receiver3);
+         SimpleReceiver receiver4 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
+         queue4.add(receiver4);
+         SimpleReceiver receiver5 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
+         queue5.add(receiver5);
+         SimpleReceiver receiver6 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
+         queue6.add(receiver6);
+         
+         assertTrue(binding1.isActive());      
+         assertTrue(binding2.isActive());
+         assertTrue(binding3.isActive());      
+         assertTrue(binding4.isActive());
+         assertTrue(binding5.isActive());      
+         assertTrue(binding6.isActive());
+         
+         Message msg1 = MessageFactory.createCoreMessage(1, persistentMessage, null);      
+         MessageReference ref1 = ms.reference(msg1);
+         
+         boolean routed = postOffice.route(ref1, "topic1", null);      
+         assertTrue(routed);
+         
+         List msgs = receiver1.getMessages();
+         assertNotNull(msgs);
+         assertEquals(1, msgs.size());
+         Message msgRec = (Message)msgs.get(0);
+         assertTrue(msg1 == msgRec);
+         receiver1.acknowledge(msgRec, null);
+         msgs = queue1.browse();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+         
+         msgs = receiver2.getMessages();
+         assertNotNull(msgs);
+         assertEquals(1, msgs.size());
+         msgRec = (Message)msgs.get(0);
+         assertTrue(msg1 == msgRec);
+         receiver2.acknowledge(msgRec, null);
+         msgs = queue2.browse();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+         
+         msgs = receiver3.getMessages();
+         assertNotNull(msgs);
+         assertEquals(1, msgs.size());
+         msgRec = (Message)msgs.get(0);
+         assertTrue(msg1 == msgRec);
+         receiver3.acknowledge(msgRec, null);
+         msgs = queue3.browse();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+         
+         msgs = receiver4.getMessages();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+         
+         msgs = receiver5.getMessages();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+         
+         msgs = receiver6.getMessages();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+         
+         receiver1.clear();
+         receiver2.clear();
+         receiver3.clear();
+         
+         
+         Message msg2 = MessageFactory.createCoreMessage(2, persistentMessage, null);      
+         MessageReference ref2 = ms.reference(msg2);
+         
+         routed = postOffice.route(ref2, "topic2", null);      
+         assertTrue(routed);
+         
+         msgs = receiver4.getMessages();
+         assertNotNull(msgs);
+         assertEquals(1, msgs.size());
+         msgRec = (Message)msgs.get(0);
+         assertTrue(msg2 == msgRec);
+         receiver4.acknowledge(msgRec, null);
+         msgs = queue4.browse();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+         
+         msgs = receiver5.getMessages();
+         assertNotNull(msgs);
+         assertEquals(1, msgs.size());
+         msgRec = (Message)msgs.get(0);
+         assertTrue(msg2 == msgRec);
+         receiver5.acknowledge(msgRec, null);
+         msgs = queue5.browse();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+         
+         msgs = receiver6.getMessages();
+         assertNotNull(msgs);
+         assertEquals(1, msgs.size());
+         msgRec = (Message)msgs.get(0);
+         assertTrue(msg2 == msgRec);
+         receiver6.acknowledge(msgRec, null);
+         msgs = queue6.browse();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());    
+         
+         msgs = receiver1.getMessages();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+         
+         msgs = receiver2.getMessages();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+         
+         msgs = receiver3.getMessages();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+         
+      }
+      finally
+      {
+         if (postOffice != null)
+         {
+            postOffice.stop();
+         }
+      }
+   }
+   
+   protected void routeTransactional(boolean persistentMessage) throws Throwable
+   {
+      PostOffice postOffice = null;
+      
+      try
+      {      
+         postOffice = createPostOffice();
+      
+         Queue queue1 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding1 =
+            postOffice.bindQueue("queue1", "topic1", false, queue1);
+         
+         Queue queue2 = new Queue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get(), null);         
+         Binding binding2 =
+            postOffice.bindQueue("queue2", "topic1",false, queue2);
+          
+         SimpleReceiver receiver1 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
+         queue1.add(receiver1);
+
+         SimpleReceiver receiver2 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
+         queue2.add(receiver2);
+   
+         assertTrue(binding1.isActive());
+         assertTrue(binding2.isActive());
+   
+         Message msg1 = MessageFactory.createCoreMessage(1, persistentMessage, null);      
+         MessageReference ref1 = ms.reference(msg1);
+         
+         Message msg2 = MessageFactory.createCoreMessage(2, persistentMessage, null);      
+         MessageReference ref2 = ms.reference(msg2);
+         
+         Transaction tx = tr.createTransaction();
+         
+         boolean routed = postOffice.route(ref1, "topic1", tx);            
+         assertTrue(routed);
+         routed = postOffice.route(ref2, "topic1", tx);            
+         assertTrue(routed);
+               
+         List msgs = queue1.browse();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+         
+         msgs = queue2.browse();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+         
+         tx.commit();
+         
+         msgs = receiver1.getMessages();
+         assertNotNull(msgs);
+         assertEquals(2, msgs.size());
+         Message msgRec1 = (Message)msgs.get(0);
+         Message msgRec2 = (Message)msgs.get(1);
+         assertTrue(msgRec1 == msg1);
+         assertTrue(msgRec2 == msg2);
+         
+         msgs = receiver2.getMessages();
+         assertNotNull(msgs);
+         assertEquals(2, msgs.size());
+         msgRec1 = (Message)msgs.get(0);
+         msgRec2 = (Message)msgs.get(1);
+         assertTrue(msgRec1 == msg1);
+         assertTrue(msgRec2 == msg2);
+         
+         //Acknowledge non transactionally
+         receiver1.acknowledge(msgRec1, null);
+         receiver1.acknowledge(msgRec2, null);
+         
+         receiver2.acknowledge(msgRec1, null);
+         receiver2.acknowledge(msgRec2, null);
+   
+         msgs = queue1.browse();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty()); 
+         
+         receiver1.clear();
+         
+         msgs = queue2.browse();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty()); 
+         
+         receiver2.clear();
+              
+         Message msg3 = MessageFactory.createCoreMessage(3, persistentMessage, null);      
+         MessageReference ref3 = ms.reference(msg3);
+         
+         Message msg4 = MessageFactory.createCoreMessage(4, persistentMessage, null);      
+         MessageReference ref4 = ms.reference(msg4);
+         
+         tx = tr.createTransaction();
+         
+         routed = postOffice.route(ref3, "topic1", tx);            
+         assertTrue(routed);
+         routed = postOffice.route(ref4, "topic1", tx);            
+         assertTrue(routed);
+               
+         msgs = queue1.browse();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty()); 
+         
+         msgs = queue2.browse();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty()); 
+         
+         tx.rollback();
+         
+         msgs = receiver1.getMessages();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+         
+         receiver1.clear();
+         
+         msgs = receiver2.getMessages();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+         
+         receiver2.clear();
+         
+         
+         Message msg5 = MessageFactory.createCoreMessage(5, persistentMessage, null);      
+         MessageReference ref5 = ms.reference(msg5);
+         
+         Message msg6 = MessageFactory.createCoreMessage(6, persistentMessage, null);      
+         MessageReference ref6 = ms.reference(msg6);
+               
+         routed = postOffice.route(ref5, "topic1", null);            
+         assertTrue(routed);
+         routed = postOffice.route(ref6, "topic1", null);            
+         assertTrue(routed);
+         
+         msgs = receiver1.getMessages();
+         assertNotNull(msgs);
+         assertEquals(2, msgs.size());
+         msgRec1 = (Message)msgs.get(0);
+         msgRec2 = (Message)msgs.get(1);
+         assertTrue(msgRec1 == msg5);
+         assertTrue(msgRec2 == msg6);
+         
+         msgs = receiver2.getMessages();
+         assertNotNull(msgs);
+         assertEquals(2, msgs.size());
+         msgRec1 = (Message)msgs.get(0);
+         msgRec2 = (Message)msgs.get(1);
+         assertTrue(msgRec1 == msg5);
+         assertTrue(msgRec2 == msg6);
+         
+         //Acknowledge transactionally
+         
+         tx = tr.createTransaction();
+         
+         receiver1.acknowledge(msgRec1, tx);
+         receiver1.acknowledge(msgRec2, tx);
+         
+         receiver2.acknowledge(msgRec1, tx);
+         receiver2.acknowledge(msgRec2, tx);
+         
+         msgs = queue1.browse();
+         assertNotNull(msgs);
+         assertEquals(2, msgs.size());
+         msgRec1 = (Message)msgs.get(0);
+         msgRec2 = (Message)msgs.get(1);
+         assertTrue(msgRec1 == msg5);
+         assertTrue(msgRec2 == msg6);
+         
+         msgs = queue2.browse();
+         assertNotNull(msgs);
+         assertEquals(2, msgs.size());
+         msgRec1 = (Message)msgs.get(0);
+         msgRec2 = (Message)msgs.get(1);
+         assertTrue(msgRec1 == msg5);
+         assertTrue(msgRec2 == msg6);
+         
+         tx.commit();
+         
+         msgs = queue1.browse();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+               
+         receiver1.clear();
+         
+         msgs = queue2.browse();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());
+               
+         receiver2.clear();
+         
+         Message msg7 = MessageFactory.createCoreMessage(7, persistentMessage, null);      
+         MessageReference ref7 = ms.reference(msg7);
+         
+         Message msg8 = MessageFactory.createCoreMessage(8, persistentMessage, null);      
+         MessageReference ref8 = ms.reference(msg8);
+               
+         routed = postOffice.route(ref7, "topic1", null);            
+         assertTrue(routed);
+         routed = postOffice.route(ref8, "topic1", null);            
+         assertTrue(routed);
+         
+         msgs = receiver1.getMessages();
+         assertNotNull(msgs);
+         assertEquals(2, msgs.size());
+         msgRec1 = (Message)msgs.get(0);
+         msgRec2 = (Message)msgs.get(1);
+         assertTrue(msgRec1 == msg7);
+         assertTrue(msgRec2 == msg8);
+         
+         msgs = receiver2.getMessages();
+         assertNotNull(msgs);
+         assertEquals(2, msgs.size());
+         msgRec1 = (Message)msgs.get(0);
+         msgRec2 = (Message)msgs.get(1);
+         assertTrue(msgRec1 == msg7);
+         assertTrue(msgRec2 == msg8);
+         
+         //Acknowledge transactionally
+         
+         tx = tr.createTransaction();
+         
+         receiver1.acknowledge(msgRec1, tx);
+         receiver1.acknowledge(msgRec2, tx);
+         
+         receiver2.acknowledge(msgRec1, tx);
+         receiver2.acknowledge(msgRec2, tx);
+         
+         msgs = queue1.browse();
+         assertNotNull(msgs);
+         assertEquals(2, msgs.size());
+         msgRec1 = (Message)msgs.get(0);
+         msgRec2 = (Message)msgs.get(1);
+         assertTrue(msgRec1 == msg7);
+         assertTrue(msgRec2 == msg8);
+         
+         msgs = queue2.browse();
+         assertNotNull(msgs);
+         assertEquals(2, msgs.size());
+         msgRec1 = (Message)msgs.get(0);
+         msgRec2 = (Message)msgs.get(1);
+         assertTrue(msgRec1 == msg7);
+         assertTrue(msgRec2 == msg8);
+         
+         tx.rollback();
+         
+         msgs = queue1.browse();
+         assertNotNull(msgs);
+         assertEquals(2, msgs.size());
+         msgRec1 = (Message)msgs.get(0);
+         msgRec2 = (Message)msgs.get(1);
+         assertTrue(msgRec1 == msg7);
+         assertTrue(msgRec2 == msg8);
+         
+         msgs = queue2.browse();
+         assertNotNull(msgs);
+         assertEquals(2, msgs.size());
+         msgRec1 = (Message)msgs.get(0);
+         msgRec2 = (Message)msgs.get(1);
+         assertTrue(msgRec1 == msg7);
+         assertTrue(msgRec2 == msg8);        
+      }
+      finally
+      {
+         if (postOffice != null)
+         {
+            postOffice.stop();
+         }
+      }
+   }
+   
+   protected void assertEquivalent(Binding binding1, Binding binding2)
+   {
+      assertEquals(binding1.getNodeId(), binding2.getNodeId());
+      assertEquals(binding1.getQueueName(), binding2.getQueueName());      
+      assertEquals(binding1.getSelector(), binding2.getSelector());
+      assertEquals(binding1.getChannelId(), binding2.getChannelId());
+      assertEquals(binding1.isDurable(), binding2.isDurable());
+      assertEquals(binding1.isNoLocal(), binding2.isNoLocal());
+   }
+   
+   protected PostOffice createPostOffice() throws Exception
+   {
+      PostOfficeImpl postOffice = 
+         new PostOfficeImpl(sc.getDataSource(), sc.getTransactionManager(),
+                              null, true, "node1", "Simple", ms);
+      
+      postOffice.start();      
+      
+      return postOffice;
+   }
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+   
+}
+

Deleted: trunk/tests/src/org/jboss/test/messaging/core/plugin/TopicExchangeTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/plugin/TopicExchangeTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/plugin/TopicExchangeTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -1,718 +0,0 @@
-/*
-  * 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.test.messaging.core.plugin;
-
-import java.util.List;
-
-import org.jboss.messaging.core.Message;
-import org.jboss.messaging.core.MessageReference;
-import org.jboss.messaging.core.local.MessageQueue;
-import org.jboss.messaging.core.message.MessageFactory;
-import org.jboss.messaging.core.plugin.contract.Exchange;
-import org.jboss.messaging.core.plugin.exchange.Binding;
-import org.jboss.messaging.core.plugin.exchange.TopicExchange;
-import org.jboss.messaging.core.tx.Transaction;
-import org.jboss.test.messaging.core.SimpleReceiver;
-import org.jboss.test.messaging.core.plugin.base.ExchangeTestBase;
-
-/**
- * 
- * A TopicExchangeTest
-
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision: 1.1 $</tt>
- *
- * $Id$
- *
- */
-public class TopicExchangeTest extends ExchangeTestBase
-{
-   // Constants -----------------------------------------------------
-
-   // Static --------------------------------------------------------
-   
-   // Attributes ----------------------------------------------------
-
-   // Constructors --------------------------------------------------
-
-   public TopicExchangeTest(String name)
-   {
-      super(name);
-   }
-
-   // Public --------------------------------------------------------
-
-   public void setUp() throws Exception
-   {
-      super.setUp();            
-   }
-
-   public void tearDown() throws Exception
-   {      
-     
-      super.tearDown();
-   }
-   
-   public final void testRoutePersistent() throws Throwable
-   {
-      route(true);
-   }
-   
-   public final void testRouteNonPersistent() throws Throwable
-   {
-      route(false);
-   }
-   
-   public final void testRouteTransactionalPersistent() throws Throwable
-   {
-      routeTransactional(true);
-   }
-   
-   public final void testRouteTransactionalNonPersistent() throws Throwable
-   {
-      routeTransactional(false);
-   }
-   
-      
-   public final void testRouteInactive() throws Throwable
-   {
-      Exchange exchange = null;
-      
-      try
-      {
-      
-         exchange = createExchange();
-         
-         Binding binding1 =
-            exchange.bindQueue("sub1", "topic1", null, false, false, ms, pm, 1000, 20, 20);      
-         Binding binding2 =
-            exchange.bindQueue("sub2", "topic1", null, false, false, ms, pm, 1000, 20, 20);
-         Binding binding3 =
-            exchange.bindQueue("sub3", "topic1", null, false, false, ms, pm, 1000, 20, 20);      
-         Binding binding4 =
-            exchange.bindQueue("sub4", "topic2", null, false, true, ms, pm, 1000, 20, 20);
-         Binding binding5 =
-            exchange.bindQueue("sub5", "topic2", null, false, true, ms, pm, 1000, 20, 20);      
-         Binding binding6 =
-            exchange.bindQueue("sub6", "topic2", null, false, true, ms, pm, 1000, 20, 20);
-         
-         MessageQueue queue1 = binding1.getQueue();      
-         MessageQueue queue2 = binding2.getQueue();
-         MessageQueue queue3 = binding3.getQueue();      
-         MessageQueue queue4 = binding4.getQueue();
-         MessageQueue queue5 = binding5.getQueue();      
-         MessageQueue queue6 = binding6.getQueue();
-         SimpleReceiver receiver1 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
-         queue1.add(receiver1);
-         SimpleReceiver receiver2 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
-         queue2.add(receiver2);
-         SimpleReceiver receiver3 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
-         queue3.add(receiver3);
-         SimpleReceiver receiver4 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
-         queue4.add(receiver4);
-         SimpleReceiver receiver5 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
-         queue5.add(receiver5);
-         SimpleReceiver receiver6 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
-         queue6.add(receiver6);
-         
-         binding1.deactivate();
-         binding2.deactivate();
-         binding5.deactivate();
-         binding6.deactivate();
-         
-         assertFalse(binding1.isActive());      
-         assertFalse(binding2.isActive());
-         assertFalse(binding5.isActive());
-         assertFalse(binding6.isActive()); 
-         assertTrue(binding3.isActive());
-         assertTrue(binding4.isActive());      
-         
-         Message msg1 = MessageFactory.createCoreMessage(1);      
-         MessageReference ref1 = ms.reference(msg1);
-         
-         boolean routed = exchange.route(ref1, "topic1", null);      
-         assertTrue(routed);
-         
-         List msgs = receiver1.getMessages();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-         
-         msgs = receiver2.getMessages();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-         
-         msgs = receiver3.getMessages();
-         assertNotNull(msgs);
-         assertEquals(1, msgs.size());
-         Message msgRec = (Message)msgs.get(0);
-         assertTrue(msg1 == msgRec);
-         receiver3.acknowledge(msgRec, null);
-         msgs = queue3.browse();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());  
-         
-         msgs = receiver4.getMessages();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-         
-         msgs = receiver5.getMessages();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-         
-         msgs = receiver6.getMessages();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-         
-         receiver3.clear();
-                     
-         Message msg2 = MessageFactory.createCoreMessage(2);      
-         MessageReference ref2 = ms.reference(msg2);
-         
-         routed = exchange.route(ref2, "topic2", null);      
-         assertTrue(routed);
-         
-         msgs = receiver1.getMessages();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-         
-         msgs = receiver2.getMessages();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-         
-         msgs = receiver3.getMessages();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());      
-         
-         msgs = receiver4.getMessages();
-         assertNotNull(msgs);
-         assertEquals(1, msgs.size());
-         msgRec = (Message)msgs.get(0);
-         assertTrue(msg2 == msgRec);
-         receiver4.acknowledge(msgRec, null);
-         msgs = queue4.browse();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());  
-         
-         msgs = receiver5.getMessages();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-         
-         msgs = receiver6.getMessages();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-      }
-      finally
-      {
-         if (exchange != null)
-         {
-            exchange.stop();
-         }
-      }
-   
-   }
-
-   public final void testRouteNoBinding() throws Throwable
-   {
-      Exchange exchange = null;
-      
-      try
-      {      
-         exchange = createExchange();
-         
-         Binding binding1 =
-            exchange.bindQueue("sub1", "topic1", null, false, false, ms, pm, 1000, 20, 20);      
-   
-         MessageQueue queue1 = binding1.getQueue();
-         SimpleReceiver receiver1 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
-         queue1.add(receiver1);
-   
-         assertTrue(binding1.isActive());
-   
-         Message msg1 = MessageFactory.createCoreMessage(1);      
-         MessageReference ref1 = ms.reference(msg1);
-         
-         boolean routed = exchange.route(ref1, "this won't match anything", null);      
-         
-         //A topic exchange always returns true even if there is no binding
-         assertTrue(routed);
-               
-         List msgs = receiver1.getMessages();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());             
-         
-      }
-      finally
-      {
-         if (exchange != null)
-         {
-            exchange.stop();
-         }
-      }
-   }
-   
-   
-   
-   // Package protected ---------------------------------------------
-
-   // Protected -----------------------------------------------------
-   
-   protected void route(boolean persistentMessage) throws Throwable
-   {
-      Exchange exchange = null;
-      
-      try
-      {      
-         exchange = createExchange();
-      
-         Binding binding1 =
-            exchange.bindQueue("sub1", "topic1", null, false, false, ms, pm, 1000, 20, 20);      
-         Binding binding2 =
-            exchange.bindQueue("sub2", "topic1", null, false, false, ms, pm, 1000, 20, 20);
-         Binding binding3 =
-            exchange.bindQueue("sub3", "topic1", null, false, false, ms, pm, 1000, 20, 20);      
-         Binding binding4 =
-            exchange.bindQueue("sub4", "topic2", null, false, true, ms, pm, 1000, 20, 20);
-         Binding binding5 =
-            exchange.bindQueue("sub5", "topic2", null, false, true, ms, pm, 1000, 20, 20);      
-         Binding binding6 =
-            exchange.bindQueue("sub6", "topic2", null, false, true, ms, pm, 1000, 20, 20);
-         
-         MessageQueue queue1 = binding1.getQueue();      
-         MessageQueue queue2 = binding2.getQueue();
-         MessageQueue queue3 = binding3.getQueue();      
-         MessageQueue queue4 = binding4.getQueue();
-         MessageQueue queue5 = binding5.getQueue();      
-         MessageQueue queue6 = binding6.getQueue();
-         SimpleReceiver receiver1 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
-         queue1.add(receiver1);
-         SimpleReceiver receiver2 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
-         queue2.add(receiver2);
-         SimpleReceiver receiver3 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
-         queue3.add(receiver3);
-         SimpleReceiver receiver4 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
-         queue4.add(receiver4);
-         SimpleReceiver receiver5 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
-         queue5.add(receiver5);
-         SimpleReceiver receiver6 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
-         queue6.add(receiver6);
-         
-         assertTrue(binding1.isActive());      
-         assertTrue(binding2.isActive());
-         assertTrue(binding3.isActive());      
-         assertTrue(binding4.isActive());
-         assertTrue(binding5.isActive());      
-         assertTrue(binding6.isActive());
-         
-         Message msg1 = MessageFactory.createCoreMessage(1, persistentMessage, null);      
-         MessageReference ref1 = ms.reference(msg1);
-         
-         boolean routed = exchange.route(ref1, "topic1", null);      
-         assertTrue(routed);
-         
-         List msgs = receiver1.getMessages();
-         assertNotNull(msgs);
-         assertEquals(1, msgs.size());
-         Message msgRec = (Message)msgs.get(0);
-         assertTrue(msg1 == msgRec);
-         receiver1.acknowledge(msgRec, null);
-         msgs = queue1.browse();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-         
-         msgs = receiver2.getMessages();
-         assertNotNull(msgs);
-         assertEquals(1, msgs.size());
-         msgRec = (Message)msgs.get(0);
-         assertTrue(msg1 == msgRec);
-         receiver2.acknowledge(msgRec, null);
-         msgs = queue2.browse();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-         
-         msgs = receiver3.getMessages();
-         assertNotNull(msgs);
-         assertEquals(1, msgs.size());
-         msgRec = (Message)msgs.get(0);
-         assertTrue(msg1 == msgRec);
-         receiver3.acknowledge(msgRec, null);
-         msgs = queue3.browse();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-         
-         msgs = receiver4.getMessages();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-         
-         msgs = receiver5.getMessages();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-         
-         msgs = receiver6.getMessages();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-         
-         receiver1.clear();
-         receiver2.clear();
-         receiver3.clear();
-         
-         
-         Message msg2 = MessageFactory.createCoreMessage(2, persistentMessage, null);      
-         MessageReference ref2 = ms.reference(msg2);
-         
-         routed = exchange.route(ref2, "topic2", null);      
-         assertTrue(routed);
-         
-         msgs = receiver4.getMessages();
-         assertNotNull(msgs);
-         assertEquals(1, msgs.size());
-         msgRec = (Message)msgs.get(0);
-         assertTrue(msg2 == msgRec);
-         receiver4.acknowledge(msgRec, null);
-         msgs = queue4.browse();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-         
-         msgs = receiver5.getMessages();
-         assertNotNull(msgs);
-         assertEquals(1, msgs.size());
-         msgRec = (Message)msgs.get(0);
-         assertTrue(msg2 == msgRec);
-         receiver5.acknowledge(msgRec, null);
-         msgs = queue5.browse();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-         
-         msgs = receiver6.getMessages();
-         assertNotNull(msgs);
-         assertEquals(1, msgs.size());
-         msgRec = (Message)msgs.get(0);
-         assertTrue(msg2 == msgRec);
-         receiver6.acknowledge(msgRec, null);
-         msgs = queue6.browse();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());    
-         
-         msgs = receiver1.getMessages();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-         
-         msgs = receiver2.getMessages();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-         
-         msgs = receiver3.getMessages();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-         
-      }
-      finally
-      {
-         if (exchange != null)
-         {
-            exchange.stop();
-         }
-      }
-   }
-   
-   protected void routeTransactional(boolean persistentMessage) throws Throwable
-   {
-      Exchange exchange = null;
-      
-      try
-      {      
-         exchange = createExchange();
-      
-         Binding binding1 =
-            exchange.bindQueue("sub1", "topic1", null, false, false, ms, pm, 1000, 20, 20);     
-         Binding binding2 =
-            exchange.bindQueue("sub2", "topic1", null, false, true, ms, pm, 1000, 20, 20);  
-   
-         MessageQueue queue1 = binding1.getQueue();
-         SimpleReceiver receiver1 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
-         queue1.add(receiver1);
-         MessageQueue queue2 = binding2.getQueue();
-         SimpleReceiver receiver2 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
-         queue2.add(receiver2);
-   
-         assertTrue(binding1.isActive());
-         assertTrue(binding2.isActive());
-   
-         Message msg1 = MessageFactory.createCoreMessage(1, persistentMessage, null);      
-         MessageReference ref1 = ms.reference(msg1);
-         
-         Message msg2 = MessageFactory.createCoreMessage(2, persistentMessage, null);      
-         MessageReference ref2 = ms.reference(msg2);
-         
-         Transaction tx = tr.createTransaction();
-         
-         boolean routed = exchange.route(ref1, "topic1", tx);            
-         assertTrue(routed);
-         routed = exchange.route(ref2, "topic1", tx);            
-         assertTrue(routed);
-               
-         List msgs = queue1.browse();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-         
-         msgs = queue2.browse();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-         
-         tx.commit();
-         
-         msgs = receiver1.getMessages();
-         assertNotNull(msgs);
-         assertEquals(2, msgs.size());
-         Message msgRec1 = (Message)msgs.get(0);
-         Message msgRec2 = (Message)msgs.get(1);
-         assertTrue(msgRec1 == msg1);
-         assertTrue(msgRec2 == msg2);
-         
-         msgs = receiver2.getMessages();
-         assertNotNull(msgs);
-         assertEquals(2, msgs.size());
-         msgRec1 = (Message)msgs.get(0);
-         msgRec2 = (Message)msgs.get(1);
-         assertTrue(msgRec1 == msg1);
-         assertTrue(msgRec2 == msg2);
-         
-         //Acknowledge non transactionally
-         receiver1.acknowledge(msgRec1, null);
-         receiver1.acknowledge(msgRec2, null);
-         
-         receiver2.acknowledge(msgRec1, null);
-         receiver2.acknowledge(msgRec2, null);
-   
-         msgs = queue1.browse();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty()); 
-         
-         receiver1.clear();
-         
-         msgs = queue2.browse();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty()); 
-         
-         receiver2.clear();
-              
-         Message msg3 = MessageFactory.createCoreMessage(3, persistentMessage, null);      
-         MessageReference ref3 = ms.reference(msg3);
-         
-         Message msg4 = MessageFactory.createCoreMessage(4, persistentMessage, null);      
-         MessageReference ref4 = ms.reference(msg4);
-         
-         tx = tr.createTransaction();
-         
-         routed = exchange.route(ref3, "topic1", tx);            
-         assertTrue(routed);
-         routed = exchange.route(ref4, "topic1", tx);            
-         assertTrue(routed);
-               
-         msgs = queue1.browse();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty()); 
-         
-         msgs = queue2.browse();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty()); 
-         
-         tx.rollback();
-         
-         msgs = receiver1.getMessages();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-         
-         receiver1.clear();
-         
-         msgs = receiver2.getMessages();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-         
-         receiver2.clear();
-         
-         
-         Message msg5 = MessageFactory.createCoreMessage(5, persistentMessage, null);      
-         MessageReference ref5 = ms.reference(msg5);
-         
-         Message msg6 = MessageFactory.createCoreMessage(6, persistentMessage, null);      
-         MessageReference ref6 = ms.reference(msg6);
-               
-         routed = exchange.route(ref5, "topic1", null);            
-         assertTrue(routed);
-         routed = exchange.route(ref6, "topic1", null);            
-         assertTrue(routed);
-         
-         msgs = receiver1.getMessages();
-         assertNotNull(msgs);
-         assertEquals(2, msgs.size());
-         msgRec1 = (Message)msgs.get(0);
-         msgRec2 = (Message)msgs.get(1);
-         assertTrue(msgRec1 == msg5);
-         assertTrue(msgRec2 == msg6);
-         
-         msgs = receiver2.getMessages();
-         assertNotNull(msgs);
-         assertEquals(2, msgs.size());
-         msgRec1 = (Message)msgs.get(0);
-         msgRec2 = (Message)msgs.get(1);
-         assertTrue(msgRec1 == msg5);
-         assertTrue(msgRec2 == msg6);
-         
-         //Acknowledge transactionally
-         
-         tx = tr.createTransaction();
-         
-         receiver1.acknowledge(msgRec1, tx);
-         receiver1.acknowledge(msgRec2, tx);
-         
-         receiver2.acknowledge(msgRec1, tx);
-         receiver2.acknowledge(msgRec2, tx);
-         
-         msgs = queue1.browse();
-         assertNotNull(msgs);
-         assertEquals(2, msgs.size());
-         msgRec1 = (Message)msgs.get(0);
-         msgRec2 = (Message)msgs.get(1);
-         assertTrue(msgRec1 == msg5);
-         assertTrue(msgRec2 == msg6);
-         
-         msgs = queue2.browse();
-         assertNotNull(msgs);
-         assertEquals(2, msgs.size());
-         msgRec1 = (Message)msgs.get(0);
-         msgRec2 = (Message)msgs.get(1);
-         assertTrue(msgRec1 == msg5);
-         assertTrue(msgRec2 == msg6);
-         
-         tx.commit();
-         
-         msgs = queue1.browse();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-               
-         receiver1.clear();
-         
-         msgs = queue2.browse();
-         assertNotNull(msgs);
-         assertTrue(msgs.isEmpty());
-               
-         receiver2.clear();
-         
-         Message msg7 = MessageFactory.createCoreMessage(7, persistentMessage, null);      
-         MessageReference ref7 = ms.reference(msg7);
-         
-         Message msg8 = MessageFactory.createCoreMessage(8, persistentMessage, null);      
-         MessageReference ref8 = ms.reference(msg8);
-               
-         routed = exchange.route(ref7, "topic1", null);            
-         assertTrue(routed);
-         routed = exchange.route(ref8, "topic1", null);            
-         assertTrue(routed);
-         
-         msgs = receiver1.getMessages();
-         assertNotNull(msgs);
-         assertEquals(2, msgs.size());
-         msgRec1 = (Message)msgs.get(0);
-         msgRec2 = (Message)msgs.get(1);
-         assertTrue(msgRec1 == msg7);
-         assertTrue(msgRec2 == msg8);
-         
-         msgs = receiver2.getMessages();
-         assertNotNull(msgs);
-         assertEquals(2, msgs.size());
-         msgRec1 = (Message)msgs.get(0);
-         msgRec2 = (Message)msgs.get(1);
-         assertTrue(msgRec1 == msg7);
-         assertTrue(msgRec2 == msg8);
-         
-         //Acknowledge transactionally
-         
-         tx = tr.createTransaction();
-         
-         receiver1.acknowledge(msgRec1, tx);
-         receiver1.acknowledge(msgRec2, tx);
-         
-         receiver2.acknowledge(msgRec1, tx);
-         receiver2.acknowledge(msgRec2, tx);
-         
-         msgs = queue1.browse();
-         assertNotNull(msgs);
-         assertEquals(2, msgs.size());
-         msgRec1 = (Message)msgs.get(0);
-         msgRec2 = (Message)msgs.get(1);
-         assertTrue(msgRec1 == msg7);
-         assertTrue(msgRec2 == msg8);
-         
-         msgs = queue2.browse();
-         assertNotNull(msgs);
-         assertEquals(2, msgs.size());
-         msgRec1 = (Message)msgs.get(0);
-         msgRec2 = (Message)msgs.get(1);
-         assertTrue(msgRec1 == msg7);
-         assertTrue(msgRec2 == msg8);
-         
-         tx.rollback();
-         
-         msgs = queue1.browse();
-         assertNotNull(msgs);
-         assertEquals(2, msgs.size());
-         msgRec1 = (Message)msgs.get(0);
-         msgRec2 = (Message)msgs.get(1);
-         assertTrue(msgRec1 == msg7);
-         assertTrue(msgRec2 == msg8);
-         
-         msgs = queue2.browse();
-         assertNotNull(msgs);
-         assertEquals(2, msgs.size());
-         msgRec1 = (Message)msgs.get(0);
-         msgRec2 = (Message)msgs.get(1);
-         assertTrue(msgRec1 == msg7);
-         assertTrue(msgRec2 == msg8);        
-      }
-      finally
-      {
-         if (exchange != null)
-         {
-            exchange.stop();
-         }
-      }
-   }
-   
-   protected Exchange createExchange() throws Exception
-   {
-      TopicExchange exchange = new TopicExchange(sc.getDataSource(), sc.getTransactionManager());      
-      
-      exchange.start();      
-      
-      ((TopicExchange)exchange).injectAttributes("Topic", "node1", ms, im, pool, tr);
-      
-      return exchange;
-   }
-
-   // Private -------------------------------------------------------
-
-   // Inner classes -------------------------------------------------
-
-}
-
-
-

Deleted: trunk/tests/src/org/jboss/test/messaging/core/plugin/base/ExchangeTestBase.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/plugin/base/ExchangeTestBase.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/core/plugin/base/ExchangeTestBase.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -1,456 +0,0 @@
-/*
-  * 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.test.messaging.core.plugin.base;
-
-import java.util.List;
-
-import org.jboss.jms.selector.Selector;
-import org.jboss.jms.server.QueuedExecutorPool;
-import org.jboss.messaging.core.Filter;
-import org.jboss.messaging.core.Message;
-import org.jboss.messaging.core.local.MessageQueue;
-import org.jboss.messaging.core.plugin.IdManager;
-import org.jboss.messaging.core.plugin.JDBCPersistenceManager;
-import org.jboss.messaging.core.plugin.SimpleMessageStore;
-import org.jboss.messaging.core.plugin.contract.Exchange;
-import org.jboss.messaging.core.plugin.contract.MessageStore;
-import org.jboss.messaging.core.plugin.contract.PersistenceManager;
-import org.jboss.messaging.core.plugin.exchange.Binding;
-import org.jboss.messaging.core.tx.Transaction;
-import org.jboss.messaging.core.tx.TransactionRepository;
-import org.jboss.test.messaging.MessagingTestCase;
-import org.jboss.test.messaging.core.SimpleReceiver;
-import org.jboss.test.messaging.tools.ServerManagement;
-import org.jboss.test.messaging.tools.jmx.ServiceContainer;
-
-/**
- * 
- * A ExchangeTestBase
-
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision: 1.1 $</tt>
- *
- * $Id$
- *
- */
-public abstract class ExchangeTestBase extends MessagingTestCase
-{
-   // Constants -----------------------------------------------------
-
-   // Static --------------------------------------------------------
-   
-   // Attributes ----------------------------------------------------
-
-   protected ServiceContainer sc;
-
-   protected PersistenceManager pm;
-      
-   protected MessageStore ms;
-   
-   protected IdManager im;
-   
-   protected TransactionRepository tr;
-   
-   protected QueuedExecutorPool pool;
-   
-   // Constructors --------------------------------------------------
-
-   public ExchangeTestBase(String name)
-   {
-      super(name);
-   }
-
-   // Public --------------------------------------------------------
-
-   public void setUp() throws Exception
-   {
-      super.setUp();
-
-      sc = new ServiceContainer("all");
-      
-      sc.start();                
-      
-      pm = new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager());
-      
-      pm.start();
-      
-      ms = new SimpleMessageStore();
-      
-      im = new IdManager("CHANNEL_ID", 10, pm);
-      
-      tr = new TransactionRepository();
-      
-      tr.injectAttributes(pm, new IdManager("TRANSACTION_ID", 10, pm));
-      
-      pool = new QueuedExecutorPool(10);
-            
-      log.debug("setup done");
-   }
-
-   public void tearDown() throws Exception
-   {      
-      if (!ServerManagement.isRemote())
-      {
-         sc.stop();
-         sc = null;
-      }
-      pm.stop();
-      
-      super.tearDown();
-   }
-   
-   // Public --------------------------------------------------------
-   
-   
-   public final void testBind() throws Throwable
-   {
-      Exchange exchange1 = null;
-      
-      Exchange exchange2 = null;
-      
-      Exchange exchange3 = null;
-      
-      try
-      {             
-         exchange1 = createExchange();
-         
-         //Bind one durable
-         
-         Filter filter1 = new Selector("x = 'cheese'");
-         Filter filter2 = new Selector("y = 'bread'");
-         
-         Binding binding1 =
-            exchange1.bindQueue("durableQueue", "condition1", filter1, true, true, ms, pm, 2000, 100, 100);
-         
-         //Binding twice with the same name should fail      
-         try
-         {
-            Binding bindFail = exchange1.bindQueue("durableQueue", "condition1", filter1, true, true, ms, pm, 2000, 100, 100);
-            fail();
-         }
-         catch (IllegalArgumentException e)
-         {
-            //Ok
-         }
-               
-         //Bind one non durable
-         Binding binding2 =
-            exchange1.bindQueue("nonDurableQueue", "condition2", filter2, true, false, ms, pm, 2000, 100, 100);
-         
-         //Check they're there
-         
-         Binding binding3 = exchange1.getBindingForName("durableQueue");
-         assertNotNull(binding3);
-         assertTrue(binding1 == binding3);
-         assertEquivalent(binding1, binding3);
-         assertNotNull(binding3.getQueue());
-         assertEquals(true, binding3.getQueue().isRecoverable());
-         
-         
-         Binding binding4 = exchange1.getBindingForName("nonDurableQueue");
-         assertNotNull(binding4);
-         assertTrue(binding2 == binding4);
-         assertEquivalent(binding2, binding4);
-         assertNotNull(binding4.getQueue());
-         assertEquals(false, binding4.getQueue().isRecoverable());
-         
-         exchange1.stop();
-         
-         //Throw away the exchange and create another
-         exchange2 = createExchange();
-         
-         //Only one binding should be there
-         Binding binding5 = exchange2.getBindingForName("durableQueue");
-         assertNotNull(binding5);
-         assertEquivalent(binding1, binding5);
-         //Should be unloaded
-         assertNull(binding5.getQueue());
-         
-         Binding binding6 = exchange2.getBindingForName("nonDurableQueue");
-         assertNull(binding6);
-         
-         //ReLoad the durable queue - or we won't be able to unbind it
-         exchange2.reloadQueues("condition1", ms, pm, 2000, 100, 100);
-         
-         //Unbind the binding
-         Binding binding7 = exchange2.unbindQueue("durableQueue");
-         assertNotNull(binding7);
-         assertEquivalent(binding1, binding7);
-         
-         //Make sure no longer there
-         Binding binding8 = exchange2.getBindingForName("durableQueue");
-         assertNull(binding8);
-         
-         exchange2.stop();
-         
-         //Throw away exchange and start another
-         exchange3 = createExchange();
-         
-         //Make sure not there
-         Binding binding9 = exchange3.getBindingForName("durableQueue");
-         assertNull(binding9);
-         
-         exchange3.stop();
-      }
-      finally
-      {
-         if (exchange1 != null)
-         {
-            exchange1.stop();
-         }
-         
-         if (exchange2 != null)
-         {
-            exchange2.stop();
-         }
-         
-         if (exchange3 != null)
-         {
-            exchange2.stop();
-         }
-      }
-            
-   }
-   
-   public final void testListBindings() throws Throwable
-   {
-      Exchange exchange = null;
-      
-      try
-      {      
-         exchange = createExchange();
-         
-         Binding binding1 =
-            exchange.bindQueue("queue1", "condition1", null, true, false, ms, pm, 2000, 100, 100);
-         Binding binding2 =
-            exchange.bindQueue("queue2", "condition1", null, true, false, ms, pm, 2000, 100, 100);
-         Binding binding3 =
-            exchange.bindQueue("queue3", "condition1", null, true, false, ms, pm, 2000, 100, 100);
-         Binding binding4 =
-            exchange.bindQueue("queue4", "condition1", null, true, false, ms, pm, 2000, 100, 100);
-         Binding binding5 =
-            exchange.bindQueue("queue5", "condition2", null, true, false, ms, pm, 2000, 100, 100);
-         Binding binding6 =
-            exchange.bindQueue("queue6", "condition2", null, true, false, ms, pm, 2000, 100, 100);
-         Binding binding7 =
-            exchange.bindQueue("queue7", "condition2", null, true, false, ms, pm, 2000, 100, 100);
-         Binding binding8 =
-            exchange.bindQueue("queue8", "condition2", null, true, false, ms, pm, 2000, 100, 100);
-         
-         List bindings = exchange.listBindingsForWildcard("dummy");
-         assertNotNull(bindings);
-         assertTrue(bindings.isEmpty());
-         
-         //We don't match on substrings
-         bindings = exchange.listBindingsForWildcard("condition123");
-         assertNotNull(bindings);
-         assertTrue(bindings.isEmpty());
-         
-         //We don't currently support hierarchies
-         bindings = exchange.listBindingsForWildcard("condition1.subcondition");
-         assertNotNull(bindings);
-         assertTrue(bindings.isEmpty());
-         
-         //We currently just do an exact match
-         bindings = exchange.listBindingsForWildcard("condition1");
-         assertNotNull(bindings);
-         assertEquals(4, bindings.size());
-         
-         assertEquivalent((Binding)bindings.get(0), binding1);
-         assertEquivalent((Binding)bindings.get(1), binding2);
-         assertEquivalent((Binding)bindings.get(2), binding3);
-         assertEquivalent((Binding)bindings.get(3), binding4);
-         
-         bindings = exchange.listBindingsForWildcard("condition2");
-         assertNotNull(bindings);
-         assertEquals(4, bindings.size());
-         
-         assertEquivalent((Binding)bindings.get(0), binding5);
-         assertEquivalent((Binding)bindings.get(1), binding6);
-         assertEquivalent((Binding)bindings.get(2), binding7);
-         assertEquivalent((Binding)bindings.get(3), binding8);
-      }
-      finally
-      {
-         if (exchange != null)
-         {
-            exchange.stop();
-         }
-      }
-         
-   }
-   
-   public final void testUnloadReload() throws Exception
-   {
-      Exchange exchange = null;
-      
-      try
-      {
-         exchange = createExchange();      
-      
-         Binding binding1 =
-            exchange.bindQueue("reloadqueue1", "condition3", null, true, true, ms, pm, 2000, 100, 100);
-         Binding binding2 =
-            exchange.bindQueue("reloadqueue2", "condition3", null, true, true, ms, pm, 2000, 100, 100);
-         Binding binding3 =
-            exchange.bindQueue("reloadqueue3", "condition3", null, true, true, ms, pm, 2000, 100, 100);
-         Binding binding4 =
-            exchange.bindQueue("reloadqueue4", "condition3", null, true, true, ms, pm, 2000, 100, 100);
-         Binding binding5 =
-            exchange.bindQueue("reloadqueue5", "condition4", null, true, true, ms, pm, 2000, 100, 100);
-         Binding binding6 =
-            exchange.bindQueue("reloadqueue6", "condition4", null, true, true, ms, pm, 2000, 100, 100);
-         Binding binding7 =
-            exchange.bindQueue("reloadqueue7", "condition4", null, true, true, ms, pm, 2000, 100, 100);
-         Binding binding8 =
-            exchange.bindQueue("reloadqueue8", "condition4", null, true, true, ms, pm, 2000, 100, 100);
-         
-         assertNotNull(binding1.getQueue());
-         assertTrue(binding1.isActive());      
-         assertNotNull(binding2.getQueue());
-         assertTrue(binding2.isActive());
-         assertNotNull(binding3.getQueue());
-         assertTrue(binding3.isActive());
-         assertNotNull(binding4.getQueue());
-         assertTrue(binding4.isActive());
-         
-         assertNotNull(binding5.getQueue());
-         assertTrue(binding5.isActive());
-         assertNotNull(binding6.getQueue());
-         assertTrue(binding6.isActive());
-         assertNotNull(binding7.getQueue());
-         assertTrue(binding7.isActive());
-         assertNotNull(binding8.getQueue());
-         assertTrue(binding8.isActive());
-         
-         exchange.unloadQueues("condition3");
-         
-         assertNull(binding1.getQueue());
-         assertFalse(binding1.isActive());      
-         assertNull(binding2.getQueue());
-         assertFalse(binding2.isActive());
-         assertNull(binding3.getQueue());
-         assertFalse(binding3.isActive());
-         assertNull(binding4.getQueue());
-         assertFalse(binding4.isActive());
-         
-         assertNotNull(binding5.getQueue());
-         assertTrue(binding5.isActive());
-         assertNotNull(binding6.getQueue());
-         assertTrue(binding6.isActive());
-         assertNotNull(binding7.getQueue());
-         assertTrue(binding7.isActive());
-         assertNotNull(binding8.getQueue());
-         assertTrue(binding8.isActive());
-         
-         exchange.unloadQueues("condition4");
-         
-         assertNull(binding1.getQueue());
-         assertFalse(binding1.isActive());      
-         assertNull(binding2.getQueue());
-         assertFalse(binding2.isActive());
-         assertNull(binding3.getQueue());
-         assertFalse(binding3.isActive());
-         assertNull(binding4.getQueue());
-         assertFalse(binding4.isActive());
-         
-         assertNull(binding5.getQueue());
-         assertFalse(binding5.isActive());
-         assertNull(binding6.getQueue());
-         assertFalse(binding6.isActive());
-         assertNull(binding7.getQueue());
-         assertFalse(binding7.isActive());
-         assertNull(binding8.getQueue());
-         assertFalse(binding8.isActive());
-         
-         exchange.reloadQueues("condition3", ms, pm, 2000, 100, 100);
-           
-         assertNotNull(binding1.getQueue());
-         assertTrue(binding1.isActive());      
-         assertNotNull(binding2.getQueue());
-         assertTrue(binding2.isActive());
-         assertNotNull(binding3.getQueue());
-         assertTrue(binding3.isActive());
-         assertNotNull(binding4.getQueue());
-         assertTrue(binding4.isActive());
-         
-         assertNull(binding5.getQueue());
-         assertFalse(binding5.isActive());
-         assertNull(binding6.getQueue());
-         assertFalse(binding6.isActive());
-         assertNull(binding7.getQueue());
-         assertFalse(binding7.isActive());
-         assertNull(binding8.getQueue());
-         assertFalse(binding8.isActive());
-         
-         exchange.reloadQueues("condition4", ms, pm, 2000, 100, 100);
-   
-         assertNotNull(binding1.getQueue());
-         assertTrue(binding1.isActive());      
-         assertNotNull(binding2.getQueue());
-         assertTrue(binding2.isActive());
-         assertNotNull(binding3.getQueue());
-         assertTrue(binding3.isActive());
-         assertNotNull(binding4.getQueue());
-         assertTrue(binding4.isActive());
-         
-         assertNotNull(binding5.getQueue());
-         assertTrue(binding5.isActive());
-         assertNotNull(binding6.getQueue());
-         assertTrue(binding6.isActive());
-         assertNotNull(binding7.getQueue());
-         assertTrue(binding7.isActive());
-         assertNotNull(binding8.getQueue());
-         assertTrue(binding8.isActive());
-      }
-      finally
-      {
-         if (exchange != null)
-         {
-            exchange.stop();
-         }
-      }
-   }
-   
-   // Package protected ---------------------------------------------
-
-   // Protected -----------------------------------------------------
-   
-   protected abstract Exchange createExchange() throws Exception;
-   
-   protected void assertEquivalent(Binding binding1, Binding binding2)
-   {
-      assertEquals(binding1.getNodeId(), binding2.getNodeId());
-      assertEquals(binding1.getQueueName(), binding2.getQueueName());      
-      assertEquals(binding1.getSelector(), binding2.getSelector());
-      assertEquals(binding1.getChannelId(), binding2.getChannelId());
-      assertEquals(binding1.isDurable(), binding2.isDurable());
-      assertEquals(binding1.isNoLocal(), binding2.isNoLocal());
-   }
-   
-
-   // Private -------------------------------------------------------
-
-   // Inner classes -------------------------------------------------
-   
-}
-

Modified: trunk/tests/src/org/jboss/test/messaging/jms/AcknowledgementTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/AcknowledgementTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/jms/AcknowledgementTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -272,25 +272,31 @@
       final int NUM_MESSAGES = 20;
 
       //Send some messages
+      log.info("********* SENDING MSGS");
       for (int i = 0; i < NUM_MESSAGES; i++)
       {
          Message m = producerSess.createMessage();
          producer.send(m);
       }
+      log.info("*********** SENT MSGSSGS");
       
       assertRemainingMessages(0);
       
       producerSess.rollback();
       
       //Send some messages
+      log.info("********* SENDING MOREMSGS");
       for (int i = 0; i < NUM_MESSAGES; i++)
       {
          Message m = producerSess.createMessage();
          producer.send(m);
       }
+      log.info("********* SENT MORE MSGS");
       assertRemainingMessages(0);
       
+      log.info("COMMITTING");
       producerSess.commit();
+      log.info("COMMITTED");
       
       assertRemainingMessages(NUM_MESSAGES);
 

Modified: trunk/tests/src/org/jboss/test/messaging/jms/persistence/MessagePersistenceManagerTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/persistence/MessagePersistenceManagerTest.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/jms/persistence/MessagePersistenceManagerTest.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -59,24 +59,25 @@
       super.setUp();              
    }
    
-   protected void doSetup(boolean batch) throws Throwable
+   protected void doSetup(boolean batch, int maxParams) throws Throwable
    {
-      super.doSetup(batch);
+      super.doSetup(batch, maxParams);
    }
 
    public void tearDown() throws Exception
    {
       super.tearDown();
    }
+       
+   protected JDBCPersistenceManager createPM(boolean batch, int maxParams) throws Throwable
+   {      
+      JDBCPersistenceManager p =
+         new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager(), null,
+                                    true, batch, true, maxParams);      
+      p.start();
+      return p;
+   }
    
-   protected JDBCPersistenceManager createPM() throws Exception
-   {           
-      JDBCPersistenceManager pm = new JDBCPersistenceManager(sc.getDataSource(), sc.getTransactionManager());
-      
-      pm.start();                 
-                   
-      return pm;     
-   }
   
    protected void checkEquivalent(Message m1, Message m2) throws Throwable
    {

Modified: trunk/tests/src/org/jboss/test/messaging/jms/server/destination/base/DestinationManagementTestBase.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/server/destination/base/DestinationManagementTestBase.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/jms/server/destination/base/DestinationManagementTestBase.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -33,6 +33,7 @@
 import org.jboss.jms.destination.JBossDestination;
 import org.jboss.jms.destination.JBossQueue;
 import org.jboss.jms.destination.JBossTopic;
+import org.jboss.jms.server.destination.ManagedDestination;
 import org.jboss.jms.util.XMLUtil;
 import org.jboss.test.messaging.MessagingTestCase;
 import org.jboss.test.messaging.tools.ServerManagement;
@@ -504,11 +505,11 @@
          jbd2 = new JBossTopic("PageableAttributes");
       }
       
-      jbd2 = ServerManagement.getDestinationManager().getDestination(jbd2);
+      ManagedDestination mDest = ServerManagement.getDestinationManager().getDestination(jbd2.getName(), jbd2.isQueue());
        
-      assertEquals(fullSize, jbd2.getFullSize());
-      assertEquals(pageSize, jbd2.getPageSize());
-      assertEquals(downCacheSize, jbd2.getDownCacheSize());
+      assertEquals(fullSize, mDest.getFullSize());
+      assertEquals(pageSize, mDest.getPageSize());
+      assertEquals(downCacheSize, mDest.getDownCacheSize());
       
       // Try to change the values when destination lives, no effect
       ServerManagement.setAttribute(destObjectName, "FullSize", "1111");
@@ -530,12 +531,12 @@
       // Start the service again and test the value from core destination
       ServerManagement.invoke(destObjectName, "start", null, null);
       
-      jbd2 = ServerManagement.getDestinationManager().getDestination(jbd2);
+      mDest = ServerManagement.getDestinationManager().getDestination(jbd2.getName(), jbd2.isQueue());
       
       // Must get the new core destination!      
-      assertEquals(751119, jbd2.getFullSize());
-      assertEquals(20019, jbd2.getPageSize());
-      assertEquals(9999, jbd2.getDownCacheSize());
+      assertEquals(751119, mDest.getFullSize());
+      assertEquals(20019, mDest.getPageSize());
+      assertEquals(9999, mDest.getDownCacheSize());
 
       undeployDestination("PageableAttributes");
    }

Modified: trunk/tests/src/org/jboss/test/messaging/tools/jmx/rmi/LocalTestServer.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/tools/jmx/rmi/LocalTestServer.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/tools/jmx/rmi/LocalTestServer.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -37,9 +37,9 @@
 import org.jboss.jms.server.ServerPeer;
 import org.jboss.jms.util.XMLUtil;
 import org.jboss.logging.Logger;
-import org.jboss.messaging.core.plugin.contract.Exchange;
 import org.jboss.messaging.core.plugin.contract.MessageStore;
 import org.jboss.messaging.core.plugin.contract.PersistenceManager;
+import org.jboss.messaging.core.plugin.contract.PostOffice;
 import org.jboss.remoting.ServerInvocationHandler;
 import org.jboss.test.messaging.tools.ServerManagement;
 import org.jboss.test.messaging.tools.jboss.MBeanConfigurationElement;
@@ -70,8 +70,8 @@
 
    // service dependencies   
    private ObjectName persistenceManagerObjectName;
-   private ObjectName directExchangeObjectName;
-   private ObjectName topicExchangeObjectName;
+   private ObjectName queuePostOfficeObjectName;
+   private ObjectName topicPostOfficeObjectName;
    private ObjectName jmsUserManagerObjectName;
    private ObjectName shutdownLoggerObjectName;
 
@@ -248,30 +248,21 @@
       ServiceDeploymentDescriptor pdd = new ServiceDeploymentDescriptor(persistenceConfigFileURL);
       ServiceDeploymentDescriptor cfdd = new ServiceDeploymentDescriptor(connFactoryConfigFileURL);
 
+      log.info("^^^^^^^^^^ STARTING PM");
       MBeanConfigurationElement persistenceManagerConfig =
          (MBeanConfigurationElement)pdd.query("service", "PersistenceManager").iterator().next();
       persistenceManagerObjectName = sc.registerAndConfigureService(persistenceManagerConfig);
       sc.invoke(persistenceManagerObjectName, "create", new Object[0], new String[0]);
       sc.invoke(persistenceManagerObjectName, "start", new Object[0], new String[0]);    
-      
-      MBeanConfigurationElement directExchangeConfig =
-         (MBeanConfigurationElement)pdd.query("service", "DirectExchange").iterator().next();
-      directExchangeObjectName = sc.registerAndConfigureService(directExchangeConfig);
-      sc.invoke(directExchangeObjectName, "create", new Object[0], new String[0]);
-      sc.invoke(directExchangeObjectName, "start", new Object[0], new String[0]);
-      
-      MBeanConfigurationElement topicExchangeConfig =
-         (MBeanConfigurationElement)pdd.query("service", "TopicExchange").iterator().next();
-      topicExchangeObjectName = sc.registerAndConfigureService(topicExchangeConfig);
-      sc.invoke(topicExchangeObjectName, "create", new Object[0], new String[0]);
-      sc.invoke(topicExchangeObjectName, "start", new Object[0], new String[0]);
-      
+           
+      log.info("^^^^^^^^^^ STARTING JMS USER MANAGER");
       MBeanConfigurationElement jmsUserManagerConfig =
          (MBeanConfigurationElement)pdd.query("service", "JMSUserManager").iterator().next();
       jmsUserManagerObjectName = sc.registerAndConfigureService(jmsUserManagerConfig);
       sc.invoke(jmsUserManagerObjectName, "create", new Object[0], new String[0]);
       sc.invoke(jmsUserManagerObjectName, "start", new Object[0], new String[0]);  
       
+      log.info("^^^^^^^^^^ STARTING SHUTDOWN LOGGER");
       MBeanConfigurationElement shutdownLoggerConfig =
          (MBeanConfigurationElement)pdd.query("service", "ShutdownLogger").iterator().next();
       shutdownLoggerObjectName = sc.registerAndConfigureService(shutdownLoggerConfig);
@@ -304,9 +295,24 @@
 
       log.debug("starting JMS server");
 
+      log.info("^^^^^^^^^^ STARTING SERVERPEER");
       sc.invoke(serverPeerObjectName, "create", new Object[0], new String[0]);
       sc.invoke(serverPeerObjectName, "start", new Object[0], new String[0]);
-
+      
+      log.info("^^^^^^^^^^ STARTING QUEUE POST OFFICE");
+      MBeanConfigurationElement queuePostOfficeConfig =
+         (MBeanConfigurationElement)pdd.query("service", "QueuePostOffice").iterator().next();
+      queuePostOfficeObjectName = sc.registerAndConfigureService(queuePostOfficeConfig);
+      sc.invoke(queuePostOfficeObjectName, "create", new Object[0], new String[0]);
+      sc.invoke(queuePostOfficeObjectName, "start", new Object[0], new String[0]);
+      
+      log.info("^^^^^^^^^^ STARTING TOPIC POST OFFICE");
+      MBeanConfigurationElement topicPostOfficeConfig =
+         (MBeanConfigurationElement)pdd.query("service", "TopicPostOffice").iterator().next();
+      topicPostOfficeObjectName = sc.registerAndConfigureService(topicPostOfficeConfig);
+      sc.invoke(topicPostOfficeObjectName, "create", new Object[0], new String[0]);
+      sc.invoke(topicPostOfficeObjectName, "start", new Object[0], new String[0]);
+ 
       log.debug("deploying connection factories");
 
       List connFactoryElements = cfdd.query("service", "ConnectionFactory");
@@ -387,13 +393,13 @@
       sc.invoke(jmsUserManagerObjectName, "destroy", new Object[0], new String[0]);
       sc.unregisterService(jmsUserManagerObjectName);
 
-      sc.invoke(directExchangeObjectName, "stop", new Object[0], new String[0]);
-      sc.invoke(directExchangeObjectName, "destroy", new Object[0], new String[0]);
-      sc.unregisterService(directExchangeObjectName);
+      sc.invoke(queuePostOfficeObjectName, "stop", new Object[0], new String[0]);
+      sc.invoke(queuePostOfficeObjectName, "destroy", new Object[0], new String[0]);
+      sc.unregisterService(queuePostOfficeObjectName);
       
-      sc.invoke(topicExchangeObjectName, "stop", new Object[0], new String[0]);
-      sc.invoke(topicExchangeObjectName, "destroy", new Object[0], new String[0]);
-      sc.unregisterService(topicExchangeObjectName);
+      sc.invoke(topicPostOfficeObjectName, "stop", new Object[0], new String[0]);
+      sc.invoke(topicPostOfficeObjectName, "destroy", new Object[0], new String[0]);
+      sc.unregisterService(topicPostOfficeObjectName);
 
       sc.invoke(persistenceManagerObjectName, "stop", new Object[0], new String[0]);
       sc.invoke(persistenceManagerObjectName, "destroy", new Object[0], new String[0]);
@@ -420,12 +426,12 @@
 
    public ObjectName getDirectExchangeObjectName()
    {
-      return directExchangeObjectName;
+      return queuePostOfficeObjectName;
    }
    
    public ObjectName getTopicExchangeObjectName()
    {
-      return topicExchangeObjectName;
+      return topicPostOfficeObjectName;
    }
 
    public Set getConnectorSubsystems() throws Exception
@@ -471,19 +477,19 @@
    public PersistenceManager getPersistenceManager() throws Exception
    {
       ServerPeer serverPeer = (ServerPeer)sc.getAttribute(serverPeerObjectName, "Instance");
-      return serverPeer.getPersistenceManagerDelegate();
+      return serverPeer.getPersistenceManagerInstance();
    }
    
-   public Exchange getDirectExchange() throws Exception
+   public PostOffice getDirectExchange() throws Exception
    {
-      return (Exchange)sc.
-         getAttribute(directExchangeObjectName, "Instance");
+      return (PostOffice)sc.
+         getAttribute(queuePostOfficeObjectName, "Instance");
    }
    
-   public Exchange getTopicExchange() throws Exception
+   public PostOffice getTopicExchange() throws Exception
    {
-      return (Exchange)sc.
-         getAttribute(topicExchangeObjectName, "Instance");
+      return (PostOffice)sc.
+         getAttribute(topicPostOfficeObjectName, "Instance");
    }
 
    
@@ -535,7 +541,7 @@
    public void deployDestination(boolean isQueue, String name, String jndiName) throws Exception
    {
       String config =
-         "<mbean code=\"org.jboss.jms.server.destination." + (isQueue ? "Queue" : "Topic") + "\"" +
+         "<mbean code=\"org.jboss.jms.server.destination." + (isQueue ? "QueueService" : "TopicService") + "\"" +
          "       name=\"jboss.messaging.destination:service=" + (isQueue ? "Queue" : "Topic") + ",name=" + name + "\"" +
          "       xmbean-dd=\"xmdesc/" + (isQueue ? "Queue" : "Topic" ) + "-xmbean.xml\">" +
          (jndiName != null ? "    <attribute name=\"JNDIName\">" + jndiName + "</attribute>" : "") +

Modified: trunk/tests/src/org/jboss/test/messaging/tools/jmx/rmi/RMITestServer.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/tools/jmx/rmi/RMITestServer.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/tools/jmx/rmi/RMITestServer.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -32,9 +32,9 @@
 import org.jboss.jms.server.DestinationManager;
 import org.jboss.jms.server.ServerPeer;
 import org.jboss.logging.Logger;
-import org.jboss.messaging.core.plugin.contract.Exchange;
 import org.jboss.messaging.core.plugin.contract.MessageStore;
 import org.jboss.messaging.core.plugin.contract.PersistenceManager;
+import org.jboss.messaging.core.plugin.contract.PostOffice;
 import org.jboss.remoting.ServerInvocationHandler;
 
 /**
@@ -247,12 +247,12 @@
       return server.getPersistenceManager();
    }
    
-   public Exchange getDirectExchange() throws Exception
+   public PostOffice getDirectExchange() throws Exception
    {
       return server.getDirectExchange();
    }
    
-   public Exchange getTopicExchange() throws Exception
+   public PostOffice getTopicExchange() throws Exception
    {
       return server.getTopicExchange();
    }

Modified: trunk/tests/src/org/jboss/test/messaging/tools/jmx/rmi/RemoteTestServer.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/tools/jmx/rmi/RemoteTestServer.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/tools/jmx/rmi/RemoteTestServer.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -22,9 +22,9 @@
 package org.jboss.test.messaging.tools.jmx.rmi;
 
 import org.jboss.jms.server.DestinationManager;
-import org.jboss.messaging.core.plugin.contract.Exchange;
 import org.jboss.messaging.core.plugin.contract.MessageStore;
 import org.jboss.messaging.core.plugin.contract.PersistenceManager;
+import org.jboss.messaging.core.plugin.contract.PostOffice;
 
 /**
  *
@@ -74,7 +74,7 @@
    /**
     * Only for in-VM use!
     */
-   public Exchange getDirectExchange() throws Exception
+   public PostOffice getDirectExchange() throws Exception
    {
       throw new UnsupportedOperationException("This method shouldn't be invoked on a remote server");      
    }
@@ -82,7 +82,7 @@
    /**
     * Only for in-VM use!
     */
-   public Exchange getTopicExchange() throws Exception
+   public PostOffice getTopicExchange() throws Exception
    {
       throw new UnsupportedOperationException("This method shouldn't be invoked on a remote server");      
    }

Modified: trunk/tests/src/org/jboss/test/messaging/tools/jmx/rmi/Server.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/tools/jmx/rmi/Server.java	2006-09-07 23:18:18 UTC (rev 1269)
+++ trunk/tests/src/org/jboss/test/messaging/tools/jmx/rmi/Server.java	2006-09-09 11:48:48 UTC (rev 1270)
@@ -29,9 +29,9 @@
 
 import org.jboss.jms.server.DestinationManager;
 import org.jboss.jms.server.ServerPeer;
-import org.jboss.messaging.core.plugin.contract.Exchange;
 import org.jboss.messaging.core.plugin.contract.MessageStore;
 import org.jboss.messaging.core.plugin.contract.PersistenceManager;
+import org.jboss.messaging.core.plugin.contract.PostOffice;
 import org.jboss.remoting.ServerInvocationHandler;
 
 /**
@@ -121,9 +121,9 @@
    /**
     * Only for in-VM use!
     */
-   Exchange getDirectExchange() throws Exception;
+   PostOffice getDirectExchange() throws Exception;
    
-   Exchange getTopicExchange() throws Exception;
+   PostOffice getTopicExchange() throws Exception;
 
    /**
     * Only for in-VM use




More information about the jboss-cvs-commits mailing list