[Jboss-cvs] JBoss Messaging SVN: r1297 - in trunk: src/main/org/jboss/jms/selector src/main/org/jboss/jms/server/destination src/main/org/jboss/jms/server/endpoint src/main/org/jboss/messaging/core src/main/org/jboss/messaging/core/local 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 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/postoffice tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster tests/src/org/jboss/test/messaging/jms tests/src/org/jboss/test/messaging/tools/jmx

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Sun Sep 17 11:48:35 EDT 2006


Author: timfox
Date: 2006-09-17 11:47:58 -0400 (Sun, 17 Sep 2006)
New Revision: 1297

Added:
   trunk/src/main/org/jboss/jms/selector/SelectorFactory.java
   trunk/src/main/org/jboss/messaging/core/FilterFactory.java
   trunk/src/main/org/jboss/messaging/core/PagingChannelSupport.java
   trunk/src/main/org/jboss/messaging/core/Queue.java
   trunk/src/main/org/jboss/messaging/core/local/PagingFilteredQueue.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/Bindings.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/BindingsImpl.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/BindingInfo.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusterRouter.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredBindings.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredBindingsImpl.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/LocalClusteredQueue.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/RemoteQueueStub.java
   trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/
   trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/SimpleFilter.java
   trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/SimpleFilterFactory.java
   trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/SimplePostOfficeTest.java
   trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/
   trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/BasicRedistributionPolicyTest.java
   trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/ClusteredPostOfficeTest.java
   trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/JGroupsUtil.java
   trunk/tests/src/org/jboss/test/messaging/jms/DurableSubscriptionTest.java
Removed:
   trunk/src/main/org/jboss/messaging/core/PagingChannel.java
   trunk/src/main/org/jboss/messaging/core/local/Queue.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/ConditionBindings.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredBinding.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredBindingImpl.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/FavourLocalRoutingPolicy.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/RoutingPolicy.java
   trunk/tests/src/org/jboss/test/messaging/core/plugin/ClusteredPostOfficeTest.java
   trunk/tests/src/org/jboss/test/messaging/core/plugin/JGroupsUtil.java
   trunk/tests/src/org/jboss/test/messaging/core/plugin/SimplePostOfficeTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/DurableSubscriberTest.java
Modified:
   trunk/src/main/org/jboss/jms/server/destination/DestinationServiceSupport.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/endpoint/ServerBrowserEndpoint.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/messaging/core/Channel.java
   trunk/src/main/org/jboss/messaging/core/ChannelSupport.java
   trunk/src/main/org/jboss/messaging/core/plugin/ClusteredPostOfficeService.java
   trunk/src/main/org/jboss/messaging/core/plugin/SimplePostOfficeService.java
   trunk/src/main/org/jboss/messaging/core/plugin/contract/ClusteredPostOffice.java
   trunk/src/main/org/jboss/messaging/core/plugin/contract/PostOffice.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/Binding.java
   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/BasicRedistributionPolicy.java
   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/ClusteredPostOfficeImpl.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredQueue.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/QueueStats.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/RedistributionOrder.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/SharedState.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/RecoverableQueueTest.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/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/tools/jmx/ServiceContainer.java
Log:
Another interim clustering commit



Added: trunk/src/main/org/jboss/jms/selector/SelectorFactory.java
===================================================================
--- trunk/src/main/org/jboss/jms/selector/SelectorFactory.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/jms/selector/SelectorFactory.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -0,0 +1,43 @@
+/*
+ * 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.selector;
+
+import org.jboss.messaging.core.Filter;
+import org.jboss.messaging.core.FilterFactory;
+
+/**
+ * A SelectorFactory
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class SelectorFactory implements FilterFactory
+{
+   public Filter createFilter(String filterString) throws Exception
+   {
+      return filterString == null ? null : new Selector(filterString);
+   }
+
+}

Modified: trunk/src/main/org/jboss/jms/server/destination/DestinationServiceSupport.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/DestinationServiceSupport.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/jms/server/destination/DestinationServiceSupport.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -62,6 +62,8 @@
    
    protected IdManager idm;
    
+   protected String nodeId;
+   
    private boolean createdProgrammatically;
    
    // Constructors --------------------------------------------------
@@ -97,6 +99,8 @@
          
          idm = serverPeer.getChannelIdManager();
          
+         nodeId = serverPeer.getServerPeerID();
+         
          String name = null;
                   
          if (serviceName != null)

Modified: trunk/src/main/org/jboss/jms/server/destination/ManagedQueue.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/ManagedQueue.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/jms/server/destination/ManagedQueue.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -27,6 +27,7 @@
 import javax.jms.JMSException;
 
 import org.jboss.jms.selector.Selector;
+import org.jboss.messaging.core.Queue;
 import org.jboss.messaging.core.plugin.postoffice.Binding;
 
 /**
@@ -53,28 +54,28 @@
 
    public int getMessageCount() throws Exception
    {
-      Binding binding = (Binding)postOffice.listBindingsForCondition(name).get(0);
+      Binding binding = (Binding)postOffice.listBindingsForCondition(name).iterator().next();
       
       if (binding == null)
       {
          throw new IllegalStateException("Cannot find binding for queue:" + name);
       }
       
-      org.jboss.messaging.core.local.Queue queue = binding.getQueue();
+      Queue queue = binding.getQueue();
 
       return queue.messageCount();
    }
    
    public void removeAllMessages() throws Throwable
    {
-      Binding binding = (Binding)postOffice.listBindingsForCondition(name).get(0);
+      Binding binding = (Binding)postOffice.listBindingsForCondition(name).iterator().next();
       
       if (binding == null)
       {
          throw new IllegalStateException("Cannot find binding for queue:" + name);
       }
       
-      org.jboss.messaging.core.local.Queue queue = binding.getQueue();
+      Queue queue = binding.getQueue();
 
       queue.removeAllReferences();
    }
@@ -90,14 +91,14 @@
          }
       }
       
-      Binding binding = (Binding)postOffice.listBindingsForCondition(name).get(0);
+      Binding binding = (Binding)postOffice.listBindingsForCondition(name).iterator().next();
       
       if (binding == null)
       {
          throw new IllegalStateException("Cannot find binding for queue:" + name);
       }
       
-      org.jboss.messaging.core.local.Queue queue = binding.getQueue();
+      Queue queue = binding.getQueue();
 
       try 
       {

Modified: trunk/src/main/org/jboss/jms/server/destination/ManagedTopic.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/ManagedTopic.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/jms/server/destination/ManagedTopic.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -22,6 +22,7 @@
 package org.jboss.jms.server.destination;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 
@@ -29,7 +30,7 @@
 
 import org.jboss.jms.selector.Selector;
 import org.jboss.jms.util.MessageQueueNameHelper;
-import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.Queue;
 import org.jboss.messaging.core.plugin.postoffice.Binding;
 
 /**
@@ -56,7 +57,7 @@
 
    public void removeAllMessages() throws Throwable
    {
-      List subs = postOffice.listBindingsForCondition(name);
+      Collection subs = postOffice.listBindingsForCondition(name);
       
       //XXX How to lock down all subscriptions?
       Iterator iter = subs.iterator();
@@ -70,14 +71,14 @@
    
    public int subscriptionCount() throws Exception
    {
-      List subs = postOffice.listBindingsForCondition(name);
+      Collection subs = postOffice.listBindingsForCondition(name);
       
       return subs.size();         
    }
    
    public int subscriptionCount(boolean durable) throws Exception
    {
-      List subs = postOffice.listBindingsForCondition(name);
+      Collection subs = postOffice.listBindingsForCondition(name);
       
       Iterator iter = subs.iterator();
       
@@ -87,7 +88,7 @@
       {
          Binding binding = (Binding)iter.next();
          
-         if ((binding.isDurable() && durable) || (!binding.isDurable() && !durable))
+         if ((binding.getQueue().isRecoverable() && durable) || (!binding.getQueue().isRecoverable() && !durable))
          {
             count++;
          }
@@ -98,14 +99,14 @@
    
    public String listSubscriptionsAsText() throws Exception
    {
-      List subs = postOffice.listBindingsForCondition(name);
+      Collection subs = postOffice.listBindingsForCondition(name);
       
       return getSubscriptionsAsText(subs, true) + getSubscriptionsAsText(subs, false);
    }
    
    public String listSubscriptionsAsText(boolean durable) throws Exception
    {
-      List subs = postOffice.listBindingsForCondition(name);
+      Collection subs = postOffice.listBindingsForCondition(name);
       
       return getSubscriptionsAsText(subs, durable);
    }
@@ -113,7 +114,7 @@
    public List listMessagesDurableSub(String subName, String clientID, String selector)
       throws Exception
    {
-      List subs = postOffice.listBindingsForCondition(name);
+      Collection subs = postOffice.listBindingsForCondition(name);
       
       return getMessagesFromDurableSub(subs, subName, clientID, trimSelector(selector));
    }
@@ -121,7 +122,7 @@
    public List listMessagesNonDurableSub(long channelID, String selector)
       throws Exception
    {
-      List subs = postOffice.listBindingsForCondition(name);
+      Collection subs = postOffice.listBindingsForCondition(name);
       
       return getMessagesFromNonDurableSub(subs, channelID, trimSelector(selector));
    }
@@ -135,7 +136,7 @@
    
    
    
-   private String getSubscriptionsAsText(List bindings, boolean durable)
+   private String getSubscriptionsAsText(Collection bindings, boolean durable)
    {
       StringBuffer sb = new StringBuffer();
       Iterator iter = bindings.iterator();
@@ -143,14 +144,14 @@
       {
          Binding binding = (Binding)iter.next();
          
-         String filterString = binding.getFilter() != null ? binding.getFilter().getFilterString() : null;
+         String filterString = binding.getQueue().getFilter() != null ? binding.getQueue().getFilter().getFilterString() : null;
                   
-         if (durable && binding.isDurable())
+         if (durable && binding.getQueue().isRecoverable())
          {                      
-            MessageQueueNameHelper helper = MessageQueueNameHelper.createHelper(binding.getQueueName());
+            MessageQueueNameHelper helper = MessageQueueNameHelper.createHelper(binding.getQueue().getName());
             
             sb.append("Durable, subscriptionID=\"");
-            sb.append(binding.getChannelId());    
+            sb.append(binding.getQueue().getChannelID());    
             sb.append("\", name=\"");
             sb.append(helper.getSubName());
             sb.append("\", clientID=\"");
@@ -159,10 +160,10 @@
             sb.append(filterString);
             sb.append("\"\n");
          }
-         else if (!durable && !binding.isDurable())
+         else if (!durable && !binding.getQueue().isRecoverable())
          {            
             sb.append("Non-durable, subscriptionID=\"");
-            sb.append(binding.getChannelId());
+            sb.append(binding.getQueue().getChannelID());
             sb.append("\", selector=\"");
             sb.append(filterString);
             sb.append("\"\n");
@@ -178,10 +179,10 @@
       if (null == name)
          throw new IllegalArgumentException();
       // Must be durable
-      if (!binding.isDurable())
+      if (!binding.getQueue().isRecoverable())
          return false;
       
-      MessageQueueNameHelper helper = MessageQueueNameHelper.createHelper(binding.getQueueName());
+      MessageQueueNameHelper helper = MessageQueueNameHelper.createHelper(binding.getQueue().getName());
 
       // Subscription name check
       if (!name.equals(helper.getSubName()))
@@ -198,15 +199,15 @@
    private boolean matchNonDurableSubscription(long channelID, Binding binding)
    {
       // Must be non-durable
-      if (binding.isDurable())
+      if (binding.getQueue().isRecoverable())
          return false;
       // Channel ID must be the same
-      if (channelID != binding.getChannelId())
+      if (channelID != binding.getQueue().getChannelID())
          return false;
       return true;
    }
    
-   private List getMessagesFromDurableSub(List bindings, String name,
+   private List getMessagesFromDurableSub(Collection bindings, String name,
             String clientID, String selector) throws InvalidSelectorException
    {
       Iterator iter = bindings.iterator();
@@ -224,7 +225,7 @@
       return new ArrayList();
    }
    
-   private List getMessagesFromNonDurableSub(List bindings, long channelID, String selector) throws InvalidSelectorException
+   private List getMessagesFromNonDurableSub(Collection bindings, long channelID, String selector) throws InvalidSelectorException
    {
       Iterator iter = bindings.iterator();
       while (iter.hasNext())

Modified: trunk/src/main/org/jboss/jms/server/destination/QueueService.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/QueueService.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/jms/server/destination/QueueService.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -11,7 +11,10 @@
 
 import org.jboss.jms.util.ExceptionUtil;
 import org.jboss.jms.util.XMLUtil;
+import org.jboss.messaging.core.local.PagingFilteredQueue;
+import org.jboss.messaging.core.plugin.contract.ClusteredPostOffice;
 import org.jboss.messaging.core.plugin.postoffice.Binding;
+import org.jboss.messaging.core.plugin.postoffice.cluster.LocalClusteredQueue;
 
 import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
 
@@ -87,37 +90,38 @@
             
          Binding binding = postOffice.getBindingForQueueName(destination.getName());
          
-         QueuedExecutor executor = (QueuedExecutor)pool.get();
-         
          if (binding != null)
-         {
-            //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);
-               q.load();
-               binding.setQueue(q);
-               binding.activate();
-            }
+         {    
+            PagingFilteredQueue queue = (PagingFilteredQueue)binding.getQueue();
+            
+            //Activate it - this causes it's state to be loaded
+            queue.deactivate();
+            queue.activate(destination.getFullSize(), destination.getPageSize(), destination.getDownCacheSize());            
          }
          else
          {         
-            //Create a new queue            
+            QueuedExecutor executor = (QueuedExecutor)pool.get();
             
-            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);
+            //Create a new queue       
             
-            //Make a binding for this queue
-            postOffice.bindQueue(destination.getName(), destination.getName(), null, q);
+            PagingFilteredQueue queue;
+            
+            if (postOffice.isLocal())
+            {
+               queue = new PagingFilteredQueue(destination.getName(), idm.getId(), ms, pm, true, true,                        
+                                               executor, null,
+                                               destination.getFullSize(), destination.getPageSize(), destination.getDownCacheSize());
+               
+               postOffice.bindQueue(destination.getName(), queue);
+            }
+            else
+            {
+               queue = new LocalClusteredQueue(nodeId, destination.getName(), idm.getId(), ms, pm, true, true,                        
+                                               executor, null,
+                                               destination.getFullSize(), destination.getPageSize(), destination.getDownCacheSize());
+               
+               ((ClusteredPostOffice)postOffice).bindClusteredQueue(destination.getName(), (LocalClusteredQueue)queue);
+            }                        
          }
          
          //push security update to the server
@@ -148,12 +152,10 @@
          //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);
-         }
+         PagingFilteredQueue queue = (PagingFilteredQueue)binding.getQueue();
          
+         queue.deactivate();
+         
          started = false;
          
          log.info(this + " stopped");

Modified: trunk/src/main/org/jboss/jms/server/destination/TopicService.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/TopicService.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/jms/server/destination/TopicService.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -7,18 +7,17 @@
 package org.jboss.jms.server.destination;
 
 import java.util.ArrayList;
+import java.util.Collection;
 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.local.PagingFilteredQueue;
 import org.jboss.messaging.core.plugin.postoffice.Binding;
 
-import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
-
 /**
  * A deployable JBoss Messaging topic.
  *
@@ -66,27 +65,16 @@
          destination.setPostOffice(postOffice);
            
          // We deploy any queues corresponding to pre-existing durable subscriptions
-         List bindings = postOffice.listBindingsForCondition(destination.getName());
+         Collection 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);
-               q.load();
-               binding.setQueue(q);
-               binding.activate();
-            }
+            
+            PagingFilteredQueue queue = (PagingFilteredQueue)binding.getQueue();
+
+            queue.deactivate();
+            queue.activate(destination.getFullSize(), destination.getPageSize(), destination.getDownCacheSize());            
          }
 
          // push security update to the server
@@ -120,21 +108,21 @@
          //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());
+         Collection bindings = postOffice.listBindingsForCondition(destination.getName());
          
          Iterator iter = bindings.iterator();
          while (iter.hasNext())            
          {
             Binding binding = (Binding)iter.next();
             
-            binding.deactivate();
+            PagingFilteredQueue queue = (PagingFilteredQueue)binding.getQueue();
             
-            if (!binding.isDurable())
+            if (!queue.isRecoverable())
             {
-               binding.getQueue().removeAllReferences();
+               queue.removeAllReferences();
             }
-            
-            binding.setQueue(null);
+                        
+            queue.deactivate();
          }
           
          started = false;

Modified: trunk/src/main/org/jboss/jms/server/endpoint/ServerBrowserEndpoint.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/endpoint/ServerBrowserEndpoint.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/jms/server/endpoint/ServerBrowserEndpoint.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -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.Queue;
+import org.jboss.messaging.core.local.PagingFilteredQueue;
 
 /**
  * Concrete implementation of BrowserEndpoint.
@@ -66,7 +66,7 @@
    // Constructors --------------------------------------------------
 
    protected ServerBrowserEndpoint(ServerSessionEndpoint session, int id,
-                                   Queue destination, String messageSelector)
+                                   PagingFilteredQueue destination, String messageSelector)
       throws JMSException
    {     
       this.session = session;

Modified: trunk/src/main/org/jboss/jms/server/endpoint/ServerConsumerEndpoint.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/endpoint/ServerConsumerEndpoint.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/jms/server/endpoint/ServerConsumerEndpoint.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -49,7 +49,7 @@
 import org.jboss.messaging.core.Receiver;
 import org.jboss.messaging.core.Routable;
 import org.jboss.messaging.core.SimpleDelivery;
-import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.local.PagingFilteredQueue;
 import org.jboss.messaging.core.plugin.contract.PostOffice;
 import org.jboss.messaging.core.plugin.postoffice.Binding;
 import org.jboss.messaging.core.tx.Transaction;
@@ -86,7 +86,7 @@
 
    private int id;
 
-   private Queue messageQueue;
+   private PagingFilteredQueue messageQueue;
    
    private String queueName;
 
@@ -125,7 +125,7 @@
    
    // Constructors --------------------------------------------------
 
-   protected ServerConsumerEndpoint(int id, Queue messageQueue, String queueName,
+   protected ServerConsumerEndpoint(int id, PagingFilteredQueue messageQueue, String queueName,
                                     ServerSessionEndpoint sessionEndpoint,
                                     String selector, boolean noLocal, JBossDestination dest,
                                     int prefetchSize)
@@ -365,7 +365,7 @@
                   throw new IllegalStateException("Cannot find queue with name " + queueName);
                }
                
-               if (!binding.isDurable())
+               if (!binding.getQueue().isRecoverable())
                {                 
                   topicPostOffice.unbindQueue(queueName);
                }

Modified: trunk/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -21,6 +21,7 @@
   */
 package org.jboss.jms.server.endpoint;
 
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -54,12 +55,14 @@
 import org.jboss.jms.util.ExceptionUtil;
 import org.jboss.jms.util.MessageQueueNameHelper;
 import org.jboss.logging.Logger;
-import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.local.PagingFilteredQueue;
 import org.jboss.messaging.core.plugin.IdManager;
+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.contract.PostOffice;
 import org.jboss.messaging.core.plugin.postoffice.Binding;
+import org.jboss.messaging.core.plugin.postoffice.cluster.LocalClusteredQueue;
 import org.jboss.util.id.GUID;
 
 import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
@@ -101,6 +104,7 @@
    private QueuedExecutorPool pool;
    private PostOffice topicPostOffice;
    private PostOffice queuePostOffice;
+   private String nodeId;
    
    
    // Constructors --------------------------------------------------
@@ -121,6 +125,7 @@
       queuePostOffice = sp.getQueuePostOfficeInstance();
       idm = sp.getChannelIdManager();
       pool = sp.getQueuedExecutorPool();
+      nodeId = sp.getServerPeerID();
 
       consumers = new HashMap();
 		browsers = new HashMap();  
@@ -187,15 +192,15 @@
                      
                //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);
                
-               //Make a binding for this queue
-               binding = topicPostOffice.bindQueue(new GUID().toString(), jmsDestination.getName(), selector, q);               
+               PagingFilteredQueue q = 
+                  new PagingFilteredQueue(new GUID().toString(), idm.getId(), ms, pm, true, false,                          
+                                          executor, selector, mDest.getFullSize(),
+                                          mDest.getPageSize(),
+                                          mDest.getDownCacheSize());       
+               
+               //Make a binding for this queue - non durable subscriptins are always non clustered
+               binding = topicPostOffice.bindQueue(jmsDestination.getName(), q);               
             }
             else
             {
@@ -224,15 +229,27 @@
                   if (trace) { log.trace("creating new durable subscription on " + jmsDestination); }
                   
                   QueuedExecutor executor = (QueuedExecutor)pool.get();
-                  Queue q = 
-                     new Queue(idm.getId(), ms, pm, true, true,
-                              mDest.getFullSize(),
-                              mDest.getPageSize(),
-                              mDest.getDownCacheSize(),
-                              executor);
+                  PagingFilteredQueue q;
                   
-                  //Make a binding for this queue
-                  binding = topicPostOffice.bindQueue(name, jmsDestination.getName(), selector, q);               
+                  if (topicPostOffice.isLocal())
+                  {
+                     q = new PagingFilteredQueue(name, idm.getId(), ms, pm, true, true,                              
+                                                 executor, selector,
+                                                 mDest.getFullSize(),
+                                                 mDest.getPageSize(),
+                                                 mDest.getDownCacheSize());
+                     
+                     binding = topicPostOffice.bindQueue(jmsDestination.getName(), q);      
+                  }
+                  else
+                  {
+                     q = new LocalClusteredQueue(nodeId, name, idm.getId(), ms, pm, true, true,                              
+                                                 executor, selector,
+                                                 mDest.getFullSize(),
+                                                 mDest.getPageSize(),
+                                                 mDest.getDownCacheSize());
+                     binding = ((ClusteredPostOffice)topicPostOffice).bindClusteredQueue(jmsDestination.getName(), (LocalClusteredQueue)q);    
+                  }                 
                }
                else
                {
@@ -246,7 +263,7 @@
                   // Changing a durable subscriber is equivalent to unsubscribing (deleting) the old
                   // one and creating a new one.
    
-                  String filterString = binding.getFilter() != null ? binding.getFilter().getFilterString() : null;
+                  String filterString = binding.getQueue().getFilter() != null ? binding.getQueue().getFilter().getFilterString() : null;
                   
                   boolean selectorChanged =
                      (selectorString == null && filterString != null) ||
@@ -271,15 +288,26 @@
                      // create a fresh new subscription
                      
                      QueuedExecutor executor = (QueuedExecutor)pool.get();
-                     Queue q = 
-                        new Queue(idm.getId(), ms, pm, true, true,
-                                 mDest.getFullSize(),
-                                 mDest.getPageSize(),
-                                 mDest.getDownCacheSize(),
-                                 executor);
+                     PagingFilteredQueue q;
                      
-                     //Make a binding for this queue
-                     binding = topicPostOffice.bindQueue(name, jmsDestination.getName(), selector, q);  
+                     if (topicPostOffice.isLocal())
+                     {
+                        q = new PagingFilteredQueue(name, idm.getId(), ms, pm, true, true,                              
+                                                    executor, selector,
+                                                    mDest.getFullSize(),
+                                                    mDest.getPageSize(),
+                                                    mDest.getDownCacheSize());
+                        binding = topicPostOffice.bindQueue(jmsDestination.getName(), q);      
+                     }
+                     else
+                     {
+                        q = new LocalClusteredQueue(nodeId, name, idm.getId(), ms, pm, true, true,                              
+                                                    executor, selector,
+                                                    mDest.getFullSize(),
+                                                    mDest.getPageSize(),
+                                                    mDest.getDownCacheSize());
+                        binding = ((ClusteredPostOffice)topicPostOffice).bindClusteredQueue(jmsDestination.getName(), (LocalClusteredQueue)q);    
+                     }    
                   }               
                }
             }
@@ -300,7 +328,7 @@
          int prefetchSize = connectionEndpoint.getPrefetchSize();
          
          ServerConsumerEndpoint ep =
-            new ServerConsumerEndpoint(consumerID, binding.getQueue(), binding.getQueueName(),
+            new ServerConsumerEndpoint(consumerID, (PagingFilteredQueue)binding.getQueue(), binding.getQueue().getName(),
                                        this, selectorString, noLocal, jmsDestination, prefetchSize);
           
          JMSDispatcher.instance.registerTarget(new Integer(consumerID), new ConsumerAdvised(ep));
@@ -351,7 +379,7 @@
    	   int browserID = connectionEndpoint.getServerPeer().getNextObjectID();
    	   
    	   ServerBrowserEndpoint ep =
-   	      new ServerBrowserEndpoint(this, browserID, binding.getQueue(), messageSelector);
+   	      new ServerBrowserEndpoint(this, browserID, (PagingFilteredQueue)binding.getQueue(), messageSelector);
    	   
    	   putBrowserDelegate(browserID, ep);
    	   
@@ -572,12 +600,13 @@
          if (dest.isQueue())
          {
             QueuedExecutor executor = (QueuedExecutor)pool.get();
-            Queue q = 
-               new Queue(idm.getId(), ms, pm, true, false, fullSize, pageSize, downCacheSize,
-                         executor);
             
+            PagingFilteredQueue q = 
+               new PagingFilteredQueue(dest.getName(), idm.getId(), ms, pm, true, false,
+                                       executor, null, fullSize, pageSize, downCacheSize);
+            
             //Make a binding for this queue
-            queuePostOffice.bindQueue(dest.getName(), dest.getName(), null, q);  
+            queuePostOffice.bindQueue(dest.getName(), q);  
          }         
       }
       catch (Throwable t)
@@ -614,10 +643,9 @@
          }
          else
          {
-            //Topic
+            //Topic            
+            Collection bindings = topicPostOffice.listBindingsForCondition(dest.getName());
             
-            List bindings = topicPostOffice.listBindingsForCondition(dest.getName());
-            
             if (!bindings.isEmpty())
             {
                throw new IllegalStateException("Cannot delete temporary destination, since it has active consumer(s)");

Modified: trunk/src/main/org/jboss/messaging/core/Channel.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/Channel.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/Channel.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -131,12 +131,6 @@
    int messageCount();   
    
    /**
-    * Load the channel state from storage
-    * @throws Exception
-    */
-   void load() throws Exception;
-   
-   /**
     * Remove all the references in the channel
     * @throws Throwable
     */

Modified: trunk/src/main/org/jboss/messaging/core/ChannelSupport.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/ChannelSupport.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/ChannelSupport.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -97,7 +97,7 @@
    protected Object refLock;
 
    protected Object deliveryLock;
-
+      
    // Constructors --------------------------------------------------
 
    protected ChannelSupport(long channelID, MessageStore ms,
@@ -445,9 +445,9 @@
          }
       }
    }
+  
+   // Public --------------------------------------------------------   
 
-   // Public --------------------------------------------------------
-
    public int memoryRefCount()
    {
       synchronized (refLock)

Added: trunk/src/main/org/jboss/messaging/core/FilterFactory.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/FilterFactory.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/FilterFactory.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -0,0 +1,39 @@
+/*
+ * 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;
+
+/**
+ * A FilterFactory
+ * 
+ * This exists so we can abstract out the creation of filters inside core code so
+ * we don't have dependencies on jms selectors
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public interface FilterFactory
+{
+   Filter createFilter(String filterString) throws Exception;
+}

Deleted: trunk/src/main/org/jboss/messaging/core/PagingChannel.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/PagingChannel.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/PagingChannel.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -1,549 +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;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.jboss.logging.Logger;
-import org.jboss.messaging.core.plugin.contract.MessageStore;
-import org.jboss.messaging.core.plugin.contract.PersistenceManager;
-import org.jboss.messaging.core.plugin.contract.PersistenceManager.InitialLoadInfo;
-import org.jboss.messaging.core.plugin.contract.PersistenceManager.ReferenceInfo;
-
-import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
-
-/**
- * A PagingChannel
- * 
- * This channel implementation automatically pages message references to and from storage to prevent more
- * than a maximum number of references being stored in memory at once.
- * 
- * This allows us to support logical channels holding many millions of messages without running out of memory.
- *
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision: 1.1 $</tt>
- *
- * $Id$
- *
- */
-public class PagingChannel extends ChannelSupport
-{
-   private static final Logger log = Logger.getLogger(PagingChannel.class);
-   
-   private boolean trace = log.isTraceEnabled();
-   
-   protected List downCache;
-   
-   /**
-    * The maximum number of references this channel will hold before going into paging mode
-    */
-   protected int fullSize;
-
-   /**
-    * The maximum number of references to load from storage in one go when unpaging
-    */
-   protected int pageSize;
-
-   /**
-    * The maximum number of references paged to storage in one operation
-    */
-   protected int downCacheSize;
-
-   /**
-    * Are we in paging mode?
-    */
-   protected boolean paging;
-
-   /**
-    * The page order value for the first reference paged in storage
-    */
-   protected long firstPagingOrder;
-   
-   /**
-    * The value of page order for the next reference to page
-    */
-   protected long nextPagingOrder;
-   
-   /**
-    * @param channelID
-    * @param ms
-    * @param pm
-    * @param mm
-    * @param acceptReliableMessages
-    * @param recoverable
-    * @param fullSize
-    * @param pageSize
-    * @param downCacheSize
-    * @param executor
-    */
-   public PagingChannel(long channelID, MessageStore ms, PersistenceManager pm, boolean acceptReliableMessages, boolean recoverable, int fullSize, int pageSize, int downCacheSize, QueuedExecutor executor)
-   {
-      super(channelID, ms, pm, acceptReliableMessages, recoverable, executor);
-      
-      if (pageSize >= fullSize)
-      {
-         throw new IllegalArgumentException("pageSize must be less than full size");
-      }
-      if (downCacheSize > pageSize)
-      {
-         throw new IllegalArgumentException("pageSize cannot be smaller than downCacheSize");
-      }
-      if (pageSize <= 0)
-      {
-         throw new IllegalArgumentException("pageSize must be greater than zero");
-      }
-      if (downCacheSize <= 0)
-      {
-         throw new IllegalArgumentException("downCacheSize must be greater than zero");
-      }
-      
-      downCache = new ArrayList(downCacheSize);
-
-      this.fullSize = fullSize;
-
-      this.pageSize = pageSize;
-
-      this.downCacheSize = downCacheSize;      
-   }
-    
-   // Channel implementation
-   // ---------------------------------------------------------------
-   
-   public void load() throws Exception
-   {
-      if (trace) { log.trace(this + " loading channel state"); }
-      synchronized (refLock)
-      {
-         InitialLoadInfo ili = pm.getInitialReferenceInfos(channelID, fullSize);
-
-         if (ili.getMaxPageOrdering() != null)            
-         {
-            firstPagingOrder = ili.getMinPageOrdering().longValue();
-            
-            nextPagingOrder = ili.getMaxPageOrdering().longValue() + 1;
-            
-            paging = true;
-         }
-         else
-         {
-            firstPagingOrder = nextPagingOrder = 0;
-         }
-         
-         Map refMap = processReferences(ili.getRefInfos());
-         
-         Iterator iter = ili.getRefInfos().iterator();
-         while (iter.hasNext())
-         {
-            ReferenceInfo info = (ReferenceInfo)iter.next();
-
-            addFromRefInfo(info, refMap);
-         }         
-      }
-   }      
-   
-   public int messageCount()
-   {   
-      int count = super.messageCount();
-      
-      //Also need to add the paged refs
-      
-      synchronized (refLock)
-      {      
-         count += nextPagingOrder - firstPagingOrder;
-      }
-      
-      return count;
-   }
-   
-   // Public --------------------------------------------------------
-
-   public int downCacheCount()
-   {
-      synchronized (refLock)
-      {
-         return downCache.size();
-      }
-   }
-
-   public boolean isPaging()
-   {
-      synchronized (refLock)
-      {
-         return paging;
-      }
-   }
-   
-   // Protected -------------------------------------------------------
-   
-   protected boolean cancelInternal(Delivery del) throws Exception
-   {
-      if (trace) { log.trace(this + " cancelling " + del + " in memory"); }
-
-      boolean removed;
-
-      synchronized (deliveryLock)
-      {
-         removed = deliveries.remove(del);
-      }
-
-      if (!removed)
-      {         
-         // This can happen if the message is cancelled before the result of
-         // ServerConsumerDelegate.handle has returned, in which case we won't have a record of the delivery
-         // In this case we don't want to add the message reference back into
-         // the state since it was never removed in the first place
-
-         if (trace) { log.trace(this + " can't find delivery " + del + " in state so not replacing messsage ref"); }
-      }
-      else
-      {
-         synchronized (refLock)
-         {
-            messageRefs.addFirst(del.getReference(), del.getReference().getPriority());
-
-            if (paging)
-            {
-               // if paging we need to evict the end reference to storage to
-               // preserve the number of refs in the queue
-
-               MessageReference ref = (MessageReference)messageRefs.removeLast();
- 
-               addToDownCache(ref, true);
-            }
-         }
-
-         if (trace) { log.trace(this + " added " + del.getReference() + " back into state"); }
-      }
-      
-      return removed;
-   }
-   
-   protected MessageReference removeFirstInMemory() throws Exception
-   {
-      synchronized (refLock)
-      {
-         MessageReference result = (MessageReference) messageRefs.removeFirst();
-
-         long refNum = downCache.size() + nextPagingOrder - firstPagingOrder   ;
-         
-         if (refNum > 0)
-         {
-            long numberLoadable = Math.min(refNum, pageSize);
-
-            if (messageRefs.size() <= fullSize - numberLoadable)
-            {
-               //This will flush the down cache too
-               loadPagedReferences(numberLoadable);
-            }
-         }
-         else
-         {
-            paging = false;
-         }
-
-         return (MessageReference) result;
-      }
-   }
-   
-   protected void addReferenceInMemory(MessageReference ref) throws Exception
-   {
-      if (ref.isReliable() && !acceptReliableMessages)
-      {
-         throw new IllegalStateException("Reliable reference " + ref +
-                                         " cannot be added to non-recoverable state");
-      }
-
-      synchronized (refLock)
-      {
-         if (paging)
-         {
-            addToDownCache(ref, false);
-         }
-         else
-         {
-            messageRefs.addLast(ref, ref.getPriority());
-
-            if (trace){ log.trace(this + " added " + ref + " non-transactionally in memory"); }
-
-            if (messageRefs.size() == fullSize)
-            {
-               // We are full in memory - go into paging mode
-               if (trace) { log.trace(this + " going into paging mode"); }
-
-               paging = true;
-            }
-         }
-      }
-   }
-   
-   protected void addToDownCache(MessageReference ref, boolean cancelling) throws Exception
-   {
-      // If the down cache exists then refs are not spilled over immediately,
-      // but store in the cache and spilled over in one go when the next load is requested,
-      // or when it is full
-
-      // Both non reliable and reliable references can go in the down cache,
-      // however only non-reliable
-      // references actually get added to storage, reliable references instead
-      // just get their page ordering column updated since they will already be in storage
-
-      //If cancelling then the ref is supposed to go back on the front of the queue segment in storage
-      //so we set the page ordering to be firstPageOrdering - 1
-      //If not cancelling, then the ref should go on the end of the quueue in storage so
-      //we set the page ordering to be nextPageOrdering
-      
-      if (cancelling)
-      {
-         ref.setPagingOrder(firstPagingOrder - 1);
-         
-         firstPagingOrder--;
-      }
-      else
-      {
-         ref.setPagingOrder(nextPagingOrder);
-         
-         nextPagingOrder++;
-      }
-      
-      downCache.add(ref);
-
-      if (trace) { log.trace(ref + " sent to downcache"); }
-      
-      if (downCache.size() == downCacheSize)
-      {
-         if (trace) { log.trace(this + "'s downcache is full (" + downCache.size() + " messages)"); }
-               
-         flushDownCache();
-      }
-   }
-
-   protected void flushDownCache() throws Exception
-   {
-      if (trace) { log.trace(this + " flushing " + downCache.size() + " refs from downcache"); }
-
-      // Non persistent refs won't already be in the db so they need to be inserted
-      // Persistent refs in a recoverable state will already be there so need to
-      // be updated
-
-      List toUpdate = new ArrayList();
-
-      List toAdd = new ArrayList();
-
-      Iterator iter = downCache.iterator();
-      
-      while (iter.hasNext())
-      {
-         MessageReference ref = (MessageReference) iter.next();
-         
-         if (ref.isReliable() && recoverable)
-         {
-            toUpdate.add(ref);
-         }
-         else
-         {
-            toAdd.add(ref);
-         }
-      }
-
-      if (!toAdd.isEmpty())
-      {
-         pm.addReferences(channelID, toAdd);
-      }
-      if (!toUpdate.isEmpty())
-      {
-         pm.updatePageOrder(channelID, toUpdate);
-      }
-
-      // Release in memory refs for the refs we just spilled
-      // Note! This must be done after the db inserts - to ensure message is
-      // still in memory
-      iter = downCache.iterator();
-
-      while (iter.hasNext())
-      {
-         MessageReference ref = (MessageReference) iter.next();
-
-         ref.releaseMemoryReference();
-      }
-
-      downCache.clear();         
-
-      if (trace) { log.trace(this + " cleared downcache"); }
-   }
-   
-   
-   
-   protected void loadPagedReferences(long number) throws Exception
-   {
-      if (trace) { log.trace(this + " Loading " + number + " paged references from storage"); }
-
-      // Must flush the down cache first
-      flushDownCache();
-      
-      List refInfos = pm.getPagedReferenceInfos(channelID, firstPagingOrder, number);
-      
-      Map refMap = processReferences(refInfos);
-
-      boolean loadedReliable = false;
-
-      List toRemove = new ArrayList();
-
-      Iterator iter = refInfos.iterator();
-      while (iter.hasNext())
-      {
-         ReferenceInfo info = (ReferenceInfo)iter.next();
-         
-         MessageReference ref = addFromRefInfo(info, refMap);
-         
-         if (recoverable && ref.isReliable())
-         {
-            loadedReliable = true;
-         }
-         else
-         {
-            // We put the non reliable refs (or reliable in a non-recoverable store)
-            // in a list to be removed
-            toRemove.add(ref);
-         }
-      }
-
-      if (!toRemove.isEmpty())
-      {
-         // Now we remove the references we loaded (only the non persistent or persistent in a non-recoverable store)
-         
-         pm.removeReferences(channelID, toRemove);
-      }
-
-      if (loadedReliable)
-      {
-         // If we loaded any reliable refs then we must set the page ordering to null in
-         // the store otherwise they may get loaded again, the next time we do a load
-         // We can't delete them since they're reliable and haven't been acked yet
-         
-         pm.updateReliableReferencesNotPagedInRange(channelID, firstPagingOrder, number);
-      }
-            
-      firstPagingOrder += number;
-      
-      if (firstPagingOrder == nextPagingOrder)
-      {
-         //No more refs in storage
-         firstPagingOrder = nextPagingOrder = 0;
-         
-         if (messageRefs.size() != fullSize)
-         {
-            paging = false;
-         }
-      }    
-   }
-   
-   // Private ------------------------------------------------------------------------------
-   
-   private MessageReference addFromRefInfo(ReferenceInfo info, Map refMap)
-   {
-      long msgId = info.getMessageId();
-
-      MessageReference ref = (MessageReference)refMap.get(new Long(msgId));
-
-      ref.setDeliveryCount(info.getDeliveryCount());
-
-      ref.setPagingOrder(-1);
-      
-      //We ignore the reliable field from the message - this is because reliable might be true on the message
-      //but this is a non recoverable state
-      
-      //TODO - Really the message shouldn't have a reliable field at all,
-      //Reliability is an attribute of the message reference, not the message
-      
-      ref.setReliable(info.isReliable());
-      
-      messageRefs.addLast(ref, ref.getPriority());
-      
-      return ref;
-   }
-   
-   private Map processReferences(List refInfos) throws Exception
-   {
-      Map refMap = new HashMap(refInfos.size());
-
-      List msgIdsToLoad = new ArrayList(refInfos.size());
-
-      Iterator iter = refInfos.iterator();
-
-      // Put the refs that we already have messages for in a map
-      while (iter.hasNext())
-      {
-         ReferenceInfo info = (ReferenceInfo) iter.next();
-
-         long msgId = info.getMessageId();
-
-         MessageReference ref = ms.reference(msgId);
-
-         if (ref != null)
-         {
-            refMap.put(new Long(msgId), ref);
-         }
-         else
-         {
-            // Add id to list of msg ids to load
-            msgIdsToLoad.add(new Long(msgId));
-         }
-      }
-
-      // Load the messages (if any)
-      List messages = null;
-      if (!msgIdsToLoad.isEmpty())
-      {
-         messages = pm.getMessages(msgIdsToLoad);
-
-         if (messages.size() != msgIdsToLoad.size())
-         {
-            // Sanity check
-            throw new IllegalStateException("Did not load correct number of messages, wanted:" +
-                                            msgIdsToLoad.size() + " but got:" +
-                                            messages.size());
-         }
-
-         // Create references for these messages and add them to the reference map
-         iter = messages.iterator();
-
-         while (iter.hasNext())
-         {
-            Message m = (Message)iter.next();
-
-            // Message might actually be know to the store since we did the
-            // first check since might have been added by different channel
-            // in intervening period, but this is ok - the store knows to only
-            // return a reference to the pre-existing message
-            MessageReference ref = ms.reference(m);
-            
-            refMap.put(new Long(m.getMessageID()), ref);
-         }
-      }
-      
-      return refMap;
-   }
-}

Added: trunk/src/main/org/jboss/messaging/core/PagingChannelSupport.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/PagingChannelSupport.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/PagingChannelSupport.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -0,0 +1,641 @@
+/*
+ * 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;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.jboss.logging.Logger;
+import org.jboss.messaging.core.plugin.contract.MessageStore;
+import org.jboss.messaging.core.plugin.contract.PersistenceManager;
+import org.jboss.messaging.core.plugin.contract.PersistenceManager.InitialLoadInfo;
+import org.jboss.messaging.core.plugin.contract.PersistenceManager.ReferenceInfo;
+import org.jboss.messaging.core.tx.Transaction;
+
+import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
+
+/**
+ * A PagingChannel
+ * 
+ * This channel implementation automatically pages message references to and from storage to prevent more
+ * than a maximum number of references being stored in memory at once.
+ * 
+ * This allows us to support logical channels holding many millions of messages without running out of memory.
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public abstract class PagingChannelSupport extends ChannelSupport
+{
+   private static final Logger log = Logger.getLogger(PagingChannelSupport.class);
+   
+   private boolean trace = log.isTraceEnabled();
+   
+   protected List downCache;
+   
+   /**
+    * The maximum number of references this channel will hold before going into paging mode
+    */
+   protected int fullSize = 75000;
+
+   /**
+    * The maximum number of references to load from storage in one go when unpaging
+    */
+   protected int pageSize = 2000;
+
+   /**
+    * The maximum number of references paged to storage in one operation
+    */
+   protected int downCacheSize = 2000;
+
+   /**
+    * Are we in paging mode?
+    */
+   protected boolean paging;
+
+   /**
+    * The page order value for the first reference paged in storage
+    */
+   protected long firstPagingOrder;
+   
+   /**
+    * The value of page order for the next reference to page
+    */
+   protected long nextPagingOrder;
+   
+   /**
+    * Is the queue active?
+    */
+   protected boolean active;
+   
+
+   /**
+    * Constructor with default paging params
+    * @param channelID
+    * @param ms
+    * @param pm
+    * @param mm
+    * @param acceptReliableMessages
+    * @param recoverable
+    * @param fullSize
+    * @param pageSize
+    * @param downCacheSize
+    * @param executor
+    */
+   public PagingChannelSupport(long channelID, MessageStore ms, PersistenceManager pm,
+                               boolean acceptReliableMessages, boolean recoverable,                        
+                               QueuedExecutor executor)
+   {
+      super(channelID, ms, pm, acceptReliableMessages, recoverable, executor);
+      
+      downCache = new ArrayList(downCacheSize);    
+      
+      active = true;
+   }
+   
+   /**
+    * Constructor specifying paging params
+    * @param channelID
+    * @param ms
+    * @param pm
+    * @param acceptReliableMessages
+    * @param recoverable
+    * @param executor
+    * @param fullSize
+    * @param pageSize
+    * @param downCacheSize
+    */
+   public PagingChannelSupport(long channelID, MessageStore ms, PersistenceManager pm,
+                               boolean acceptReliableMessages, boolean recoverable,                        
+                               QueuedExecutor executor,
+                               int fullSize, int pageSize, int downCacheSize)
+   {
+      super(channelID, ms, pm, acceptReliableMessages, recoverable, executor);
+      
+      if (pageSize >= fullSize)
+      {
+         throw new IllegalArgumentException("pageSize must be less than full size");
+      }
+      if (downCacheSize > pageSize)
+      {
+         throw new IllegalArgumentException("pageSize cannot be smaller than downCacheSize");
+      }
+      if (pageSize <= 0)
+      {
+         throw new IllegalArgumentException("pageSize must be greater than zero");
+      }
+      if (downCacheSize <= 0)
+      {
+         throw new IllegalArgumentException("downCacheSize must be greater than zero");
+      }
+      
+      downCache = new ArrayList(downCacheSize);    
+      
+      this.fullSize = fullSize;
+      
+      this.pageSize = pageSize;
+      
+      this.downCacheSize = downCacheSize;
+      
+      active = true;
+   }
+    
+   // Receiver implementation
+   // -----------------------------------------------------------------
+   
+   public Delivery handle(DeliveryObserver sender, MessageReference ref, Transaction tx)
+   {
+      if (!active)
+      {
+         return null;
+      }
+      
+      return super.handle(sender, ref, tx);
+   }
+   
+   // Channel implementation
+   // ---------------------------------------------------------------
+         
+   public int messageCount()
+   {   
+      int count = super.messageCount();
+      
+      //Also need to add the paged refs
+      
+      synchronized (refLock)
+      {      
+         count += nextPagingOrder - firstPagingOrder;
+      }
+      
+      return count;
+   }
+   
+   // Public --------------------------------------------------------
+
+   public int downCacheCount()
+   {
+      synchronized (refLock)
+      {
+         return downCache.size();
+      }
+   }
+
+   public boolean isPaging()
+   {
+      synchronized (refLock)
+      {
+         return paging;
+      }
+   }
+   
+   public void activate(int fullSize, int pageSize, int downCacheSize) throws Exception
+   {            
+      synchronized (refLock)
+      {
+         if (active)
+         {
+            return;
+         }
+         
+         this.fullSize = fullSize;
+         
+         this.pageSize = pageSize;
+         
+         this.downCacheSize = downCacheSize;
+         
+         if (trace) { log.trace(this + " loading channel state"); }
+         
+         InitialLoadInfo ili = pm.getInitialReferenceInfos(channelID, fullSize);
+
+         if (ili.getMaxPageOrdering() != null)            
+         {
+            firstPagingOrder = ili.getMinPageOrdering().longValue();
+            
+            nextPagingOrder = ili.getMaxPageOrdering().longValue() + 1;
+            
+            paging = true;
+         }
+         else
+         {
+            firstPagingOrder = nextPagingOrder = 0;
+         }
+         
+         Map refMap = processReferences(ili.getRefInfos());
+         
+         Iterator iter = ili.getRefInfos().iterator();
+         while (iter.hasNext())
+         {
+            ReferenceInfo info = (ReferenceInfo)iter.next();
+
+            addFromRefInfo(info, refMap);
+         }         
+      }
+      
+      active = true;
+   }      
+   
+   public void deactivate() throws Exception
+   {
+      synchronized (refLock)
+      {
+         synchronized (deliveryLock)
+         {
+            messageRefs.clear();
+            
+            deliveries.clear();
+            
+            downCache.clear();
+            
+            paging = false;
+            
+            firstPagingOrder = nextPagingOrder = 0;
+            
+            active = true;
+         }
+      }
+   }
+   
+   public boolean isActive()
+   {
+      synchronized (refLock)
+      {
+         return active;
+      }
+   }
+   
+   // Protected -------------------------------------------------------
+   
+   protected boolean cancelInternal(Delivery del) throws Exception
+   {
+      if (trace) { log.trace(this + " cancelling " + del + " in memory"); }
+
+      boolean removed;
+
+      synchronized (deliveryLock)
+      {
+         removed = deliveries.remove(del);
+      }
+
+      if (!removed)
+      {         
+         // This can happen if the message is cancelled before the result of
+         // ServerConsumerDelegate.handle has returned, in which case we won't have a record of the delivery
+         // In this case we don't want to add the message reference back into
+         // the state since it was never removed in the first place
+
+         if (trace) { log.trace(this + " can't find delivery " + del + " in state so not replacing messsage ref"); }
+      }
+      else
+      {
+         synchronized (refLock)
+         {
+            messageRefs.addFirst(del.getReference(), del.getReference().getPriority());
+
+            if (paging)
+            {
+               // if paging we need to evict the end reference to storage to
+               // preserve the number of refs in the queue
+
+               MessageReference ref = (MessageReference)messageRefs.removeLast();
+ 
+               addToDownCache(ref, true);
+            }
+         }
+
+         if (trace) { log.trace(this + " added " + del.getReference() + " back into state"); }
+      }
+      
+      return removed;
+   }
+   
+   protected MessageReference removeFirstInMemory() throws Exception
+   {
+      synchronized (refLock)
+      {
+         MessageReference result = (MessageReference) messageRefs.removeFirst();
+
+         long refNum = downCache.size() + nextPagingOrder - firstPagingOrder   ;
+         
+         if (refNum > 0)
+         {
+            long numberLoadable = Math.min(refNum, pageSize);
+
+            if (messageRefs.size() <= fullSize - numberLoadable)
+            {
+               //This will flush the down cache too
+               loadPagedReferences(numberLoadable);
+            }
+         }
+         else
+         {
+            paging = false;
+         }
+
+         return (MessageReference) result;
+      }
+   }
+   
+   protected void addReferenceInMemory(MessageReference ref) throws Exception
+   {
+      if (ref.isReliable() && !acceptReliableMessages)
+      {
+         throw new IllegalStateException("Reliable reference " + ref +
+                                         " cannot be added to non-recoverable state");
+      }
+
+      synchronized (refLock)
+      {
+         if (paging)
+         {
+            addToDownCache(ref, false);
+         }
+         else
+         {
+            messageRefs.addLast(ref, ref.getPriority());
+
+            if (trace){ log.trace(this + " added " + ref + " non-transactionally in memory"); }
+
+            if (messageRefs.size() == fullSize)
+            {
+               // We are full in memory - go into paging mode
+               if (trace) { log.trace(this + " going into paging mode"); }
+
+               paging = true;
+            }
+         }
+      }
+   }
+   
+   protected void addToDownCache(MessageReference ref, boolean cancelling) throws Exception
+   {
+      // If the down cache exists then refs are not spilled over immediately,
+      // but store in the cache and spilled over in one go when the next load is requested,
+      // or when it is full
+
+      // Both non reliable and reliable references can go in the down cache,
+      // however only non-reliable
+      // references actually get added to storage, reliable references instead
+      // just get their page ordering column updated since they will already be in storage
+
+      //If cancelling then the ref is supposed to go back on the front of the queue segment in storage
+      //so we set the page ordering to be firstPageOrdering - 1
+      //If not cancelling, then the ref should go on the end of the quueue in storage so
+      //we set the page ordering to be nextPageOrdering
+      
+      if (cancelling)
+      {
+         ref.setPagingOrder(firstPagingOrder - 1);
+         
+         firstPagingOrder--;
+      }
+      else
+      {
+         ref.setPagingOrder(nextPagingOrder);
+         
+         nextPagingOrder++;
+      }
+      
+      downCache.add(ref);
+
+      if (trace) { log.trace(ref + " sent to downcache"); }
+      
+      if (downCache.size() == downCacheSize)
+      {
+         if (trace) { log.trace(this + "'s downcache is full (" + downCache.size() + " messages)"); }
+               
+         flushDownCache();
+      }
+   }
+
+   protected void flushDownCache() throws Exception
+   {
+      if (trace) { log.trace(this + " flushing " + downCache.size() + " refs from downcache"); }
+
+      // Non persistent refs won't already be in the db so they need to be inserted
+      // Persistent refs in a recoverable state will already be there so need to
+      // be updated
+
+      List toUpdate = new ArrayList();
+
+      List toAdd = new ArrayList();
+
+      Iterator iter = downCache.iterator();
+      
+      while (iter.hasNext())
+      {
+         MessageReference ref = (MessageReference) iter.next();
+         
+         if (ref.isReliable() && recoverable)
+         {
+            toUpdate.add(ref);
+         }
+         else
+         {
+            toAdd.add(ref);
+         }
+      }
+
+      if (!toAdd.isEmpty())
+      {
+         pm.addReferences(channelID, toAdd);
+      }
+      if (!toUpdate.isEmpty())
+      {
+         pm.updatePageOrder(channelID, toUpdate);
+      }
+
+      // Release in memory refs for the refs we just spilled
+      // Note! This must be done after the db inserts - to ensure message is
+      // still in memory
+      iter = downCache.iterator();
+
+      while (iter.hasNext())
+      {
+         MessageReference ref = (MessageReference) iter.next();
+
+         ref.releaseMemoryReference();
+      }
+
+      downCache.clear();         
+
+      if (trace) { log.trace(this + " cleared downcache"); }
+   }
+   
+   
+   
+   protected void loadPagedReferences(long number) throws Exception
+   {
+      if (trace) { log.trace(this + " Loading " + number + " paged references from storage"); }
+
+      // Must flush the down cache first
+      flushDownCache();
+      
+      List refInfos = pm.getPagedReferenceInfos(channelID, firstPagingOrder, number);
+      
+      Map refMap = processReferences(refInfos);
+
+      boolean loadedReliable = false;
+
+      List toRemove = new ArrayList();
+
+      Iterator iter = refInfos.iterator();
+      while (iter.hasNext())
+      {
+         ReferenceInfo info = (ReferenceInfo)iter.next();
+         
+         MessageReference ref = addFromRefInfo(info, refMap);
+         
+         if (recoverable && ref.isReliable())
+         {
+            loadedReliable = true;
+         }
+         else
+         {
+            // We put the non reliable refs (or reliable in a non-recoverable store)
+            // in a list to be removed
+            toRemove.add(ref);
+         }
+      }
+
+      if (!toRemove.isEmpty())
+      {
+         // Now we remove the references we loaded (only the non persistent or persistent in a non-recoverable store)
+         
+         pm.removeReferences(channelID, toRemove);
+      }
+
+      if (loadedReliable)
+      {
+         // If we loaded any reliable refs then we must set the page ordering to null in
+         // the store otherwise they may get loaded again, the next time we do a load
+         // We can't delete them since they're reliable and haven't been acked yet
+         
+         pm.updateReliableReferencesNotPagedInRange(channelID, firstPagingOrder, number);
+      }
+            
+      firstPagingOrder += number;
+      
+      if (firstPagingOrder == nextPagingOrder)
+      {
+         //No more refs in storage
+         firstPagingOrder = nextPagingOrder = 0;
+         
+         if (messageRefs.size() != fullSize)
+         {
+            paging = false;
+         }
+      }    
+   }
+   
+   // Private ------------------------------------------------------------------------------
+   
+   private MessageReference addFromRefInfo(ReferenceInfo info, Map refMap)
+   {
+      long msgId = info.getMessageId();
+
+      MessageReference ref = (MessageReference)refMap.get(new Long(msgId));
+
+      ref.setDeliveryCount(info.getDeliveryCount());
+
+      ref.setPagingOrder(-1);
+      
+      //We ignore the reliable field from the message - this is because reliable might be true on the message
+      //but this is a non recoverable state
+      
+      //TODO - Really the message shouldn't have a reliable field at all,
+      //Reliability is an attribute of the message reference, not the message
+      
+      ref.setReliable(info.isReliable());
+      
+      messageRefs.addLast(ref, ref.getPriority());
+      
+      return ref;
+   }
+   
+   private Map processReferences(List refInfos) throws Exception
+   {
+      Map refMap = new HashMap(refInfos.size());
+
+      List msgIdsToLoad = new ArrayList(refInfos.size());
+
+      Iterator iter = refInfos.iterator();
+
+      // Put the refs that we already have messages for in a map
+      while (iter.hasNext())
+      {
+         ReferenceInfo info = (ReferenceInfo) iter.next();
+
+         long msgId = info.getMessageId();
+
+         MessageReference ref = ms.reference(msgId);
+
+         if (ref != null)
+         {
+            refMap.put(new Long(msgId), ref);
+         }
+         else
+         {
+            // Add id to list of msg ids to load
+            msgIdsToLoad.add(new Long(msgId));
+         }
+      }
+
+      // Load the messages (if any)
+      List messages = null;
+      if (!msgIdsToLoad.isEmpty())
+      {
+         messages = pm.getMessages(msgIdsToLoad);
+
+         if (messages.size() != msgIdsToLoad.size())
+         {
+            // Sanity check
+            throw new IllegalStateException("Did not load correct number of messages, wanted:" +
+                                            msgIdsToLoad.size() + " but got:" +
+                                            messages.size());
+         }
+
+         // Create references for these messages and add them to the reference map
+         iter = messages.iterator();
+
+         while (iter.hasNext())
+         {
+            Message m = (Message)iter.next();
+
+            // Message might actually be know to the store since we did the
+            // first check since might have been added by different channel
+            // in intervening period, but this is ok - the store knows to only
+            // return a reference to the pre-existing message
+            MessageReference ref = ms.reference(m);
+            
+            refMap.put(new Long(m.getMessageID()), ref);
+         }
+      }
+      
+      return refMap;
+   }
+}

Added: trunk/src/main/org/jboss/messaging/core/Queue.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/Queue.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/Queue.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -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;
+
+/**
+ * A Queue
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public interface Queue extends Channel
+{
+   public String getName();
+   
+   public Filter getFilter();
+}

Added: trunk/src/main/org/jboss/messaging/core/local/PagingFilteredQueue.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/local/PagingFilteredQueue.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/local/PagingFilteredQueue.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -0,0 +1,139 @@
+/*
+  * 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.PagingChannelSupport;
+import org.jboss.messaging.core.Queue;
+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 PagingFilteredQueue
+ * 
+ * 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: 1295 $</tt>
+ *
+ * $Id: Queue.java 1295 2006-09-15 17:44:02Z timfox $
+ *
+ */
+public class PagingFilteredQueue extends PagingChannelSupport implements Queue
+{
+   // Constants -----------------------------------------------------
+   
+   private static final Logger log;
+   
+   private static final boolean trace;
+   
+   static
+   {
+      log = Logger.getLogger(PagingFilteredQueue.class);
+      trace = log.isTraceEnabled();
+   }
+
+   // Static --------------------------------------------------------
+   
+   // Attributes ----------------------------------------------------
+   
+   private String name;
+   
+   private Filter filter;
+   
+   // Constructors --------------------------------------------------
+
+   public PagingFilteredQueue(String name, long id, MessageStore ms, PersistenceManager pm,             
+                             boolean acceptReliableMessages, boolean recoverable, QueuedExecutor executor,
+                             Filter filter)
+   {
+      super(id, ms, pm, acceptReliableMessages, recoverable, executor);
+      
+      router = new RoundRobinPointToPointRouter();
+      
+      this.name = name;
+      
+      this.filter = filter;
+   }
+   
+   public PagingFilteredQueue(String name, long id, MessageStore ms, PersistenceManager pm,             
+                              boolean acceptReliableMessages, boolean recoverable, QueuedExecutor executor,
+                              Filter filter,
+                              int fullSize, int pageSize, int downCacheSize)
+   {
+      super(id, ms, pm, acceptReliableMessages, recoverable, executor, fullSize, pageSize, downCacheSize);
+      
+      router = new RoundRobinPointToPointRouter();
+      
+      this.name = name;
+      
+      this.filter = filter;
+   }
+    
+   // Channel implementation ----------------------------------------   
+   
+   public Delivery handle(DeliveryObserver sender, MessageReference ref, Transaction tx)
+   {
+      if (filter.accept(ref))
+      {
+         return super.handle(sender, ref, tx);
+      }
+      else
+      {
+         return null;
+      }
+   }
+   
+   // Public --------------------------------------------------------
+
+   public String getName()
+   {
+      return name;
+   }
+   
+   public String toString()
+   {
+      return "Queue[" + getChannelID() + "]";
+   }
+   
+   public Filter getFilter()
+   {
+      return filter;
+   }
+
+   // Package protected ---------------------------------------------
+   
+   // Protected -----------------------------------------------------
+   
+   // Private -------------------------------------------------------
+   
+   // Inner classes -------------------------------------------------   
+}

Deleted: trunk/src/main/org/jboss/messaging/core/local/Queue.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/local/Queue.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/local/Queue.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -1,91 +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.PagingChannel;
-import org.jboss.messaging.core.plugin.contract.MessageStore;
-import org.jboss.messaging.core.plugin.contract.PersistenceManager;
-
-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 ----------------------------------------------------
-    
-   // Constructors --------------------------------------------------
-
-   public Queue(long id, MessageStore ms, PersistenceManager pm,             
-                boolean acceptReliableMessages, boolean recoverable,
-                int fullSize, int pageSize, int downCacheSize, QueuedExecutor executor)
-   {
-      super(id, ms, pm, acceptReliableMessages, recoverable, fullSize, pageSize, downCacheSize, executor);
-      
-      router = new RoundRobinPointToPointRouter();
-   }
-    
-   // Channel implementation ----------------------------------------   
-
-   // Public --------------------------------------------------------
-
-   public String toString()
-   {
-      return "Queue[" + getChannelID() + "]";
-   }
-   
-   // Package protected ---------------------------------------------
-   
-   // Protected -----------------------------------------------------
-   
-   // Private -------------------------------------------------------
-   
-   // Inner classes -------------------------------------------------   
-}

Modified: trunk/src/main/org/jboss/messaging/core/plugin/ClusteredPostOfficeService.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/ClusteredPostOfficeService.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/ClusteredPostOfficeService.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -24,16 +24,17 @@
 import javax.management.ObjectName;
 import javax.transaction.TransactionManager;
 
+import org.jboss.jms.selector.SelectorFactory;
+import org.jboss.jms.server.QueuedExecutorPool;
 import org.jboss.jms.server.ServerPeer;
 import org.jboss.jms.util.ExceptionUtil;
+import org.jboss.messaging.core.FilterFactory;
 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.BasicRedistributionPolicy;
 import org.jboss.messaging.core.plugin.postoffice.cluster.ClusteredPostOfficeImpl;
-import org.jboss.messaging.core.plugin.postoffice.cluster.FavourLocalRoutingPolicy;
 import org.jboss.messaging.core.plugin.postoffice.cluster.RedistributionPolicy;
-import org.jboss.messaging.core.plugin.postoffice.cluster.RoutingPolicy;
 import org.jboss.messaging.core.tx.TransactionRepository;
 import org.w3c.dom.Element;
 
@@ -198,18 +199,21 @@
          
          PersistenceManager pm = serverPeer.getPersistenceManagerInstance();
          
+         QueuedExecutorPool pool = serverPeer.getQueuedExecutorPool();
+                  
          String nodeId = serverPeer.getServerPeerID();
          
-         RoutingPolicy routingPolicy = new FavourLocalRoutingPolicy(nodeId);
+         RedistributionPolicy redistPolicy = new BasicRedistributionPolicy(nodeId);
          
-         RedistributionPolicy redistPolicy = new BasicRedistributionPolicy(nodeId);
+         FilterFactory ff = new SelectorFactory();
                   
          postOffice =  new ClusteredPostOfficeImpl(ds, tm, sqlProperties, createTablesOnStartup,
                                                nodeId, officeName, ms,
+                                               pm, tr, ff, pool, 
                                                groupName,
                                                syncChannelConfig, asyncChannelConfig,
-                                               tr, pm, stateTimeout, castTimeout,
-                                               routingPolicy, redistPolicy, redistPeriod);
+                                               stateTimeout, castTimeout,
+                                               redistPolicy, redistPeriod);
          
          postOffice.start();
          

Modified: trunk/src/main/org/jboss/messaging/core/plugin/SimplePostOfficeService.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/SimplePostOfficeService.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/SimplePostOfficeService.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -24,10 +24,14 @@
 import javax.management.ObjectName;
 import javax.transaction.TransactionManager;
 
+import org.jboss.jms.selector.SelectorFactory;
+import org.jboss.jms.server.QueuedExecutorPool;
 import org.jboss.jms.server.ServerPeer;
 import org.jboss.jms.util.ExceptionUtil;
+import org.jboss.messaging.core.FilterFactory;
 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.PostOfficeImpl;
 import org.jboss.messaging.core.tx.TransactionRepository;
 
@@ -116,13 +120,19 @@
          
          MessageStore ms = serverPeer.getMessageStore();
          
+         PersistenceManager pm = serverPeer.getPersistenceManagerInstance();
+         
+         QueuedExecutorPool pool = serverPeer.getQueuedExecutorPool();
+         
          TransactionRepository tr = serverPeer.getTxRepository();
          
          String nodeId = serverPeer.getServerPeerID();
-                  
+         
+         FilterFactory ff = new SelectorFactory();
+               
          postOffice = new PostOfficeImpl(ds, tm, sqlProperties,
-                                           createTablesOnStartup,
-                                           nodeId, officeName, ms, tr);
+                                         createTablesOnStartup,
+                                         nodeId, officeName, ms, pm, tr, ff, pool);
          
          postOffice.start();
          

Modified: trunk/src/main/org/jboss/messaging/core/plugin/contract/ClusteredPostOffice.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/contract/ClusteredPostOffice.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/contract/ClusteredPostOffice.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -21,9 +21,8 @@
  */
 package org.jboss.messaging.core.plugin.contract;
 
-import org.jboss.messaging.core.Filter;
-import org.jboss.messaging.core.plugin.postoffice.cluster.ClusteredBinding;
-import org.jboss.messaging.core.plugin.postoffice.cluster.ClusteredQueue;
+import org.jboss.messaging.core.plugin.postoffice.Binding;
+import org.jboss.messaging.core.plugin.postoffice.cluster.LocalClusteredQueue;
 
 /**
  * 
@@ -40,14 +39,12 @@
    /**
     * 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
     */
-   ClusteredBinding bindClusteredQueue(String queueName, String condition, Filter filter, ClusteredQueue queue) throws Exception;
+   Binding bindClusteredQueue(String condition, LocalClusteredQueue queue) throws Exception;
    
    /**
     * Unbind a clustered queue from the post office
@@ -55,6 +52,6 @@
     * @return
     * @throws Throwable
     */
-   ClusteredBinding unbindClusteredQueue(String queueName) throws Throwable;
+   Binding unbindClusteredQueue(String queueName) throws Throwable;
   
 }

Modified: trunk/src/main/org/jboss/messaging/core/plugin/contract/PostOffice.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/contract/PostOffice.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/contract/PostOffice.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -21,11 +21,10 @@
  */
 package org.jboss.messaging.core.plugin.contract;
 
-import java.util.List;
+import java.util.Collection;
 
-import org.jboss.messaging.core.Filter;
 import org.jboss.messaging.core.MessageReference;
-import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.Queue;
 import org.jboss.messaging.core.plugin.postoffice.Binding;
 import org.jboss.messaging.core.tx.Transaction;
 
@@ -49,24 +48,9 @@
  */
 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 filter The filter to use
-    * @param queue
-    * @return
-    * @throws Exception
-    */
-   Binding bindQueue(String queueName, String condition, Filter filter, Queue queue) throws Exception;
+   Binding bindQueue(String condition, 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;
    
    /**
@@ -75,7 +59,7 @@
     * @return
     * @throws Exception
     */
-   List listBindingsForCondition(String condition) throws Exception;
+   Collection listBindingsForCondition(String condition) throws Exception;
    
    /**
     * Get the binding for the specified queue name
@@ -98,4 +82,6 @@
    boolean route(MessageReference ref, String condition, Transaction tx) throws Exception;   
    
    void recover() throws Exception;
+   
+   boolean isLocal();
 }

Modified: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/Binding.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/Binding.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/Binding.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -21,12 +21,11 @@
  */
 package org.jboss.messaging.core.plugin.postoffice;
 
-import org.jboss.messaging.core.Filter;
-import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.Queue;
 
 /**
  * A Binding
-
+ *
  * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
  * @version <tt>$Revision: 1.1 $</tt>
  *
@@ -35,26 +34,9 @@
  */
 public interface Binding
 {
-   String getNodeId();
+   public String getNodeId();
    
-   String getQueueName();
+   public String getCondition();
    
-   String getCondition();
-   
-   Queue getQueue();
-   
-   Filter getFilter();
-     
-   long getChannelId();
-   
-   boolean isDurable();
-   
-   boolean isActive();
-   
-   void activate();
-   
-   void deactivate();
-   
-   void setQueue(Queue queue);
-
+   public Queue getQueue();
 }

Modified: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/BindingImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/BindingImpl.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/BindingImpl.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -21,14 +21,8 @@
  */
 package org.jboss.messaging.core.plugin.postoffice;
 
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
+import org.jboss.messaging.core.Queue;
 
-import org.jboss.jms.selector.Selector;
-import org.jboss.messaging.core.Filter;
-import org.jboss.messaging.core.local.Queue;
-import org.jboss.messaging.util.StreamUtils;
-
 /**
  * 
  * A BindingImpl
@@ -43,53 +37,28 @@
 {
    private String nodeId;
    
-   private String queueName;
-   
    private String condition;
    
    private Queue queue;
-    
-   private boolean active;
-   
-   private Filter filter;
-   
-   private long channelId;
-     
-   private boolean durable;
-         
+       
    public BindingImpl()
    {      
    }
 
-   public BindingImpl(String nodeId, String queueName, String condition, Filter filter,
-                      long channelId, boolean durable)
+   public BindingImpl(String nodeId, String condition, Queue queue)
    {
       this.nodeId = nodeId;
       
-      this.queueName = queueName;
+      this.condition = condition;     
       
-      this.condition = condition;      
-      
-      this.filter = filter;
-      
-      this.channelId = channelId;
-         
-      //Bindings are always created de-activated
-      this.active = false;
-      
-      this.durable = durable;          
+      this.queue = queue;
    }
    
    public String getNodeId()
    {
       return nodeId;
    }
-     
-   public String getQueueName()
-   {
-      return queueName;
-   }
-   
+      
    public String getCondition()
    {
       return condition;
@@ -99,82 +68,4 @@
    {
       return queue;
    }
- 
-   public void activate()
-   {
-      active = true;
-   }
-   
-   public void deactivate()
-   {
-      active = false;
-   }
-   
-   public boolean isActive()
-   {
-      return active;
-   }
-   
-   public Filter getFilter()
-   {
-      return filter;
-   }
-   
-   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 read(DataInputStream in) throws Exception
-   {
-      nodeId = in.readUTF();
-      
-      queueName = in.readUTF();
-      
-      condition = in.readUTF();
-      
-      active = in.readBoolean();
-      
-      String filterString = (String)StreamUtils.readObject(in, false);
-      
-      //TODO we need to generalise this
-      filter = new Selector(filterString);
-      
-      channelId = in.readLong();
-      
-      durable = in.readBoolean();
-   }
-
-   public void write(DataOutputStream out) throws Exception
-   {
-      out.writeUTF(nodeId);
-      
-      out.writeUTF(queueName);
-      
-      out.writeUTF(condition);
-      
-      out.writeBoolean(active);
-      
-      StreamUtils.writeObject(out, filter.getFilterString(), false, false);
-      
-      out.writeLong(channelId);
-      
-      out.writeBoolean(durable);
-   }
-
 }

Added: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/Bindings.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/Bindings.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/Bindings.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -0,0 +1,46 @@
+/*
+ * 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.util.Collection;
+
+/**
+ * A Bindings
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public interface Bindings
+{
+   void addBinding(Binding binding);
+   
+   boolean removeBinding(Binding binding);
+   
+   Collection getAllBindings();
+   
+   int getDurableCount();
+   
+   boolean isEmpty();
+}

Added: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/BindingsImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/BindingsImpl.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/BindingsImpl.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -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.messaging.core.plugin.postoffice;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * A BindingsImpl
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class BindingsImpl implements Bindings
+{
+   private List bindings;
+   
+   private int durableCount;
+   
+   public BindingsImpl()
+   {
+      bindings = new ArrayList();
+   }
+
+   public void addBinding(Binding binding)
+   {
+      if (bindings.contains(binding))
+      {
+         throw new IllegalArgumentException("Bindings already contains binding: " + binding);
+      }
+      bindings.add(binding);
+      
+      if (binding.getQueue().isRecoverable())
+      {
+         durableCount++;
+      }
+   }
+
+   public Collection getAllBindings()
+   {
+      return bindings;
+   }
+
+   public boolean removeBinding(Binding binding)
+   {
+      boolean removed = bindings.remove(binding);
+      
+      if (removed && binding.getQueue().isRecoverable())
+      {
+         durableCount--;
+      }
+      
+      return removed;
+   }
+   
+   public int getDurableCount()
+   {
+      return durableCount;
+   }
+   
+   public boolean isEmpty()
+   {
+      return bindings.isEmpty();
+   }
+
+}

Deleted: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/ConditionBindings.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/ConditionBindings.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/ConditionBindings.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -1,179 +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.postoffice;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-
-/**
- * A ConditionBindings
- *
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision: 1.1 $</tt>
- *
- * $Id$
- *
- */
-public class ConditionBindings
-{
-   private List allBindings;
-   
-   private List durableBindings;
-   
-   private List nonDurableBindings;
-   
-   // Map <name, binding or list of bindings>
-   private Map nameMap;
-   
-   private String thisNode;
-   
-   private int localDurableCount;
-   
-   public ConditionBindings(String thisNode)
-   {
-      allBindings = new ArrayList();
-      
-      durableBindings = new ArrayList();
-      
-      nonDurableBindings = new ArrayList();
-      
-      nameMap = new HashMap();
-      
-      this.thisNode = thisNode;
-   }
-   
-   public void addBinding(Binding binding)
-   {
-      if (allBindings.contains(binding))
-      {
-         throw new IllegalArgumentException("Bindings already contains binding: " + binding);
-      }
-               
-      allBindings.add(binding);
-      
-      if (binding.isDurable())
-      {
-         durableBindings.add(binding);
-      }
-      else
-      {
-         nonDurableBindings.add(binding);
-      }
-      
-      List bindings = (List)nameMap.get(binding.getQueueName());
-      
-      if (bindings == null)
-      {
-         bindings = new ArrayList();
-         
-         nameMap.put(binding.getQueueName(), bindings);
-      }
-      
-      bindings.add(binding);      
-      
-      if (binding.isDurable() && binding.getNodeId().equals(thisNode))
-      {
-         localDurableCount++;
-      }
-   }
-   
-   public boolean removeBinding(Binding binding)
-   {
-      boolean removed = allBindings.remove(binding);
-      
-      if (!removed)
-      {
-         return false;
-      }
-      
-      if (binding.isDurable())
-      {
-         durableBindings.remove(binding);
-      }
-      else
-      {
-         nonDurableBindings.remove(binding);
-      }
-      
-      List bindings = (List)nameMap.get(binding.getQueueName());
-      
-      if (bindings == null)
-      {
-         throw new IllegalStateException("Cannot find bindins in name map");
-      }
-      
-      removed = bindings.remove(binding);
-      
-      if (!removed)
-      {
-         throw new IllegalStateException("Cannot find binding in list");
-      }
-      
-      if (bindings.isEmpty())
-      {
-         nameMap.remove(binding.getQueueName());
-      }
-      
-      if (binding.isDurable() && binding.getNodeId().equals(thisNode))
-      {
-         localDurableCount--;
-      }
-      
-      return true;
-   }
-   
-   public Collection getBindingsByName()
-   {
-      return nameMap.values();
-   }
-   
-   public boolean isEmpty()
-   {
-      return nameMap.isEmpty();
-   }
-   
-   public List getAllBindings()
-   {
-      return allBindings;
-   }
-   
-   public int getLocalDurableCount()
-   {
-      return this.localDurableCount;
-   }
-   
-   public int getDurableCount()
-   {
-      return this.durableBindings.size();
-   }
-   
-   public int getRemoteDurableCount()
-   {
-      return getDurableCount() - getLocalDurableCount();
-   }
-   
-      
-}

Modified: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/PostOfficeImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/PostOfficeImpl.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/PostOfficeImpl.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -25,30 +25,33 @@
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.Types;
-import java.util.ArrayList;
+import java.util.Collection;
 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.jms.selector.Selector;
+import org.jboss.jms.server.QueuedExecutorPool;
 import org.jboss.logging.Logger;
 import org.jboss.messaging.core.Delivery;
 import org.jboss.messaging.core.Filter;
+import org.jboss.messaging.core.FilterFactory;
 import org.jboss.messaging.core.MessageReference;
-import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.Queue;
 import org.jboss.messaging.core.plugin.JDBCSupport;
 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.cluster.LocalClusteredQueue;
 import org.jboss.messaging.core.tx.Transaction;
 import org.jboss.messaging.core.tx.TransactionRepository;
 
+import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
 import EDU.oswego.cs.dl.util.concurrent.ReadWriteLock;
 import EDU.oswego.cs.dl.util.concurrent.WriterPreferenceReadWriteLock;
 
@@ -72,6 +75,8 @@
    
    protected MessageStore ms;     
    
+   protected PersistenceManager pm;
+   
    protected TransactionRepository tr;
    
    protected String nodeId;
@@ -81,7 +86,11 @@
    
    //Map <condition, List <binding> >
    protected Map conditionMap;
-     
+   
+   protected FilterFactory filterFactory;
+   
+   protected QueuedExecutorPool pool;
+   
    public PostOfficeImpl()
    {      
    }
@@ -89,7 +98,9 @@
    public PostOfficeImpl(DataSource ds, TransactionManager tm, Properties sqlProperties,
                          boolean createTablesOnStartup,
                          String nodeId, String officeName, MessageStore ms,
-                         TransactionRepository tr)
+                         PersistenceManager pm,
+                         TransactionRepository tr, FilterFactory filterFactory,
+                         QueuedExecutorPool pool)
    {            
       super (ds, tm, sqlProperties, createTablesOnStartup);
       
@@ -105,7 +116,13 @@
       
       this.ms = ms;
       
+      this.pm = pm;
+      
       this.tr = tr;
+      
+      this.filterFactory = filterFactory;
+      
+      this.pool = pool;
    }
    
    // MessagingComponent implementation --------------------------------
@@ -124,9 +141,9 @@
      
    // PostOffice implementation ---------------------------------------        
          
-   public Binding bindQueue(String queueName, String condition, Filter filter, Queue queue) throws Exception
+   public Binding bindQueue(String condition, Queue queue) throws Exception
    {
-      if (queueName == null)
+      if (queue.getName() == null)
       {
          throw new IllegalArgumentException("Queue name is null");
       }
@@ -135,7 +152,7 @@
       {
          throw new IllegalArgumentException("Condition is null");
       }
-      
+       
       lock.writeLock().acquire();
 
       try
@@ -147,26 +164,19 @@
          
          if (nameMap != null)
          {
-            binding = (Binding)nameMap.get(queueName);
+            binding = (Binding)nameMap.get(queue.getName());
          }
          
          if (binding != null)
          {
-            throw new IllegalArgumentException("Binding already exists for name " + queueName);
+            throw new IllegalArgumentException("Binding already exists for name " + queue.getName());
          }
+                 
+         binding = new BindingImpl(this.nodeId, condition, queue); 
          
-         boolean durable = queue.isRecoverable();
-                    
-         binding = createBinding(nodeId, queueName, condition, filter,
-                                 queue.getChannelID(), durable);         
-         
-         binding.setQueue(queue);
-         
-         binding.activate();
-         
          addBinding(binding);
                
-         if (durable)
+         if (queue.isRecoverable())
          {
             //Need to write the binding to the db            
             insertBinding(binding);       
@@ -193,17 +203,14 @@
       {         
          Binding binding = removeBinding(this.nodeId, queueName);
       
-         if (binding.isDurable())
+         if (binding.getQueue().isRecoverable())
          {
             //Need to remove from db too
             
-            deleteBinding(binding.getQueueName());                        
+            deleteBinding(binding.getQueue().getName());                        
          }
          
-         if (binding.getQueue() != null)
-         {
-            binding.getQueue().removeAllReferences();
-         }
+         binding.getQueue().removeAllReferences();         
          
          return binding;     
       }
@@ -213,7 +220,7 @@
       }
    }   
    
-   public List listBindingsForCondition(String condition) throws Exception
+   public Collection listBindingsForCondition(String condition) throws Exception
    {
       if (condition == null)
       {
@@ -224,7 +231,7 @@
       
       try
       {
-         ConditionBindings cb = (ConditionBindings)conditionMap.get(condition);
+         Bindings cb = (Bindings)conditionMap.get(condition);
                   
          if (cb == null)
          {
@@ -232,9 +239,7 @@
          }
          else
          {
-            List list = cb.getAllBindings();                        
-            
-            return list;
+            return cb.getAllBindings();
          }
       }
       finally
@@ -294,15 +299,15 @@
                 
       try
       {                 
-         ConditionBindings cb = (ConditionBindings)conditionMap.get(condition);
+         Bindings bd = (Bindings)conditionMap.get(condition);
                              
-         if (cb != null)
+         if (bd != null)
          {            
             boolean startInternalTx = false;
             
             if (tx == null && ref.isReliable())
             {
-               if (cb.getDurableCount() > 1)
+               if (bd.getDurableCount() > 1)
                {
                   // When routing a persistent message without a transaction then we may need to start an 
                   // internal transaction in order to route it.
@@ -317,31 +322,28 @@
                tx = tr.createTransaction();
             }
                         
-            List bindings = cb.getAllBindings();
+            Collection bindings = bd.getAllBindings();
             
             Iterator iter = bindings.iterator();
             
             while (iter.hasNext())
             {
                Binding binding = (Binding)iter.next();
-                 
-               if (binding.isActive() && binding.getNodeId().equals(this.nodeId))
+               
+               //Sanity check
+               if (!binding.getNodeId().equals(this.nodeId))
                {
-                  //It's a local binding so we pass the message on to the subscription
-                  Queue queue = binding.getQueue();
-                  
-                  Filter filter = binding.getFilter();
-                  
-                  if (filter != null && filter.accept(ref))
-                  {
-                     Delivery del = queue.handle(null, ref, tx);
-                     
-                     if (del != null && del.isSelectorAccepted())
-                     {
-                        routed = true;
-                     }      
-                  }                  
-               }               
+                  throw new IllegalStateException("Local post office has foreign bindings!");
+               }
+                                
+               Queue queue = binding.getQueue();
+               
+               Delivery del = queue.handle(null, ref, tx);
+               
+               if (del != null && del.isSelectorAccepted())
+               {
+                  routed = true;
+               }                                                                     
             } 
             
             if (startInternalTx)
@@ -358,39 +360,98 @@
          lock.readLock().release();
       }
    } 
-     
-   // Protected -----------------------------------------------------
    
-   protected Binding createBinding(String nodeId, String queueName, String condition, Filter filter,
-                                   long channelId, boolean durable) throws Exception
-   {           
-      return new BindingImpl(nodeId, queueName, condition, filter,
-                             channelId, durable);   
+   public boolean isLocal()
+   {
+      return true;
    }
-   
+     
+   // Protected -----------------------------------------------------
+    
    protected void loadBindings() throws Exception
    {
       lock.writeLock().acquire();
       
+      Connection conn = null;
+      PreparedStatement ps  = null;
+      ResultSet rs = null;
+      TransactionWrapper wrap = new TransactionWrapper();
+       
       try
       {
-         List list = getBindings();
+         conn = ds.getConnection();
          
-         Iterator iter = list.iterator();
-         
-         while (iter.hasNext())
+         ps = conn.prepareStatement(getSQLStatement("LOAD_BINDINGS"));
+                 
+         ps.setString(1, this.officeName);
+
+         rs = ps.executeQuery();
+              
+         while (rs.next())
          {
-            Binding binding = (Binding)iter.next();
+            String nodeId = rs.getString(1);
             
-            addBinding(binding);              
+            String queueName = rs.getString(2);
+            
+            String condition = rs.getString(3);
+            
+            String selector = rs.getString(4);
+            
+            if (rs.wasNull())
+            {
+               selector = null;
+            }
+            
+            long channelId = rs.getLong(5);
+                                             
+            Binding binding = this.createBinding(nodeId, condition, queueName, channelId, selector, true);
+            
+            addBinding(binding);
          }
       }
       finally
       {
          lock.writeLock().release();
+         
+         if (rs != null)
+         {
+            rs.close();
+         }
+         if (ps != null)
+         {
+            ps.close();
+         }
+         if (conn != null)
+         {
+            conn.close();
+         }
+         wrap.end();
       }
    }
+   
+   protected Binding createBinding(String nodeId, String condition, String queueName, long channelId, String filterString, boolean durable) throws Exception
+   {      
+      
+      Filter filter = filterFactory.createFilter(filterString);
+      
+      Queue queue;
+      if (nodeId.equals(this.nodeId))
+      {
+         QueuedExecutor executor = (QueuedExecutor)pool.get();
          
+         queue = new LocalClusteredQueue(nodeId, queueName, channelId, ms, pm, true,
+                                         true, executor, filter);
+      }
+      else
+      {
+         throw new IllegalStateException("This is a non clustered post office - should not have bindings from different nodes!");
+      }
+      
+      Binding binding = new BindingImpl(nodeId, condition, queue);
+      
+      return binding;
+   }
+         
    protected void insertBinding(Binding binding) throws Exception
    {
       Connection conn = null;
@@ -403,11 +464,11 @@
          
          ps = conn.prepareStatement(getSQLStatement("INSERT_BINDING"));
          
-         String filterString = binding.getFilter() == null ? null : binding.getFilter().getFilterString();
+         String filterString = binding.getQueue().getFilter() == null ? null : binding.getQueue().getFilter().getFilterString();
                   
          ps.setString(1, this.officeName);
          ps.setString(2, this.nodeId);
-         ps.setString(3, binding.getQueueName());
+         ps.setString(3, binding.getQueue().getName());
          ps.setString(4, binding.getCondition());         
          if (filterString != null)
          {
@@ -417,9 +478,9 @@
          {
             ps.setNull(5, Types.VARCHAR);
          }
-         ps.setLong(6, binding.getChannelId());
+         ps.setLong(6, binding.getQueue().getChannelID());
 
-         ps.executeUpdate();;
+         ps.executeUpdate();
       }
       finally
       {
@@ -469,82 +530,6 @@
       }     
    }
 
-   /*
-    * 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);
-            
-            if (rs.wasNull())
-            {
-               selector = null;
-            }
-            
-            long channelId = rs.getLong(5);
-              
-            //We don't load the actual queue - this is because we don't know the paging params until
-            //activation time
-                    
-            //TODO we need to generalise selector creation
-            Selector filter = null;
-            if (selector != null)
-            {
-               filter = new Selector(selector);
-            }
-            
-            Binding binding = createBinding(nodeId, queueName, condition, filter, 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());
@@ -556,15 +541,15 @@
          nameMaps.put(binding.getNodeId(), nameMap);
       }
       
-      nameMap.put(binding.getQueueName(), binding);
+      nameMap.put(binding.getQueue().getName(), binding);
       
       String condition = binding.getCondition();
             
-      ConditionBindings bindings = (ConditionBindings)conditionMap.get(condition);
+      Bindings bindings = (Bindings)conditionMap.get(condition);
       
       if (bindings == null)
       {
-         bindings = new ConditionBindings(this.nodeId);
+         bindings = createBindings();
          
          conditionMap.put(condition, bindings);
       }
@@ -603,7 +588,7 @@
          nameMaps.remove(nodeId);
       }
                   
-      ConditionBindings bindings = (ConditionBindings)conditionMap.get(binding.getCondition());
+      Bindings bindings = (Bindings)conditionMap.get(binding.getCondition());
       
       if (bindings == null)
       {
@@ -625,6 +610,11 @@
       return binding;
    }
    
+   protected Bindings createBindings()
+   {
+      return new BindingsImpl();
+   }
+   
    protected Map getDefaultDMLStatements()
    {                
       Map map = new HashMap();
@@ -651,5 +641,6 @@
    
    // Private -------------------------------------------------------             
                  
-   // Inner classes -------------------------------------------------            
+   // Inner classes ------------------------------------------------- 
+      
 }

Modified: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/BasicRedistributionPolicy.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/BasicRedistributionPolicy.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/BasicRedistributionPolicy.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -24,6 +24,8 @@
 import java.util.Iterator;
 import java.util.List;
 
+import org.jboss.messaging.core.plugin.postoffice.Binding;
+
 /**
  * A BasicRedistributonPolicy
  *
@@ -48,11 +50,11 @@
    {
       Iterator iter = bindings.iterator();
       
-      ClusteredBinding localBinding = null;
+      Binding localBinding = null;
       
       while (iter.hasNext())
       {
-         ClusteredBinding binding = (ClusteredBinding)iter.next();
+         Binding binding = (Binding)iter.next();
          
          if (binding.getNodeId().equals(localNodeId))
          {
@@ -67,7 +69,9 @@
          return null;
       }
       
-      if (localBinding.getConsumptionRate() == 0 && localBinding.getMessageCount() > 0)
+      ClusteredQueue queue = (ClusteredQueue)localBinding.getQueue();
+      
+      if (queue.getGrowthRate() == 0 && queue.getMessageCount() > 0)
       {
          //No consumers on the queue - the messages are stranded
          //We should consider moving them somewhere else
@@ -78,17 +82,21 @@
          
          double maxRate = 0;
          
-         ClusteredBinding maxRateBinding = null;
+         Binding maxRateBinding = null;
          
          while (iter.hasNext())
          {
-            ClusteredBinding binding = (ClusteredBinding)iter.next();
+            Binding binding = (Binding)iter.next();
             
+            ClusteredQueue theQueue = (ClusteredQueue)binding.getQueue();
+            
             if (!binding.getNodeId().equals(localNodeId))
             {
-               if (binding.getConsumptionRate() > maxRate)
+               double rate = theQueue.getGrowthRate();
+               
+               if (rate > maxRate)
                {
-                  maxRate = binding.getConsumptionRate();
+                  maxRate = rate;
                   
                   maxRateBinding = binding;
                }
@@ -100,9 +108,9 @@
             //Move messages to this node
             
             //How many should we move?
-            int numberToMove = Math.min(MAX_MESSAGES_TO_MOVE, localBinding.getMessageCount());     
+            int numberToMove = Math.min(MAX_MESSAGES_TO_MOVE, queue.getMessageCount());     
             
-            return new RedistributionOrder(numberToMove, localBinding.getQueueName(), maxRateBinding.getNodeId());
+            return new RedistributionOrder(numberToMove, queue, maxRateBinding.getNodeId());
          }
       }
       

Modified: 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-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/BindRequest.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -24,8 +24,6 @@
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 
-import org.jboss.messaging.util.StreamUtils;
-
 /**
  * A BindRequest
  *
@@ -37,18 +35,8 @@
  */
 class BindRequest extends ClusterRequest
 {
-   private String nodeId;   
+   private BindingInfo bindingInfo;   
    
-   private String queueName;   
-   
-   private String condition;   
-   
-   private String filterString; 
-   
-   private long channelId;   
-   
-   private boolean durable;
-   
    static final byte TYPE = 1;
    
    BindRequest()
@@ -58,23 +46,14 @@
    BindRequest(String nodeId, String queueName, String condition, String filterString,
                long channelId, boolean durable)
    {
-      this.nodeId = nodeId;
-      
-      this.queueName = queueName;
-      
-      this.condition = condition;
-      
-      this.filterString = filterString;
-      
-      this.channelId = channelId;
-      
-      this.durable = durable;
+      bindingInfo = new BindingInfo(nodeId, queueName, condition, filterString,
+                                    channelId, durable);
    }
 
    public void execute(PostOfficeInternal office) throws Exception
    {
-      office.addBindingFromCluster(nodeId, queueName, condition,
-                                   filterString, channelId, durable);
+      office.addBindingFromCluster(bindingInfo.getNodeId(), bindingInfo.getQueueName(), bindingInfo.getCondition(),
+                                   bindingInfo.getFilterString(), bindingInfo.getChannelId(), bindingInfo.isDurable());
       
    }
    
@@ -85,31 +64,13 @@
 
    public void read(DataInputStream in) throws Exception
    {
-      nodeId = in.readUTF();
+      bindingInfo = new BindingInfo();
       
-      queueName = in.readUTF();
-      
-      condition = in.readUTF();
-      
-      filterString = (String)StreamUtils.readObject(in, false);   
-      
-      channelId = in.readLong();
-      
-      durable = in.readBoolean();
+      bindingInfo.read(in);
    }
 
    public void write(DataOutputStream out) throws Exception
    {
-      out.writeUTF(nodeId);
-      
-      out.writeUTF(queueName);
-      
-      out.writeUTF(condition);
-      
-      StreamUtils.writeObject(out, filterString, false, false);
-      
-      out.writeLong(channelId);
-      
-      out.writeBoolean(durable);
+      bindingInfo.write(out);
    }
 }

Added: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/BindingInfo.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/BindingInfo.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/BindingInfo.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -0,0 +1,139 @@
+/*
+ * 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.DataInputStream;
+import java.io.DataOutputStream;
+
+import org.jboss.messaging.util.StreamUtils;
+import org.jboss.messaging.util.Streamable;
+
+/**
+ * A BindingInfo
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class BindingInfo implements Streamable
+{
+   private String nodeId;   
+   
+   private String queueName;   
+   
+   private String condition;   
+   
+   private String filterString; 
+   
+   private long channelId;   
+   
+   private boolean durable;
+   
+   BindingInfo()
+   {      
+   }
+   
+   BindingInfo(String nodeId, String queueName, String condition, String filterString,
+               long channelId, boolean durable)
+   {
+      this.nodeId = nodeId;
+      
+      this.queueName = queueName;
+      
+      this.condition = condition;
+      
+      this.filterString = filterString;
+      
+      this.channelId = channelId;
+      
+      this.durable = durable;
+   }
+
+   public void execute(PostOfficeInternal office) throws Exception
+   {
+      office.addBindingFromCluster(nodeId, queueName, condition,
+                                   filterString, channelId, durable);
+      
+   }
+   
+   public void read(DataInputStream in) throws Exception
+   {
+      nodeId = in.readUTF();
+      
+      queueName = in.readUTF();
+      
+      condition = in.readUTF();
+      
+      filterString = (String)StreamUtils.readObject(in, false);   
+      
+      channelId = in.readLong();
+      
+      durable = in.readBoolean();
+   }
+
+   public void write(DataOutputStream out) throws Exception
+   {
+      out.writeUTF(nodeId);
+      
+      out.writeUTF(queueName);
+      
+      out.writeUTF(condition);
+      
+      StreamUtils.writeObject(out, filterString, false, false);
+      
+      out.writeLong(channelId);
+      
+      out.writeBoolean(durable);
+   }
+
+   public long getChannelId()
+   {
+      return channelId;
+   }
+
+   public String getCondition()
+   {
+      return condition;
+   }
+
+   public boolean isDurable()
+   {
+      return durable;
+   }
+
+   public String getFilterString()
+   {
+      return filterString;
+   }
+
+   public String getNodeId()
+   {
+      return nodeId;
+   }
+
+   public String getQueueName()
+   {
+      return queueName;
+   }
+}

Modified: 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-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/CastMessagesCallback.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -62,6 +62,8 @@
 class CastMessagesCallback implements TxCallback
 {           
    private static final Logger log = Logger.getLogger(CastMessagesCallback.class);
+   
+   public static final String KEY = "cast";
       
    private List persistent;
    

Added: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusterRouter.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusterRouter.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusterRouter.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -0,0 +1,145 @@
+/*
+ * 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.Iterator;
+import java.util.List;
+
+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.Router;
+import org.jboss.messaging.core.tx.Transaction;
+
+/**
+ * A ClusterRouter
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class ClusterRouter implements Router
+{
+   private List queues;
+   
+   private ClusteredQueue localQueue;
+   
+   public ClusterRouter()
+   {
+      queues = new ArrayList();
+   }
+
+   public boolean add(Receiver receiver)
+   {
+      ClusteredQueue queue = (ClusteredQueue)receiver;
+      
+      if (queue.isLocal())
+      {
+         if (localQueue != null)
+         {
+            throw new IllegalStateException("Already has local queue");
+         }
+         localQueue = queue;
+      }
+      
+      queues.add(queue);      
+      
+      return true;
+   }
+
+   public void clear()
+   {
+      queues.clear();
+      localQueue = null;
+   }
+
+   public boolean contains(Receiver queue)
+   {
+      return queues.contains(queue);
+   }
+
+   public Iterator iterator()
+   {
+      return queues.iterator();
+   }
+
+   public boolean remove(Receiver queue)
+   {
+      if (queues.remove(queue))
+      {
+         if (localQueue == queue)
+         {
+            localQueue = null;
+         }
+         return true;
+      }
+      else
+      {
+         return false;
+      }
+   }
+
+   public Delivery handle(DeliveryObserver observer, MessageReference reference, Transaction tx)
+   {
+      //Favour the local queue
+      
+      if (localQueue != null)
+      {
+         Delivery del = localQueue.handle(observer, reference, tx);
+         
+         if (del != null && del.isSelectorAccepted())
+         {
+            return del;
+         }
+      }
+      
+      //TODO make this round robin
+      
+      Iterator iter = queues.iterator();
+      
+      while (iter.hasNext())
+      {
+         ClusteredQueue queue = (ClusteredQueue)iter.next();
+         
+         if (!queue.isLocal())
+         {
+            Delivery del = queue.handle(observer, reference, tx);
+            
+            if (del != null && del.isSelectorAccepted())
+            {
+               return del;
+            }
+         }
+      }
+      
+      return null;      
+   }
+   
+   public List getQueues()
+   {
+      return queues;
+   }
+}

Deleted: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredBinding.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredBinding.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredBinding.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -1,46 +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.postoffice.cluster;
-
-import org.jboss.messaging.core.plugin.postoffice.Binding;
-import org.jboss.messaging.util.Streamable;
-
-/**
- * 
- * A ClusteredBinding
- *
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision: 1.1 $</tt>
- *
- * $Id$
- *
- */
-public interface ClusteredBinding extends Binding, Streamable
-{
-   double getConsumptionRate();
-   
-   int getMessageCount();
-   
-   void setConsumptionRate(double rate);
-   
-   void setMessageCount(int count);
-}

Deleted: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredBindingImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredBindingImpl.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredBindingImpl.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -1,92 +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.postoffice.cluster;
-
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-
-import org.jboss.messaging.core.Filter;
-import org.jboss.messaging.core.plugin.postoffice.BindingImpl;
-
-/**
- * 
- * A ClusteredBindingImpl
- *
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision: 1.1 $</tt>
- *
- * $Id$
- *
- */
-public class ClusteredBindingImpl extends BindingImpl implements ClusteredBinding
-{
-   private double consumptionRate;
-   
-   private int messageCount;
-   
-   public ClusteredBindingImpl()
-   {
-   }
-
-   public ClusteredBindingImpl(String nodeId, String queueName, String condition, Filter filter, long channelId, boolean durable)
-   {
-      super(nodeId, queueName, condition, filter, channelId, durable);
-   }
-
-   public double getConsumptionRate()
-   {
-      return consumptionRate;
-   }
-
-   public int getMessageCount()
-   {
-      return messageCount;
-   }
-
-   public void setConsumptionRate(double consumptionRate)
-   {
-      this.consumptionRate = consumptionRate;
-   }
-
-   public void setMessageCount(int messageCount)
-   {
-      this.messageCount = messageCount;
-   }
-
-   public void read(DataInputStream in) throws Exception
-   {
-      super.read(in);
-      
-      consumptionRate = in.readDouble();
-      
-      messageCount = in.readInt();
-   }
-
-   public void write(DataOutputStream out) throws Exception
-   {
-      super.write(out);
-      
-      out.writeDouble(consumptionRate);
-      
-      out.writeInt(messageCount);
-   }
-}

Added: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredBindings.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredBindings.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredBindings.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -0,0 +1,42 @@
+/*
+ * 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.Collection;
+
+import org.jboss.messaging.core.plugin.postoffice.Bindings;
+
+/**
+ * A ClusteredBindings
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public interface ClusteredBindings extends Bindings
+{
+   Collection getRouters();
+   
+   int getLocalDurableCount();
+}

Added: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredBindingsImpl.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredBindingsImpl.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredBindingsImpl.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -0,0 +1,126 @@
+/*
+ * 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.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.jboss.messaging.core.plugin.postoffice.Binding;
+import org.jboss.messaging.core.plugin.postoffice.BindingsImpl;
+
+
+/**
+ * 
+ * A ClusteredBindings
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class ClusteredBindingsImpl extends BindingsImpl implements ClusteredBindings
+{
+   // Map <name, router>
+   private Map nameMap;
+   
+   private String thisNode;
+   
+   private int localDurableCount;
+   
+   public ClusteredBindingsImpl(String thisNode)
+   {
+      super();
+      
+      nameMap = new HashMap();
+      
+      this.thisNode = thisNode;
+   }
+   
+   public void addBinding(Binding binding)
+   {
+      super.addBinding(binding);
+               
+      ClusterRouter router = (ClusterRouter)nameMap.get(binding.getQueue().getName());
+      
+      if (router == null)
+      {
+         router = new ClusterRouter();
+         
+         nameMap.put(binding.getQueue().getName(), router);
+      }
+      
+      router.add(binding.getQueue());      
+      
+      if (binding.getNodeId().equals(thisNode) && binding.getQueue().isRecoverable())
+      {
+         localDurableCount++;
+      }      
+   }
+   
+   public boolean removeBinding(Binding binding)
+   {
+      boolean removed = super.removeBinding(binding);
+      
+      if (!removed)
+      {
+         return false;
+      }
+           
+      ClusterRouter router = (ClusterRouter)nameMap.get(binding.getQueue().getName());
+      
+      if (router == null)
+      {
+         throw new IllegalStateException("Cannot find router in name map");
+      }
+      
+      removed = router.remove(binding.getQueue());
+      
+      if (!removed)
+      {
+         throw new IllegalStateException("Cannot find binding in list");
+      }
+      
+      if (!router.iterator().hasNext())
+      {
+         nameMap.remove(binding.getQueue().getName());
+      }
+      
+      if (binding.getNodeId().equals(thisNode) && binding.getQueue().isRecoverable())
+      {
+         localDurableCount--;
+      }      
+
+      return true;
+   }
+   
+   public int getLocalDurableCount()
+   {
+      return localDurableCount;
+   }
+   
+   public Collection getRouters()
+   {
+      return nameMap.values();
+   }
+}

Modified: 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-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredPostOfficeImpl.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -36,17 +36,20 @@
 import javax.sql.DataSource;
 import javax.transaction.TransactionManager;
 
-import org.jboss.jms.selector.Selector;
+import org.jboss.jms.server.QueuedExecutorPool;
 import org.jboss.logging.Logger;
 import org.jboss.messaging.core.Delivery;
 import org.jboss.messaging.core.Filter;
+import org.jboss.messaging.core.FilterFactory;
 import org.jboss.messaging.core.MessageReference;
-import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.Queue;
+import org.jboss.messaging.core.Router;
 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.Binding;
-import org.jboss.messaging.core.plugin.postoffice.ConditionBindings;
+import org.jboss.messaging.core.plugin.postoffice.BindingImpl;
+import org.jboss.messaging.core.plugin.postoffice.Bindings;
 import org.jboss.messaging.core.plugin.postoffice.PostOfficeImpl;
 import org.jboss.messaging.core.tx.Transaction;
 import org.jboss.messaging.core.tx.TransactionRepository;
@@ -64,6 +67,8 @@
 import org.jgroups.blocks.RequestHandler;
 import org.w3c.dom.Element;
 
+import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
+
 /**
  * 
  * A ClusteredPostOfficeImpl
@@ -77,6 +82,8 @@
 public class ClusteredPostOfficeImpl extends PostOfficeImpl implements ClusteredPostOffice, PostOfficeInternal
 {
    private static final Logger log = Logger.getLogger(ClusteredPostOfficeImpl.class);
+   
+   private static final int STATS_DIFFERENCE_MARGIN_PERCENT = 10;   
                        
    private Channel syncChannel;
    
@@ -105,8 +112,6 @@
    
    private Map holdingArea;
    
-   private PersistenceManager pm;
-   
    private Element syncChannelConfigE;
    
    private Element asyncChannelConfigE;
@@ -119,8 +124,6 @@
    
    private long castTimeout;
    
-   private RoutingPolicy routingPolicy;
-   
    private RedistributionPolicy redistributionPolicy;
    
    private MessageRedistributor redistributor;
@@ -143,21 +146,21 @@
     * 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,
-                              RoutingPolicy routingPolicy,
-                              RedistributionPolicy redistributionPolicy,
-                              long redistributePeriod) throws Exception
+            boolean createTablesOnStartup,
+            String nodeId, String officeName, MessageStore ms,
+            PersistenceManager pm,
+            TransactionRepository tr,
+            FilterFactory filterFactory,
+            QueuedExecutorPool pool,                              
+            String groupName,
+            Element syncChannelConfig,
+            Element asyncChannelConfig,
+            long stateTimeout, long castTimeout,
+            RedistributionPolicy redistributionPolicy,
+            long redistributePeriod) throws Exception
    {            
       this(ds, tm, sqlProperties, createTablesOnStartup, nodeId, officeName, ms,
-           groupName, tr, pm, stateTimeout, castTimeout, routingPolicy, redistributionPolicy,
-           redistributePeriod);
+           pm, tr, filterFactory, pool, groupName, stateTimeout, castTimeout, redistributionPolicy, redistributePeriod);
       
       this.syncChannelConfigE = syncChannelConfig;      
       this.asyncChannelConfigE = asyncChannelConfig;     
@@ -169,18 +172,19 @@
    public ClusteredPostOfficeImpl(DataSource ds, TransactionManager tm, Properties sqlProperties,
                               boolean createTablesOnStartup,
                               String nodeId, String officeName, MessageStore ms,
+                              PersistenceManager pm,
+                              TransactionRepository tr,
+                              FilterFactory filterFactory,
+                              QueuedExecutorPool pool,                              
                               String groupName,
                               String syncChannelConfig,
                               String asyncChannelConfig,
-                              TransactionRepository tr,
-                              PersistenceManager pm,
                               long stateTimeout, long castTimeout,
-                              RoutingPolicy routingPolicy,
                               RedistributionPolicy redistributionPolicy,
                               long redistributePeriod) throws Exception
    {            
       this(ds, tm, sqlProperties, createTablesOnStartup, nodeId, officeName, ms,
-           groupName, tr, pm, stateTimeout, castTimeout, routingPolicy, redistributionPolicy, redistributePeriod);
+           pm, tr, filterFactory, pool, groupName, stateTimeout, castTimeout, redistributionPolicy, redistributePeriod);
 
       this.syncChannelConfigS = syncChannelConfig;      
       this.asyncChannelConfigS = asyncChannelConfig;     
@@ -189,16 +193,18 @@
    private ClusteredPostOfficeImpl(DataSource ds, TransactionManager tm, Properties sqlProperties,
                                boolean createTablesOnStartup,
                                String nodeId, String officeName, MessageStore ms,
-                               String groupName,
+                               PersistenceManager pm,                               
                                TransactionRepository tr,
-                               PersistenceManager pm,
-                               long stateTimeout, long castTimeout,
-                               RoutingPolicy routingPolicy,
+                               FilterFactory filterFactory,
+                               QueuedExecutorPool pool,
+                               String groupName,
+                               long stateTimeout, long castTimeout,                             
                                RedistributionPolicy redistributionPolicy,
                                long redistributePeriod)
    {
-      super (ds, tm, sqlProperties, createTablesOnStartup, nodeId, officeName, ms, tr);
-       
+      super (ds, tm, sqlProperties, createTablesOnStartup, nodeId, officeName, ms, pm, tr, filterFactory,
+             pool);
+             
       this.pm = pm;
       
       this.groupName = groupName;
@@ -207,8 +213,6 @@
       
       this.castTimeout = castTimeout;
       
-      this.routingPolicy = routingPolicy;
-      
       this.redistributionPolicy = redistributionPolicy;
       
       this.redistributePeriod = redistributePeriod;
@@ -278,25 +282,30 @@
    }  
    
    // PostOffice implementation ---------------------------------------        
-   
-   public ClusteredBinding bindClusteredQueue(String queueName, String condition, Filter filter, ClusteredQueue queue) throws Exception
+      
+   public Binding bindClusteredQueue(String condition, LocalClusteredQueue queue) throws Exception
    {           
-      ClusteredBinding binding = (ClusteredBinding)super.bindQueue(queueName, condition, filter, queue);
+      if (!queue.getNodeId().equals(this.nodeId))
+      {
+         throw new IllegalArgumentException("Queue node id does not match office node id");
+      }
       
+      Binding binding = (Binding)super.bindQueue(condition, queue);
+      
       boolean durable = queue.isRecoverable();
       
       BindRequest request =
-         new BindRequest(nodeId, queueName, condition, filter == null ? null : filter.getFilterString(),
-                         binding.getChannelId(), durable);
+         new BindRequest(nodeId, queue.getName(), condition, queue.getFilter() == null ? null : queue.getFilter().getFilterString(),
+                         binding.getQueue().getChannelID(), durable);
       
       syncSendRequest(request);
       
       return binding;
    }
    
-   public ClusteredBinding unbindClusteredQueue(String queueName) throws Throwable
+   public Binding unbindClusteredQueue(String queueName) throws Throwable
    {
-      ClusteredBinding binding = (ClusteredBinding)super.unbindQueue(queueName);
+      Binding binding = (Binding)super.unbindQueue(queueName);
       
       UnbindRequest request = new UnbindRequest(nodeId, queueName);
       
@@ -332,7 +341,7 @@
       
       try
       {      
-         ConditionBindings cb = (ConditionBindings)conditionMap.get(condition);
+         ClusteredBindings cb = (ClusteredBindings)conditionMap.get(condition);
          
          boolean startInternalTx = false;
          
@@ -348,7 +357,7 @@
                   // We need to do this if there is any other than a single local durable subscription
                   startInternalTx = true;
                }
-            }
+            }                        
             
             if (startInternalTx)
             {
@@ -359,91 +368,44 @@
             //1) No transaction specified in params and reference is unreliable
             //2) No transaction specified in params and reference is reliable and there is only one
             //   or less local durable subscription
-         
-            Collection bindingLists = cb.getBindingsByName();
-
-            Iterator iter = bindingLists.iterator();
-            
+                     
             int numberRemote = 0;
             
             Map queueNameNodeIdMap = null;
             
-            
+            Collection routers = cb.getRouters();
+
+            Iterator iter = routers.iterator();
+                     
             while (iter.hasNext())
             {
-               //Each list is the list of bindings which have the same queue name
-               List bindings = (List)iter.next();
+               Router router = (Router)iter.next();
                
-               //We may have more than one binding with the same queue name on different nodes in the
-               //following situations:
-               //1) When a point to point queue has been deployed across the cluster
-               //2) When a durable subscription has been created on multiple nodes to implement
-               // shared durable subscriptions.
-               //In both of these cases we only want one of the queues to receive the message, we choose which 
-               //one by asking the routing policy
-               Binding binding;
+               Delivery del = router.handle(null, ref, tx);
                
-               if (bindings.size() == 1)
+               if (del != null && del.isSelectorAccepted())
                {
-                  binding = (Binding)bindings.get(0);
+                  routed = true;
                }
-               else if (bindings.size() > 1)
+               
+               ClusteredQueue queue = (ClusteredQueue)del.getObserver();
+               
+               if (!queue.isLocal())
                {
-                  binding = routingPolicy.choose(bindings); 
+                  //We need to cast the message
+                  numberRemote++;
                   
                   if (queueNameNodeIdMap == null)
                   {
                      queueNameNodeIdMap = new HashMap();
-                  }
-                  
-                  if (!binding.getNodeId().equals(this.nodeId))
-                  {
-                     //Chose a remote node
-                     //We add the node id to the map against the name
-                     //This is used on receipt to work out if a particular queue should
-                     //accept the message, when multicasted
-                     queueNameNodeIdMap.put(binding.getQueueName(), binding.getNodeId());
-                  }
-               }
-               else
-               {
-                  throw new IllegalStateException("No bindings in list!");
-               }
-               
-               Filter filter = binding.getFilter();
-                               
-               if (filter != null && filter.accept(ref))
-               {
-                  if (binding.getNodeId().equals(this.nodeId))
-                  {
-                     //It's a local binding so we pass the message on to the queue
-                     Queue queue = binding.getQueue();
-                  
-                     Delivery del = queue.handle(null, ref, tx);    
                      
-                     if (del != null && del.isSelectorAccepted())
-                     {
-                        routed = true;
-                     }  
+                     //We add an entry to the map so that on the receiving node we can work out which
+                     //queue instance will receive the message
+                     queueNameNodeIdMap.put(queue.getName(), queue.getNodeId());
                   }
-                  else
-                  {
-                     //It's a binding on a different office instance on the cluster
-                     numberRemote++;                     
-                     
-                     if (ref.isReliable() && binding.isDurable())
-                     {
-                        //Insert the reference into the database
-                        
-                        //TODO perhaps we should do this via a stub queue class
-                        pm.addReference(binding.getChannelId(), ref, tx);
-                     }
-                     
-                     routed = true;
-                  }  
-               }                                                              
+               }
             }
-                                    
+            
             //Now we've sent the message to any local queues, we might also need
             //to send the message to the other office instances on the cluster if there are
             //queues on those nodes that need to receive the message
@@ -475,7 +437,7 @@
                   callback.addMessage(condition, ref.getMessage(), queueNameNodeIdMap);    
                }
             }
-            
+                                                
             if (startInternalTx)
             {               
                // TODO - do we need to rollback if an exception is thrown??
@@ -492,6 +454,11 @@
       return routed; 
    }
    
+   public boolean isLocal()
+   {
+      return false;
+   }
+   
    // PostOfficeInternal implementation ------------------------------------------------------------------
    
    /*
@@ -526,12 +493,9 @@
          {
             throw new IllegalArgumentException(this.nodeId + "Binding already exists for node Id " + nodeId + " queue name " + queueName);
          }
+            
+         binding = this.createBinding(nodeId, condition, queueName, channelID, filterString, durable);
          
-         binding = new ClusteredBindingImpl(nodeId, queueName, condition, new Selector(filterString),
-                                           channelID, durable); 
-         
-         binding.activate();
-         
          addBinding(binding);         
       }
       finally
@@ -590,7 +554,7 @@
             throw new IllegalStateException("Cannot find binding for queue name " + queueName);
          }
          
-         ClusteredQueue queue = (ClusteredQueue)binding.getQueue();
+         LocalClusteredQueue queue = (LocalClusteredQueue)binding.getQueue();
          
          Iterator iter = messages.iterator();
          
@@ -634,48 +598,45 @@
          ref = ms.reference(message);
               
          // We route on the condition
-         ConditionBindings cb = (ConditionBindings)conditionMap.get(routingKey);
+         ClusteredBindingsImpl cb = (ClusteredBindingsImpl)conditionMap.get(routingKey);
       
          if (cb != null)
          {                                
-            List bindings = cb.getAllBindings();
+            Collection bindings = cb.getAllBindings();
             
             Iterator iter = bindings.iterator();
             
             while (iter.hasNext())
             {
                Binding binding = (Binding)iter.next();
-                                             
-               if (binding.isActive())
-               {            
-                  if (binding.getNodeId().equals(this.nodeId))
-                  {  
-                     boolean handle = true;
+                                                        
+               if (binding.getNodeId().equals(this.nodeId))
+               {  
+                  boolean handle = true;
+                  
+                  if (queueNameNodeIdMap != null)
+                  {
+                     String desiredNodeId = (String)queueNameNodeIdMap.get(binding.getQueue().getName());
                      
-                     if (queueNameNodeIdMap != null)
-                     {
-                        String desiredNodeId = (String)queueNameNodeIdMap.get(binding.getQueueName());
-                        
-                        //When there are more than one queues with the same name across the cluster we only
-                        //want to chose one of them
-                        
-                        if (desiredNodeId != null)
-                        {
-                           handle = desiredNodeId.equals(nodeId);
-                        }
-                     }
+                     //When there are more than one queues with the same name across the cluster we only
+                     //want to chose one of them
                      
-                     if (handle)
+                     if (desiredNodeId != null)
                      {
-                        //It's a local binding so we pass the message on to the subscription
-                        ClusteredQueue queue = (ClusteredQueue)binding.getQueue();
-                     
-                        //TODO instead of adding a new method on the channel
-                        //we should set a header and use the same method
-                        queue.handleFromCluster(null, ref, null);
+                        handle = desiredNodeId.equals(nodeId);
                      }
-                  }                               
-               }
+                  }
+                  
+                  if (handle)
+                  {
+                     //It's a local binding so we pass the message on to the subscription
+                     LocalClusteredQueue queue = (LocalClusteredQueue)binding.getQueue();
+                  
+                     //TODO instead of adding a new method on the channel
+                     //we should set a header and use the same method
+                     queue.handleFromCluster(null, ref, null);
+                  }
+               }                                              
             }                          
          }
       }
@@ -807,25 +768,22 @@
          
          while (iter.hasNext())
          {
-            ConditionBindings cb = (ConditionBindings)iter.next();
+            ClusteredBindings cb = (ClusteredBindings)iter.next();
             
-            Collection nameLists = cb.getBindingsByName();
+            Collection routers = cb.getRouters();
             
-            Iterator iter2 = nameLists.iterator();
+            Iterator iter2 = routers.iterator();
             
             while (iter2.hasNext())
             {
-               List bindings = (List)iter2.next();        
+               ClusterRouter router = (ClusterRouter)iter2.next();        
             
-               if (bindings.size() > 1)
+               RedistributionOrder order = redistributionPolicy.calculate(router.getQueues());
+               
+               if (order != null)
                {
-                  RedistributionOrder order = redistributionPolicy.calculate(bindings);
-                  
-                  if (order != null)
-                  {
-                     moveMessages(order.getQueueName(), order.getDestinationNodeId(), order.getNumberOfMessages());
-                  }
-               }
+                  moveMessages(order.getQueue(), order.getDestinationNodeId(), order.getNumberOfMessages());
+               }               
             }
          }
       }
@@ -852,35 +810,32 @@
                      
             while (iter.hasNext())
             {
-               ClusteredBinding bb = (ClusteredBinding)iter.next();
+               Binding bb = (Binding)iter.next();
                
-               if (bb.isActive())
-               {                  
-                  ClusteredQueue q = (ClusteredQueue)bb.getQueue();
-                  
+               LocalClusteredQueue q = (LocalClusteredQueue)bb.getQueue();
+                             
+               if (q.isActive())
+               {                                    
                   //We don't bother sending the stat if there is less than STATS_DIFFERENCE_MARGIN_PERCENT % difference
                   
                   double newRate = q.getGrowthRate();
                   
                   int newMessageCount = q.messageCount();
                   
-                  boolean sendStats = decideToSendStats(bb.getConsumptionRate(), newRate);
+                  boolean sendStats = decideToSendStats(q.getGrowthRate(), newRate);
                   
                   if (!sendStats)
                   {
-                     sendStats = decideToSendStats(bb.getMessageCount(), newMessageCount);
+                     sendStats = decideToSendStats(q.getMessageCount(), newMessageCount);
                   }
                   
                   if (sendStats)
                   {
-                     bb.setConsumptionRate(newRate);
-                     bb.setMessageCount(newMessageCount);
-                     
                      if (stats == null)
                      {
                         stats = new ArrayList();
                      }
-                     QueueStats qs = new QueueStats(bb.getQueueName(), newRate, newMessageCount);
+                     QueueStats qs = new QueueStats(bb.getQueue().getName(), newRate, newMessageCount);
                      
                      stats.add(qs);
                   } 
@@ -901,31 +856,6 @@
       }
    }
    
-   private boolean decideToSendStats(double oldValue, double newValue)
-   {
-      boolean sendStats = false;
-      
-      if (oldValue != 0)
-      {         
-         int percentChange = (int)(100 * (oldValue - newValue) / oldValue);
-         
-         if (Math.abs(percentChange) >= STATS_DIFFERENCE_MARGIN_PERCENT)
-         {
-            sendStats = true;
-         }
-      }
-      else
-      {
-         if (newValue != 0)
-         {
-            sendStats = true;
-         }
-      }
-      return sendStats;
-   }
-   
-   private static final int STATS_DIFFERENCE_MARGIN_PERCENT = 10;
-   
    public void updateQueueStats(String nodeId, List stats) throws Exception
    {
       lock.writeLock().acquire();
@@ -945,16 +875,16 @@
          {
             QueueStats st = (QueueStats)iter.next();
             
-            ClusteredBinding bb = (ClusteredBinding)nameMap.get(st.getQueueName());
+            Binding bb = (Binding)nameMap.get(st.getQueueName());
             
             if (bb == null)
             {
                throw new IllegalStateException("Cannot find binding for queue name: " + st.getQueueName());
             }
             
-            bb.setConsumptionRate(st.getConsumptionRate());
+            RemoteQueueStub stub = (RemoteQueueStub)bb.getQueue();
             
-            bb.setMessageCount(st.getMessageCount());
+            stub.setStats(st.getMessageCount(), st.getGrowthRate());
          }         
       }
       finally
@@ -962,20 +892,39 @@
          lock.writeLock().release();      
       }
    }
-          
    
-   
+   private boolean decideToSendStats(double oldValue, double newValue)
+   {
+      boolean sendStats = false;
+      
+      if (oldValue != 0)
+      {         
+         int percentChange = (int)(100 * (oldValue - newValue) / oldValue);
+         
+         if (Math.abs(percentChange) >= STATS_DIFFERENCE_MARGIN_PERCENT)
+         {
+            sendStats = true;
+         }
+      }
+      else
+      {
+         if (newValue != 0)
+         {
+            sendStats = true;
+         }
+      }
+      return sendStats;
+   }
+      
    // Public ------------------------------------------------------------------------------------------
       
    // Protected ---------------------------------------------------------------------------------------
-   
-   protected Binding createBinding(String nodeId, String queueName, String condition, Filter filter,
-            long channelId, boolean durable) throws Exception
+        
+   protected Bindings createBindings()
    {
-      return new ClusteredBindingImpl(nodeId, queueName, condition, filter,
-                                      channelId, durable);   
+      return new ClusteredBindingsImpl(this.nodeId);
    }
-           
+   
    protected void loadBindings() throws Exception
    {
       // TODO I need to know whether this call times out - how do I know this??
@@ -1001,6 +950,28 @@
       }
    }
    
+   protected Binding createBinding(String nodeId, String condition, String queueName, long channelId, String filterString, boolean durable) throws Exception
+   {            
+      Filter filter = filterFactory.createFilter(filterString);
+      
+      Queue queue;
+      if (nodeId.equals(this.nodeId))
+      {
+         QueuedExecutor executor = (QueuedExecutor)pool.get();
+         
+         queue = new LocalClusteredQueue(nodeId, queueName, channelId, ms, pm, true,
+                                         true, executor, filter);
+      }
+      else
+      {
+         queue = new RemoteQueueStub(nodeId, queueName, channelId, true, pm, filter);
+      }
+      
+      Binding binding = new BindingImpl(nodeId, condition, queue);
+      
+      return binding;
+   }
+   
    // Private ------------------------------------------------------------------------------------------
            
    private void syncSendRequest(ClusterRequest request) throws Exception
@@ -1020,7 +991,7 @@
       //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());
+      Collection bindings = listBindingsForCondition(holder.getRoutingKey());
       
       if (bindings == null)
       {
@@ -1036,11 +1007,11 @@
       {
          Binding binding = (Binding)iter2.next();
          
-         if (binding.isDurable())
+         if (binding.getQueue().isRecoverable())
          {
             found = true;
             
-            channelID = binding.getChannelId();
+            channelID = binding.getQueue().getChannelID();
          }
       }
       
@@ -1097,7 +1068,7 @@
             {
                Binding binding = (Binding)iter.next();
                
-               if (!binding.isDurable())
+               if (!binding.getQueue().isRecoverable())
                {
                   toRemove.add(binding);
                }
@@ -1109,7 +1080,7 @@
             {
                Binding binding = (Binding)iter.next();
                
-               removeBinding(nodeId, binding.getQueueName());
+               removeBinding(nodeId, binding.getQueue().getName());
             }
          }
          
@@ -1138,7 +1109,16 @@
          
          while (iter2.hasNext())
          {
-            bindings.add(iter2.next());
+            Binding binding = (Binding)iter2.next();
+                      
+            Queue queue = binding.getQueue();        
+            
+            BindingInfo info = new BindingInfo(binding.getNodeId(), queue.getName(),
+                                               binding.getCondition(),
+                                               queue.getFilter() == null ? null : queue.getFilter().getFilterString(),
+                                               queue.getChannelID(),
+                                               queue.isRecoverable());    
+            bindings.add(info);
          }
       }
       
@@ -1165,8 +1145,10 @@
       
       while (iter.hasNext())
       {
-         Binding binding = (Binding)iter.next();
+         BindingInfo info = (BindingInfo)iter.next();
          
+         Binding binding = this.createBinding(info.getNodeId(), info.getCondition(), info.getQueueName(), info.getChannelId(), info.getFilterString(), info.isDurable());
+         
          addBinding(binding);
       }
       
@@ -1178,26 +1160,17 @@
    /*
     * Move messages from queue on one node to queue on another node
     */
-   private void moveMessages(String queueName, String toNodeId, int num) throws Throwable
+   private void moveMessages(Queue fromQueue, String toNodeId, int num) throws Throwable
    {      
       log.info("Moving " + num + " messages from " + this.nodeId + " to " + toNodeId + " for queue name");
       
-      Binding binding = getBindingForQueueName(queueName);
-      
-      if (binding == null)
-      {
-         throw new IllegalStateException("Cannot find binding for queue name: " + queueName);
-      }
-      
-      Queue fromQueue = binding.getQueue();
-
       Transaction tx = tr.createTransaction();
                
-      List dels = ((ClusteredQueue)fromQueue).getDeliveries(num);
+      List dels = ((LocalClusteredQueue)fromQueue).getDeliveries(num);
       
       Iterator iter = dels.iterator();
       
-      MoveMessagesCallback cb = new MoveMessagesCallback(nodeId, toNodeId, queueName,
+      MoveMessagesCallback cb = new MoveMessagesCallback(nodeId, toNodeId, fromQueue.getName(),
                                                          tx.getId(), this);      
       while (iter.hasNext())
       {

Modified: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredQueue.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredQueue.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/ClusteredQueue.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -21,23 +21,9 @@
  */
 package org.jboss.messaging.core.plugin.postoffice.cluster;
 
-import java.util.ArrayList;
-import java.util.List;
+import org.jboss.messaging.core.Queue;
 
-import org.jboss.messaging.core.Delivery;
-import org.jboss.messaging.core.DeliveryObserver;
-import org.jboss.messaging.core.MessageReference;
-import org.jboss.messaging.core.SimpleDelivery;
-import org.jboss.messaging.core.local.Queue;
-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.util.Future;
-
-import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
-
 /**
- * 
  * A ClusteredQueue
  *
  * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
@@ -46,122 +32,13 @@
  * $Id$
  *
  */
-public class ClusteredQueue extends Queue
+public interface ClusteredQueue extends Queue
 {
-   private static final int MIN_PERIOD = 1000;
+   double getGrowthRate();
    
-   private long lastTime;
+   int getMessageCount();
    
-   private double lastGrowthRate;
+   String getNodeId();
    
-   private volatile int numberAdded;
-   
-   private volatile int numberConsumed;
- 
-   public ClusteredQueue(long id, MessageStore ms, PersistenceManager pm, boolean acceptReliableMessages,
-                         boolean recoverable, int fullSize, int pageSize, int downCacheSize, QueuedExecutor executor)
-   {
-      super(id, ms, pm, acceptReliableMessages, recoverable, fullSize, pageSize,
-            downCacheSize, executor);
-      
-      lastTime = System.currentTimeMillis();      
-      
-      numberAdded = numberConsumed = 0;
-   }
-   
-   /**
-    * 
-    * @return The rate of growth in messages per second of the queue
-    * Rate of growth is defined as follows:
-    * growth = (number of messages added - number of messages consumed) / time
-    */
-   public synchronized double getGrowthRate()
-   {
-      long now = System.currentTimeMillis();
-      
-      long period = now - lastTime;
-      
-      if (period <= MIN_PERIOD)
-      {
-         //Cache the value to avoid recalculating too often
-         return lastGrowthRate;
-      }
-      
-      lastGrowthRate = 1000 * (numberAdded - numberConsumed) / ((double)period);
-      
-      lastTime = now;
-      
-      numberAdded = numberConsumed = 0;
-      
-      return lastGrowthRate;
-   }
-   
-   public List getDeliveries(int number) throws Exception
-   {
-      List dels = new ArrayList();
-      
-      synchronized (refLock)
-      {
-         synchronized (deliveryLock)
-         {
-            MessageReference ref;
-            
-            while ((ref = removeFirstInMemory()) != null)
-            {
-               SimpleDelivery del = new SimpleDelivery(this, ref);
-               
-               deliveries.add(del);
-               
-               dels.add(del);               
-            }           
-            return dels;
-         }
-      }          
-   }
-   
-   /*
-    * This is the same as the normal handle() method on the Channel except it doesn't
-    * persist the message even if it is persistent - this is because persistent messages
-    * are always persisted on the sending node before sending.
-    */
-   public Delivery handleFromCluster(DeliveryObserver sender, MessageReference ref, Transaction tx)
-      throws Exception
-   {
-      checkClosed();
-      
-      Future result = new Future();
-
-      if (tx == null)
-      {         
-         // Instead of executing directly, we add the handle request to the event queue.
-         // 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, ref, false));
-   
-         return (Delivery)result.getResult();
-      }
-      else
-      {
-         return handleInternal(sender, ref, tx, false);
-      }
-   }
-
-   protected void addReferenceInMemory(MessageReference ref) throws Exception
-   {
-      super.addReferenceInMemory(ref);
-      
-      //This is ok, since the channel ensures only one thread calls this method at once
-      numberAdded++;
-   }
-
-   protected boolean acknowledgeInMemory(Delivery d)
-   {
-      boolean acked = super.acknowledgeInMemory(d);
-      
-      // This is ok, since the channel ensures only one thread calls this method at once
-      numberConsumed--;
-      
-      return acked;
-   }  
+   boolean isLocal();
 }

Deleted: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/FavourLocalRoutingPolicy.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/FavourLocalRoutingPolicy.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/FavourLocalRoutingPolicy.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -1,68 +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.postoffice.cluster;
-
-import java.util.Iterator;
-import java.util.List;
-
-import org.jboss.messaging.core.plugin.postoffice.Binding;
-
-/**
- * A FavourLocalRoutingPolicy
- * 
- * This routing policy always favours the local queue
- *
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision: 1.1 $</tt>
- *
- * $Id$
- *
- */
-public class FavourLocalRoutingPolicy implements RoutingPolicy
-{
-   private String localNodeId;
-
-   public FavourLocalRoutingPolicy(String localNodeId)
-   {
-      this.localNodeId = localNodeId;
-   }
-   
-   public Binding choose(List bindings)
-   {
-      Iterator iter = bindings.iterator();
-      
-      Binding binding = null;
-      
-      while (iter.hasNext())
-      {
-         binding = (Binding)iter.next();
-         
-         if (binding.getNodeId().equals(localNodeId))
-         {
-            return binding;
-         }
-      }
-      
-      return binding;
-   }
-
-}

Added: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/LocalClusteredQueue.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/LocalClusteredQueue.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/LocalClusteredQueue.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -0,0 +1,201 @@
+/*
+ * 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.Delivery;
+import org.jboss.messaging.core.DeliveryObserver;
+import org.jboss.messaging.core.Filter;
+import org.jboss.messaging.core.MessageReference;
+import org.jboss.messaging.core.SimpleDelivery;
+import org.jboss.messaging.core.local.PagingFilteredQueue;
+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.util.Future;
+
+import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
+
+/**
+ * 
+ * A LocalClusteredQueue
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class LocalClusteredQueue extends PagingFilteredQueue implements ClusteredQueue
+{
+   private static final int MIN_PERIOD = 1000;
+   
+   private String nodeId;
+   
+   private long lastTime;
+   
+   private double lastGrowthRate;
+   
+   private volatile int numberAdded;
+   
+   private volatile int numberConsumed;
+ 
+   public LocalClusteredQueue(String nodeId, String name, long id, MessageStore ms, PersistenceManager pm,             
+                              boolean acceptReliableMessages, boolean recoverable, QueuedExecutor executor,
+                              Filter filter,
+                              int fullSize, int pageSize, int downCacheSize)
+   {
+      super(name, id, ms, pm, acceptReliableMessages, recoverable, executor, filter, fullSize, pageSize, downCacheSize);
+     
+      this.nodeId = nodeId;
+      
+      lastTime = System.currentTimeMillis();      
+      
+      numberAdded = numberConsumed = 0;
+   }
+   
+   public LocalClusteredQueue(String nodeId, String name, long id, MessageStore ms, PersistenceManager pm,             
+                              boolean acceptReliableMessages, boolean recoverable, QueuedExecutor executor,
+                              Filter filter)
+   {
+      super(name, id, ms, pm, acceptReliableMessages, recoverable, executor, filter);
+      
+      this.nodeId = nodeId;
+      
+      lastTime = System.currentTimeMillis();      
+      
+      numberAdded = numberConsumed = 0;
+   }
+   
+   /**
+    * 
+    * @return The rate of growth in messages per second of the queue
+    * Rate of growth is defined as follows:
+    * growth = (number of messages added - number of messages consumed) / time
+    */
+   public synchronized double getGrowthRate()
+   {
+      long now = System.currentTimeMillis();
+      
+      long period = now - lastTime;
+      
+      if (period <= MIN_PERIOD)
+      {
+         //Cache the value to avoid recalculating too often
+         return lastGrowthRate;
+      }
+      
+      lastGrowthRate = 1000 * (numberAdded - numberConsumed) / ((double)period);
+      
+      lastTime = now;
+      
+      numberAdded = numberConsumed = 0;
+      
+      return lastGrowthRate;
+   }
+   
+   public boolean isLocal()
+   {
+      return true;
+   }
+   
+   public String getNodeId()
+   {
+      return nodeId;
+   }
+   
+   public int getMessageCount()
+   {
+      return messageCount();
+   }
+   
+   public List getDeliveries(int number) throws Exception
+   {
+      List dels = new ArrayList();
+      
+      synchronized (refLock)
+      {
+         synchronized (deliveryLock)
+         {
+            MessageReference ref;
+            
+            while ((ref = removeFirstInMemory()) != null)
+            {
+               SimpleDelivery del = new SimpleDelivery(this, ref);
+               
+               deliveries.add(del);
+               
+               dels.add(del);               
+            }           
+            return dels;
+         }
+      }          
+   }
+   
+   /*
+    * This is the same as the normal handle() method on the Channel except it doesn't
+    * persist the message even if it is persistent - this is because persistent messages
+    * are always persisted on the sending node before sending.
+    */
+   public Delivery handleFromCluster(DeliveryObserver sender, MessageReference ref, Transaction tx)
+      throws Exception
+   {
+      checkClosed();
+      
+      Future result = new Future();
+
+      if (tx == null)
+      {         
+         // Instead of executing directly, we add the handle request to the event queue.
+         // 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, ref, false));
+   
+         return (Delivery)result.getResult();
+      }
+      else
+      {
+         return handleInternal(sender, ref, tx, false);
+      }
+   }
+
+   protected void addReferenceInMemory(MessageReference ref) throws Exception
+   {
+      super.addReferenceInMemory(ref);
+      
+      //This is ok, since the channel ensures only one thread calls this method at once
+      numberAdded++;
+   }
+
+   protected boolean acknowledgeInMemory(Delivery d)
+   {
+      boolean acked = super.acknowledgeInMemory(d);
+      
+      // This is ok, since the channel ensures only one thread calls this method at once
+      numberConsumed--;
+      
+      return acked;
+   }  
+}

Modified: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/QueueStats.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/QueueStats.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/QueueStats.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -39,7 +39,7 @@
 {
    private String queueName;
    
-   private double consumptionRate;
+   private double growthRate;
    
    private int messageCount;
 
@@ -47,18 +47,18 @@
    {      
    }
    
-   QueueStats(String queueName, double consumptionRate, int messageCount)
+   QueueStats(String queueName, double growthRate, int messageCount)
    {
       this.queueName = queueName;
       
-      this.consumptionRate = consumptionRate;
+      this.growthRate = growthRate;
       
       this.messageCount = messageCount;
    }
 
-   double getConsumptionRate()
+   double getGrowthRate()
    {
-      return consumptionRate;
+      return growthRate;
    }
 
    int getMessageCount()
@@ -75,7 +75,7 @@
    {
       queueName = in.readUTF();
       
-      consumptionRate = in.readDouble();
+      growthRate = in.readDouble();
       
       messageCount = in.readInt();
    }
@@ -84,7 +84,7 @@
    {
       out.writeUTF(queueName);
       
-      out.writeDouble(consumptionRate);
+      out.writeDouble(growthRate);
       
       out.writeInt(messageCount);
    }      

Modified: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/RedistributionOrder.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/RedistributionOrder.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/RedistributionOrder.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -21,6 +21,8 @@
  */
 package org.jboss.messaging.core.plugin.postoffice.cluster;
 
+import org.jboss.messaging.core.Queue;
+
 /**
  * 
  * A RedistributionOrder
@@ -35,15 +37,15 @@
 {
    private int numberOfMessages;
    
-   private String queueName;
+   private Queue queue;
    
    private String destinationNodeId;
 
-   public RedistributionOrder(int numberOfMessages, String queueName, String destinationNodeId)
+   public RedistributionOrder(int numberOfMessages, Queue queue, String destinationNodeId)
    {
       this.numberOfMessages = numberOfMessages;
       
-      this.queueName = queueName;
+      this.queue = queue;
       
       this.destinationNodeId = destinationNodeId;
    }
@@ -58,8 +60,8 @@
       return numberOfMessages;
    }
 
-   public String getQueueName()
+   public Queue getQueue()
    {
-      return queueName;
+      return queue;
    }
 }

Added: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/RemoteQueueStub.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/RemoteQueueStub.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/RemoteQueueStub.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -0,0 +1,234 @@
+/*
+ * 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;
+
+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.Receiver;
+import org.jboss.messaging.core.SimpleDelivery;
+import org.jboss.messaging.core.plugin.contract.PersistenceManager;
+import org.jboss.messaging.core.tx.Transaction;
+import org.jboss.messaging.core.tx.TxCallback;
+
+/**
+ * A RemoteQueueStub
+ * 
+ * TODO to avoid having to implement a lot of methods that throw
+ * UnsupportedOperationException should define an interface that only declares
+ * the required methods and implement that
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class RemoteQueueStub implements ClusteredQueue
+{
+   private static final Logger log = Logger.getLogger(RemoteQueueStub.class);
+      
+   private String nodeId;
+   
+   private String name;
+   
+   private long id;
+   
+   private Filter filter;
+   
+   private boolean recoverable;
+   
+   private int messageCount;
+   
+   private double growthRate;
+   
+   private PersistenceManager pm;
+   
+   public RemoteQueueStub(String nodeId, String name, long id, boolean recoverable, PersistenceManager pm, Filter filter)
+   {
+      this.nodeId = nodeId;
+      
+      this.name = name;
+      
+      this.id = id;
+      
+      this.recoverable = recoverable;
+      
+      this.pm = pm;
+      
+      this.filter = filter;
+   }
+   
+   public String getNodeId()
+   {
+      return nodeId;
+   }
+   
+   public boolean isLocal()
+   {
+      return false;
+   }
+   
+   public void setStats(int messageCount, double growthRate)
+   {
+      this.messageCount = messageCount;
+      
+      this.growthRate = growthRate;
+   }
+   
+   public double getGrowthRate()
+   {
+      return growthRate;
+   }
+   
+   public int getMessageCount()
+   {
+      return messageCount;
+   }
+
+   public Delivery handle(DeliveryObserver observer, MessageReference reference, Transaction tx)
+   {
+      //If the message is persistent and we are recoverable then we persist here, *before*
+      //the message is sent across the network
+      
+      if (recoverable && reference.isReference())
+      {
+         try
+         {
+            pm.addReference(id, reference, tx);
+         }
+         catch (Exception e)
+         {
+            log.error("Failed to add reference", e);
+            return null;
+         }
+      }
+  
+      return new SimpleDelivery(this, reference, false);      
+   }
+
+   public Filter getFilter()
+   {
+      return filter;
+   }
+
+   public String getName()
+   {
+      return name;
+   }
+
+   public boolean acceptReliableMessages()
+   {
+      return true;
+   }
+
+   public List browse()
+   {
+      throw new UnsupportedOperationException();
+   }
+
+   public List browse(Filter filter)
+   {
+      throw new UnsupportedOperationException();
+   }
+
+   public void clear()
+   {
+      throw new UnsupportedOperationException();
+   }
+
+   public void close()
+   {
+   }
+
+   public void deliver(boolean synchronous)
+   {
+      throw new UnsupportedOperationException();
+   }
+
+   public List delivering(Filter filter)
+   {
+      throw new UnsupportedOperationException();
+   }
+
+   public long getChannelID()
+   {
+      return id;
+   }
+
+   public boolean isRecoverable()
+   {
+      return recoverable;
+   }
+
+   public int messageCount()
+   {
+      return messageCount;
+   }
+
+   public void removeAllReferences() throws Throwable
+   {
+      throw new UnsupportedOperationException();
+   }
+
+   public List undelivered(Filter filter)
+   {
+      throw new UnsupportedOperationException();
+   }
+
+   public void acknowledge(Delivery d, Transaction tx) throws Throwable
+   {
+      throw new UnsupportedOperationException();
+   }
+
+   public void cancel(Delivery d) throws Throwable
+   {
+      throw new UnsupportedOperationException();
+   }
+
+   public boolean add(Receiver receiver)
+   {
+      // TODO Auto-generated method stub
+      return false;
+   }
+
+   public boolean contains(Receiver receiver)
+   {
+      throw new UnsupportedOperationException();
+   }
+
+   public Iterator iterator()
+   {
+      throw new UnsupportedOperationException();
+   }
+
+   public boolean remove(Receiver receiver)
+   {
+      throw new UnsupportedOperationException();
+   }
+   
+}

Deleted: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/RoutingPolicy.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/RoutingPolicy.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/RoutingPolicy.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -1,40 +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.postoffice.cluster;
-
-import java.util.List;
-
-import org.jboss.messaging.core.plugin.postoffice.Binding;
-
-/**
- * A RoutingPolicy
- *
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- * @version <tt>$Revision: 1.1 $</tt>
- *
- * $Id$
- *
- */
-public interface RoutingPolicy
-{
-   Binding choose(List bindings); 
-}

Modified: 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-15 22:09:37 UTC (rev 1296)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/SharedState.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -28,7 +28,6 @@
 import java.util.List;
 import java.util.Map;
 
-import org.jboss.messaging.core.plugin.postoffice.Binding;
 import org.jboss.messaging.util.StreamUtils;
 import org.jboss.messaging.util.Streamable;
 
@@ -74,7 +73,7 @@
       bindings = new ArrayList(size);
       for (int i = 0; i < size; i++)
       {
-         ClusteredBinding bb = new ClusteredBindingImpl();
+         BindingInfo bb = new BindingInfo();
          bb.read(in);
          bindings.add(bb);
       }
@@ -88,16 +87,9 @@
       Iterator iter = bindings.iterator();
       while (iter.hasNext())
       {
-         Binding binding = (Binding)iter.next();
+         BindingInfo info = (BindingInfo)iter.next();
          
-         if (!(binding instanceof ClusteredBinding))
-         {
-            throw new IllegalStateException("Can only cluster clustered bindings");
-         }
-         
-         ClusteredBinding bb = (ClusteredBinding)binding;
-         
-         bb.write(out);
+         info.write(out);
       }
       
       StreamUtils.writeObject(out, nodeIdAddressMap, true, false);     

Modified: trunk/tests/src/org/jboss/test/messaging/core/base/QueueTestBase.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/base/QueueTestBase.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/base/QueueTestBase.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -26,11 +26,11 @@
 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.local.PagingFilteredQueue;
 import org.jboss.messaging.core.plugin.IdManager;
 import org.jboss.messaging.core.plugin.JDBCPersistenceManager;
 import org.jboss.messaging.core.plugin.SimpleMessageStore;
@@ -89,7 +89,7 @@
    
    protected ServiceContainer sc;
 
-   protected Channel queue;
+   protected PagingFilteredQueue queue;
 
 
    // Constructors --------------------------------------------------

Modified: trunk/tests/src/org/jboss/test/messaging/core/local/NonRecoverableQueueTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/local/NonRecoverableQueueTest.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/local/NonRecoverableQueueTest.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -21,7 +21,10 @@
 */
 package org.jboss.test.messaging.core.local;
 
-import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.Filter;
+import org.jboss.messaging.core.local.PagingFilteredQueue;
+import org.jboss.messaging.core.plugin.contract.MessageStore;
+import org.jboss.messaging.core.plugin.contract.PersistenceManager;
 import org.jboss.test.messaging.core.base.QueueTestBase;
 
 import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
@@ -55,9 +58,9 @@
    {
       super.setUp();
       
-      queue = new Queue(1, ms, pm, true, false, 100, 20, 10, new QueuedExecutor());
+      queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, false, new QueuedExecutor(), null);
    }
-
+   
    public void tearDown() throws Exception
    {
       queue.close();
@@ -71,7 +74,7 @@
 
    public void recoverChannel() throws Exception
    {
-      queue = new Queue(1, ms, pm, true, false, 100, 20, 10, new QueuedExecutor());
+      queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, false, new QueuedExecutor(), null);
    }
 
    // Public --------------------------------------------------------

Modified: trunk/tests/src/org/jboss/test/messaging/core/local/RecoverableQueueTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/local/RecoverableQueueTest.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/local/RecoverableQueueTest.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -21,7 +21,7 @@
 */
 package org.jboss.test.messaging.core.local;
 
-import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.local.PagingFilteredQueue;
 import org.jboss.test.messaging.core.base.QueueTestBase;
 
 import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
@@ -55,7 +55,7 @@
    {
       super.setUp();
       
-      queue = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor());
+      queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null);
    }
 
    public void tearDown() throws Exception
@@ -71,7 +71,7 @@
 
    public void recoverChannel() throws Exception
    {
-      queue = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor());
+      queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null);
    }
 
    // Public --------------------------------------------------------

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-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_2PCTest.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -25,7 +25,7 @@
 
 import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.MessageReference;
-import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.local.PagingFilteredQueue;
 import org.jboss.messaging.core.plugin.LockMap;
 import org.jboss.messaging.core.tx.Transaction;
 import org.jboss.test.messaging.util.CoreMessageFactory;
@@ -64,10 +64,10 @@
    
    public void testChannelShareNP_2PC() throws Throwable
    {
-      Queue queue1 = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor());
+      PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
       
-      Queue queue2 = new Queue(2, ms, pm, true, true, 50, 10, 5, new QueuedExecutor());
-                      
+      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", 1, ms, pm, true, true, new QueuedExecutor(), null, 50, 10, 5);
+                  
       Message[] msgs = new Message[150];
       
       MessageReference[] refs1 = new MessageReference[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-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_NTTest.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -25,7 +25,7 @@
 
 import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.MessageReference;
-import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.local.PagingFilteredQueue;
 import org.jboss.messaging.core.plugin.LockMap;
 import org.jboss.test.messaging.util.CoreMessageFactory;
 
@@ -63,10 +63,10 @@
    
    public void test1() throws Throwable
    {
-      Queue queue1 = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor());
-      
-      Queue queue2 = new Queue(2, ms, pm, true, true, 50, 10, 5, new QueuedExecutor());
-                  
+      PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+     
+      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", 1, ms, pm, true, true, new QueuedExecutor(), null, 50, 10, 5);
+           
       Message[] msgs = new Message[150];
       
       MessageReference[] refs1 = new MessageReference[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-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_TTest.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -25,7 +25,7 @@
 
 import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.MessageReference;
-import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.local.PagingFilteredQueue;
 import org.jboss.messaging.core.plugin.LockMap;
 import org.jboss.messaging.core.tx.Transaction;
 import org.jboss.test.messaging.util.CoreMessageFactory;
@@ -64,9 +64,10 @@
    
    public void testChannelShareNP_Transactional() throws Throwable
    {
-      Queue queue1 = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor());
+      PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
       
-      Queue queue2 = new Queue(2, ms, pm, true, true, 50, 10, 5, new QueuedExecutor());
+      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", 1, ms, pm, true, true, new QueuedExecutor(), null, 50, 10, 5);
+     
                                
       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-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_2PCTest.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -25,7 +25,7 @@
 
 import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.MessageReference;
-import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.local.PagingFilteredQueue;
 import org.jboss.messaging.core.plugin.LockMap;
 import org.jboss.messaging.core.tx.Transaction;
 import org.jboss.test.messaging.util.CoreMessageFactory;
@@ -59,9 +59,10 @@
    
    public void test1() throws Throwable
    {
-      Queue queue1 = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor());
+      PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
       
-      Queue queue2 = new Queue(2, ms, pm, true, true, 50, 10, 5, new QueuedExecutor());
+      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", 1, ms, pm, true, true, new QueuedExecutor(), null, 50, 10, 5);
+     
                             
       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-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_NTTest.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -25,7 +25,7 @@
 
 import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.MessageReference;
-import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.local.PagingFilteredQueue;
 import org.jboss.messaging.core.plugin.LockMap;
 import org.jboss.test.messaging.util.CoreMessageFactory;
 
@@ -63,9 +63,10 @@
    
    public void test1() throws Throwable
    {
-      Queue queue1 = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor());
+      PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
       
-      Queue queue2 = new Queue(2, ms, pm, true, true, 50, 10, 5, new QueuedExecutor());
+      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", 1, ms, pm, true, true, new QueuedExecutor(), null, 50, 10, 5);
+     
                                 
       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-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_TTest.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -25,7 +25,7 @@
 
 import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.MessageReference;
-import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.local.PagingFilteredQueue;
 import org.jboss.messaging.core.plugin.LockMap;
 import org.jboss.messaging.core.tx.Transaction;
 import org.jboss.test.messaging.util.CoreMessageFactory;
@@ -63,10 +63,10 @@
    
    public void test1() throws Throwable
    {
-      Queue queue1 = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor());
+      PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
       
-      Queue queue2 = new Queue(2, ms, pm, true, true, 50, 10, 5, new QueuedExecutor());
-                            
+      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", 1, ms, pm, true, true, new QueuedExecutor(), null, 50, 10, 5);
+                                
       Message[] msgs = new Message[150];
       
       MessageReference[] refs1 = new MessageReference[150];

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-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/PagingTest.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -21,7 +21,7 @@
 */
 package org.jboss.test.messaging.core.paging;
 
-import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.local.PagingFilteredQueue;
 import org.jboss.messaging.core.message.CoreMessage;
 import org.jboss.messaging.core.plugin.JDBCPersistenceManager;
 import org.jboss.messaging.core.plugin.SimpleMessageStore;
@@ -63,8 +63,8 @@
 
    public void testPaging() throws Exception
    {
-      Queue p = new Queue(0, ms, pm, true, true, 100, 20, 10, new QueuedExecutor());
-
+      PagingFilteredQueue p = new PagingFilteredQueue("queue0", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+           
       CoreMessage m = null;
 
       m = CoreMessageFactory.createCoreMessage(0);

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-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_2PCTest.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -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.Queue;
+import org.jboss.messaging.core.local.PagingFilteredQueue;
 import org.jboss.messaging.core.plugin.LockMap;
 import org.jboss.messaging.core.tx.Transaction;
 import org.jboss.test.messaging.util.CoreMessageFactory;
@@ -66,8 +66,8 @@
    
    public void test1() throws Throwable
    {
-      Queue queue = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor());
-               
+      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+            
       Message[] msgs = new Message[241];
       
       MessageReference[] refs = new MessageReference[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-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_NTTest.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -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.Queue;
+import org.jboss.messaging.core.local.PagingFilteredQueue;
 import org.jboss.messaging.core.plugin.LockMap;
 import org.jboss.test.messaging.util.CoreMessageFactory;
 
@@ -65,8 +65,8 @@
    
    public void test1() throws Throwable
    {
-      Queue queue = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor());
-                           
+      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      
       Message[] msgs = new Message[241];
       
       MessageReference[] refs = new MessageReference[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-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_TTest.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -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.Queue;
+import org.jboss.messaging.core.local.PagingFilteredQueue;
 import org.jboss.messaging.core.plugin.LockMap;
 import org.jboss.messaging.core.tx.Transaction;
 import org.jboss.test.messaging.util.CoreMessageFactory;
@@ -66,8 +66,8 @@
  
    public void test1() throws Throwable
    {
-      Queue queue = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor());
-                    
+      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      
       Message[] msgs = new Message[241];
       
       MessageReference[] refs = new MessageReference[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-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_2PCTest.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -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.Queue;
+import org.jboss.messaging.core.local.PagingFilteredQueue;
 import org.jboss.messaging.core.plugin.LockMap;
 import org.jboss.messaging.core.tx.Transaction;
 import org.jboss.test.messaging.util.CoreMessageFactory;
@@ -66,8 +66,8 @@
    
    public void test1() throws Throwable
    {
-      Queue queue = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor());
-                    
+      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      
       Message[] msgs = new Message[241];
       
       MessageReference[] refs = new MessageReference[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-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_NTTest.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -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.Queue;
+import org.jboss.messaging.core.local.PagingFilteredQueue;
 import org.jboss.messaging.core.plugin.LockMap;
 import org.jboss.test.messaging.util.CoreMessageFactory;
 
@@ -65,8 +65,8 @@
    
    public void test1() throws Throwable
    {
-      Queue queue = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor());
-                        
+      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      
       Message[] msgs = new Message[241];
       
       MessageReference[] refs = new MessageReference[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-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_TTest.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -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.Queue;
+import org.jboss.messaging.core.local.PagingFilteredQueue;
 import org.jboss.messaging.core.plugin.LockMap;
 import org.jboss.messaging.core.tx.Transaction;
 import org.jboss.test.messaging.util.CoreMessageFactory;
@@ -66,8 +66,8 @@
    
    public void test1() throws Throwable
    {
-      Queue queue = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor());
-                  
+      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      
       Message[] msgs = new Message[241];
       
       MessageReference[] refs = new MessageReference[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-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_ReloadTest.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -25,7 +25,7 @@
 
 import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.MessageReference;
-import org.jboss.messaging.core.local.Queue;
+import org.jboss.messaging.core.local.PagingFilteredQueue;
 import org.jboss.messaging.core.plugin.IdManager;
 import org.jboss.messaging.core.plugin.JDBCPersistenceManager;
 import org.jboss.messaging.core.plugin.LockMap;
@@ -66,8 +66,8 @@
    
    public void testRecoverableQueueCrash() throws Throwable
    {
-      Queue queue = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor());
-      
+      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+
       Message[] msgs = new Message[200];
       
       MessageReference[] refs = new MessageReference[200];
@@ -126,10 +126,8 @@
       ms = new SimpleMessageStore();
       ms.start();
        
-      Queue queue2 = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor());
-      
-      queue2.load();
-      
+      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+
       refIds = getReferenceIdsOrderedByPageOrd(queue.getChannelID());
       assertEquals(50, refIds.size());
                    
@@ -155,8 +153,8 @@
    {
       //Non recoverable queue - eg temporary queue
       
-      Queue queue = new Queue(1, ms, pm, true, false, 100, 20, 10, new QueuedExecutor());
-
+      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      
       Message[] msgs = new Message[200];
       
       MessageReference[] refs = new MessageReference[200];
@@ -215,10 +213,8 @@
       ms = new SimpleMessageStore();
       ms.start();
       
-      Queue queue2 = new Queue(1, ms, pm, true, false, 100, 20, 10, new QueuedExecutor());
+      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
       
-      queue2.load();
-      
       refIds = getReferenceIdsOrderedByPageOrd(queue.getChannelID());
       assertEquals(0, refIds.size());
       
@@ -242,8 +238,8 @@
    {
       //Non recoverable queue - eg temporary queue
       
-      Queue queue = new Queue(1, ms, pm, true, false, 100, 20, 10, new QueuedExecutor());
-      
+      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+  
       Message[] msgs = new Message[200];
       
       MessageReference[] refs = new MessageReference[200];
@@ -306,8 +302,8 @@
    
    public void testQueueReloadWithSmallerFullSize() throws Throwable
    {
-      Queue queue = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor());
-
+      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      
       Message[] msgs = new Message[150];
       
       MessageReference[] refs = new MessageReference[150];
@@ -360,10 +356,8 @@
       
       //Reload the queue with a smaller fullSize
       
-      Queue queue2 = new Queue(1, ms, pm, true, false, 50, 20, 10, new QueuedExecutor());
+      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 50, 20, 10);
       
-      queue2.load();
-      
       refIds = getReferenceIdsOrderedByPageOrd(queue.getChannelID());
       assertEquals(150, refIds.size());
       
@@ -404,8 +398,8 @@
    
    public void testReloadWithLargerFullSize() throws Throwable
    {
-      Queue queue = new Queue(1, ms, pm, true, true, 100, 20, 10, new QueuedExecutor());
-
+      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      
       Message[] msgs = new Message[150];
       
       MessageReference[] refs = new MessageReference[150];
@@ -458,10 +452,8 @@
       
       //Reload the queue with a smaller fullSize
       
-      Queue queue2 = new Queue(1, ms, pm, true, false, 130, 20, 10, new QueuedExecutor());
+      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 130, 20, 10);
       
-      queue2.load();
-      
       refIds = getReferenceIdsOrderedByPageOrd(queue.getChannelID());
       assertEquals(150, refIds.size());
       

Deleted: trunk/tests/src/org/jboss/test/messaging/core/plugin/ClusteredPostOfficeTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/plugin/ClusteredPostOfficeTest.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/plugin/ClusteredPostOfficeTest.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -1,1248 +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.plugin.contract.ClusteredPostOffice;
-import org.jboss.messaging.core.plugin.postoffice.Binding;
-import org.jboss.messaging.core.plugin.postoffice.cluster.BasicRedistributionPolicy;
-import org.jboss.messaging.core.plugin.postoffice.cluster.ClusteredBinding;
-import org.jboss.messaging.core.plugin.postoffice.cluster.ClusteredPostOfficeImpl;
-import org.jboss.messaging.core.plugin.postoffice.cluster.ClusteredQueue;
-import org.jboss.messaging.core.plugin.postoffice.cluster.FavourLocalRoutingPolicy;
-import org.jboss.messaging.core.plugin.postoffice.cluster.RedistributionPolicy;
-import org.jboss.messaging.core.plugin.postoffice.cluster.RoutingPolicy;
-import org.jboss.messaging.core.tx.Transaction;
-import org.jboss.test.messaging.core.SimpleReceiver;
-import org.jboss.test.messaging.util.CoreMessageFactory;
-
-import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
-
-/**
- * 
- * A ClusteredPostOfficeTest
- *
- * @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 testClusteredBindUnbind() throws Throwable
-   {
-      ClusteredPostOffice office1 = null;
-      
-      ClusteredPostOffice office2 = null;
-      
-      ClusteredPostOffice office3 = null;
-      
-      try
-      {         
-         //Start one office
-         
-         office1 = createClusteredPostOffice("node1", "testgroup");
-         
-         //Add a couple of bindings
-         
-         ClusteredQueue queue1 = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding1 =
-            office1.bindClusteredQueue("sub1", "topic1", null, queue1);
-         ClusteredQueue queue2 = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding2 =
-            office1.bindClusteredQueue("sub2", "topic1", null, queue2);
-         
-         //Start another office - 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
-         
-         ClusteredQueue queue3 = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding3 =
-            office2.bindClusteredQueue("sub3", "topic1", null, 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
-         
-         ClusteredQueue queue4 = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding4 =
-            office2.bindClusteredQueue("sub4", "topic1", null, 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 office
-                  
-         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
-                  
-         ClusteredQueue queue5 = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding5 =
-            office3.bindClusteredQueue("sub5", "topic1", null, 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
-         
-         ClusteredQueue queue6 = new ClusteredQueue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding6 =
-            office1.bindClusteredQueue("sub6", "topic1", null, queue6);
-         
-         ClusteredQueue queue7 = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding7 =
-            office1.bindClusteredQueue("sub7", "topic1", null, 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 office 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 office 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 office 1 and office 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 offices
-         
-         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);
-   }
-   
-   public final void testRedistribute() throws Exception
-   {
-      ClusteredPostOffice office1 = null;
-      
-      ClusteredPostOffice office2 = null;
-          
-      try
-      {   
-         office1 = createClusteredPostOffice("node1", "testgroup");
-         office2 = createClusteredPostOffice("node2", "testgroup");
-         
-         ClusteredQueue queue1 = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         ClusteredBinding binding1 = office1.bindClusteredQueue("queue1", "queue1", null, queue1);
-         
-         ClusteredQueue queue2 = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         ClusteredBinding binding2 = office2.bindClusteredQueue("queue1", "queue1", null, queue1);
-         
-         final int NUM_MESSAGES = 10;
-         for (int i = 0; i < NUM_MESSAGES; i++)
-         {
-            Message msg = CoreMessageFactory.createCoreMessage(i, false, null);      
-            MessageReference ref = ms.reference(msg);         
-            boolean routed = office1.route(ref, "queue1", null);
-         }
-         
-         List msgs = queue1.browse();
-         assertEquals(NUM_MESSAGES, msgs.size());
-         msgs = queue2.browse();
-         assertEquals(0, msgs.size());
-         
-         
-      
-      }
-      finally
-      {
-         if (office1 != null)
-         {            
-            office1.stop();
-         }
-         
-         if (office2 != null)
-         {
-            office2.stop();
-         }
-      }
-   }
-   
-   // 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
-         
-         ClusteredQueue[] queues = new ClusteredQueue[16];
-         Binding[] bindings = new Binding[16];
-         
-         queues[0] = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[0] = office1.bindClusteredQueue("sub1", "topic1", null, queues[0]);
-         
-         queues[1] = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[1] = office1.bindClusteredQueue("sub2", "topic1", null, queues[1]);
-         
-         queues[2] = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[2] = office2.bindClusteredQueue("sub3", "topic1", null, queues[2]);
-         
-         queues[3] = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[3] = office2.bindClusteredQueue("sub4", "topic1", null, queues[3]);
-         
-         queues[4] = new ClusteredQueue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[4] = office2.bindClusteredQueue("sub5", "topic1", null, queues[4]);
-         
-         queues[5] = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[5] = office1.bindClusteredQueue("sub6", "topic1", null, queues[5]);
-         
-         queues[6] = new ClusteredQueue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[6] = office1.bindClusteredQueue("sub7", "topic1", null, queues[6]);
-         
-         queues[7] = new ClusteredQueue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[7] = office1.bindClusteredQueue("sub8", "topic1", null, queues[7]);
-         
-         queues[8] = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[8] = office1.bindClusteredQueue("sub9", "topic2", null, queues[8]);
-         
-         queues[9] = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[9] = office1.bindClusteredQueue("sub10", "topic2", null, queues[9]);
-         
-         queues[10] = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[10] = office2.bindClusteredQueue("sub11", "topic2", null, queues[10]);
-         
-         queues[11] = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[11] = office2.bindClusteredQueue("sub12", "topic2", null, queues[11]);
-         
-         queues[12] = new ClusteredQueue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[12] = office2.bindClusteredQueue("sub13", "topic2", null, queues[12]);
-         
-         queues[13] = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[13] = office1.bindClusteredQueue("sub14", "topic2", null, queues[13]);
-         
-         queues[14] = new ClusteredQueue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[14] = office1.bindClusteredQueue("sub15", "topic2", null, queues[14]);
-         
-         queues[15] = new ClusteredQueue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[15] = office1.bindClusteredQueue("sub16", "topic2", null, 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 = CoreMessageFactory.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++)
-         {         
-            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 = CoreMessageFactory.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");
-     
-         ClusteredQueue[] queues = new ClusteredQueue[16];
-         Binding[] bindings = new Binding[16];
-         
-         queues[0] = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[0] = office1.bindClusteredQueue("sub1", "topic1", null, queues[0]);
-         
-         queues[1] = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[1] = office1.bindClusteredQueue("sub2", "topic1", null, queues[1]);
-         
-         queues[2] = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[2] = office2.bindClusteredQueue("sub3", "topic1", null, queues[2]);
-         
-         queues[3] = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[3] = office2.bindClusteredQueue("sub4", "topic1", null, queues[3]);
-         
-         queues[4] = new ClusteredQueue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[4] = office2.bindClusteredQueue("sub5", "topic1", null, queues[4]);
-         
-         queues[5] = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[5] = office1.bindClusteredQueue("sub6", "topic1", null, queues[5]);
-         
-         queues[6] = new ClusteredQueue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[6] = office1.bindClusteredQueue("sub7", "topic1", null, queues[6]);
-         
-         queues[7] = new ClusteredQueue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[7] = office1.bindClusteredQueue("sub8", "topic1", null, queues[7]);
-         
-         queues[8] = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[8] = office1.bindClusteredQueue("sub9", "topic2", null, queues[8]);
-         
-         queues[9] = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[9] = office1.bindClusteredQueue("sub10", "topic2", null, queues[9]);
-         
-         queues[10] = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[10] = office2.bindClusteredQueue("sub11", "topic2", null, queues[10]);
-         
-         queues[11] = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[11] = office2.bindClusteredQueue("sub12", "topic2", null, queues[11]);
-         
-         queues[12] = new ClusteredQueue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[12] = office2.bindClusteredQueue("sub13", "topic2", null, queues[12]);
-         
-         queues[13] = new ClusteredQueue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[13] = office1.bindClusteredQueue("sub14", "topic2", null, queues[13]);
-         
-         queues[14] = new ClusteredQueue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[14] = office1.bindClusteredQueue("sub15", "topic2", null, queues[14]);
-         
-         queues[15] = new ClusteredQueue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         bindings[15] = office1.bindClusteredQueue("sub16", "topic2", null, 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 = CoreMessageFactory.createCoreMessage(1, persistent, null);;      
-         MessageReference ref1 = ms.reference(msg1);
-         
-         Message msg2 = CoreMessageFactory.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 = CoreMessageFactory.createCoreMessage(1, persistent, null);;      
-         ref1 = ms.reference(msg1);
-         
-         msg2 = CoreMessageFactory.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 = CoreMessageFactory.createCoreMessage(1, persistent, null);
-         ref1 = ms.reference(msg1);
-         
-         msg2 = CoreMessageFactory.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 = CoreMessageFactory.createCoreMessage(1, persistent, null);;      
-         ref1 = ms.reference(msg1);
-         
-         msg2 = CoreMessageFactory.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 = CoreMessageFactory.createCoreMessage(1, persistent, null);    
-         ref1 = ms.reference(msg1);
-         
-         msg2 = CoreMessageFactory.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 = CoreMessageFactory.createCoreMessage(1, persistent, null);;      
-         ref1 = ms.reference(msg1);
-         
-         msg2 = CoreMessageFactory.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 = CoreMessageFactory.createCoreMessage(1, persistent, null);      
-         ref1 = ms.reference(msg1);
-         
-         msg2 = CoreMessageFactory.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 = CoreMessageFactory.createCoreMessage(1, persistent, null);;      
-         ref1 = ms.reference(msg1);
-         
-         msg2 = CoreMessageFactory.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
-   {
-      RoutingPolicy routingPolicy = new FavourLocalRoutingPolicy(nodeId);
-      
-      RedistributionPolicy redistPolicy = new BasicRedistributionPolicy(nodeId);
-      
-      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, routingPolicy, redistPolicy, 1000);
-      
-      postOffice.start();      
-      
-      return postOffice;
-   }
-
-   // Private -------------------------------------------------------
-
-   // Inner classes -------------------------------------------------
-
-}
-
-
-

Deleted: trunk/tests/src/org/jboss/test/messaging/core/plugin/JGroupsUtil.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/plugin/JGroupsUtil.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/plugin/JGroupsUtil.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -1,100 +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;
-
-/**
- * @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 JGroupsUtil
-{
-   // Constants -----------------------------------------------------
-
-   // Static --------------------------------------------------------
-
-   
-   public static String getDataStackProperties(int PING_timeout,
-                                               int PING_num_initial_members)
-   {
-      String host = System.getProperty("test.bind.address");
-      if (host == null)
-      {
-         host = "localhost";
-      }
-
-      return
-         "UDP(mcast_addr=228.8.8.8;mcast_port=45566;ip_ttl=32;bind_addr=" + host + "):" +
-         "PING(timeout=" + PING_timeout + ";num_initial_members=" + PING_num_initial_members + "):"+
-         "FD(timeout=3000):"+
-         "VERIFY_SUSPECT(timeout=1500):"+
-         "pbcast.NAKACK(gc_lag=10;retransmit_timeout=600,1200,2400,4800):"+
-         "pbcast.STABLE(desired_avg_gossip=10000):"+
-         "FRAG:"+
-         "pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=true;print_local_addr=true)"; 
-   }
-   
-
-   
-   /*
-    * The control stack is used for sending control messages and maintaining state
-    * It must be reliable and have the state protocol enabled
-    */
-   public static String getControlStackProperties(int PING_timeout,
-                                                  int PING_num_initial_members)
-   {
-      String host = System.getProperty("test.bind.address");
-      if (host == null)
-      {
-         host = "localhost";
-      }
-
-      return
-         "UDP(mcast_addr=228.8.8.8;mcast_port=45568;ip_ttl=32;bind_addr=" + host + "):" +
-         "PING(timeout=" + PING_timeout + ";num_initial_members=" + PING_num_initial_members + "):"+
-         "FD(timeout=3000):"+
-         "VERIFY_SUSPECT(timeout=1500):"+
-         "pbcast.NAKACK(gc_lag=10;retransmit_timeout=600,1200,2400,4800):"+
-         "pbcast.STABLE(desired_avg_gossip=10000):"+
-         "FRAG:"+
-         "pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=true;print_local_addr=true):" +
-         "pbcast.STATE_TRANSFER";     
-   }
-
-   // Attributes ----------------------------------------------------
-   
-   // Constructors --------------------------------------------------
-   
-   // Public --------------------------------------------------------
-
-   // Package protected ---------------------------------------------
-   
-   // Protected -----------------------------------------------------
-   
-   // Private -------------------------------------------------------
-   
-   // Inner classes -------------------------------------------------   
-}

Deleted: trunk/tests/src/org/jboss/test/messaging/core/plugin/SimplePostOfficeTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/plugin/SimplePostOfficeTest.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/plugin/SimplePostOfficeTest.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -1,988 +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.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.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.plugin.contract.PostOffice;
-import org.jboss.messaging.core.plugin.postoffice.Binding;
-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 org.jboss.test.messaging.util.CoreMessageFactory;
-
-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());
-         
-         Binding binding1 =
-            office1.bindQueue("durableQueue", "condition1", null, queue1);
-         
-         //Binding twice with the same name should fail      
-         try
-         {
-            Binding bindFail = office1.bindQueue("durableQueue", "condition1", null, 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());
-         Binding binding2 =
-            office1.bindQueue("nonDurableQueue", "condition2", null, 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 office 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 office 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());         
-         Binding binding1 =
-            office.bindQueue("queue1", "condition1", null, queue1);
-         
-         Queue queue2 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding2 =
-            office.bindQueue("queue2", "condition1", null, queue2);
-         
-         Queue queue3 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding3 =
-            office.bindQueue("queue3", "condition1", null, queue3);
-         
-         Queue queue4 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding4 =
-            office.bindQueue("queue4", "condition1", null, queue4);
-         
-         Queue queue5 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding5 =
-            office.bindQueue("queue5", "condition2", null, queue5);
-         
-         Queue queue6 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding6 =
-            office.bindQueue("queue6", "condition2", null, queue6);
-         
-         Queue queue7 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding7 =
-            office.bindQueue("queue7", "condition2", null, queue7);
-         
-         Queue queue8 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding8 =
-            office.bindQueue("queue8", "condition2", null, 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());         
-         Binding binding1 =
-            postOffice.bindQueue("queue1", "topic1", null, queue1);
-         
-         Queue queue2 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding2 =
-            postOffice.bindQueue("queue2", "topic1", null, queue2);
-         
-         Queue queue3 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding3 =
-            postOffice.bindQueue("queue3", "topic1", null, queue3);
-         
-         Queue queue4 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding4 =
-            postOffice.bindQueue("queue4", "topic2", null, queue4);
-         
-         Queue queue5 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding5 =
-            postOffice.bindQueue("queue5", "topic2", null, queue5);
-         
-         Queue queue6 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding6 =
-            postOffice.bindQueue("queue6", "topic2", null, 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 = CoreMessageFactory.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 = CoreMessageFactory.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());         
-         Binding binding1 =
-            postOffice.bindQueue("queue1", "condition1", null, queue1);
-              
-         SimpleReceiver receiver1 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
-         queue1.add(receiver1);
-   
-         assertTrue(binding1.isActive());
-   
-         Message msg1 = CoreMessageFactory.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());         
-         Binding binding1 =
-            postOffice.bindQueue("queue1", "topic1", null, queue1);
-         
-         Queue queue2 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding2 =
-            postOffice.bindQueue("queue2", "topic1", null, queue2);
-         
-         Queue queue3 = new Queue(im.getId(), ms, pm, true, false, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding3 =
-            postOffice.bindQueue("queue3", "topic1", null, queue3);
-         
-         Queue queue4 = new Queue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding4 =
-            postOffice.bindQueue("queue4", "topic2", null, queue4);
-         
-         Queue queue5 = new Queue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding5 =
-            postOffice.bindQueue("queue5", "topic2", null, queue5);
-         
-         Queue queue6 = new Queue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding6 =
-            postOffice.bindQueue("queue6", "topic2", null, 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 = CoreMessageFactory.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 = CoreMessageFactory.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());         
-         Binding binding1 =
-            postOffice.bindQueue("queue1", "topic1", null, queue1);
-         
-         Queue queue2 = new Queue(im.getId(), ms, pm, true, true, 2000, 100, 100, (QueuedExecutor)pool.get());         
-         Binding binding2 =
-            postOffice.bindQueue("queue2", "topic1", null, 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 = CoreMessageFactory.createCoreMessage(1, persistentMessage, null);      
-         MessageReference ref1 = ms.reference(msg1);
-         
-         Message msg2 = CoreMessageFactory.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 = CoreMessageFactory.createCoreMessage(3, persistentMessage, null);      
-         MessageReference ref3 = ms.reference(msg3);
-         
-         Message msg4 = CoreMessageFactory.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 = CoreMessageFactory.createCoreMessage(5, persistentMessage, null);      
-         MessageReference ref5 = ms.reference(msg5);
-         
-         Message msg6 = CoreMessageFactory.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 = CoreMessageFactory.createCoreMessage(7, persistentMessage, null);      
-         MessageReference ref7 = ms.reference(msg7);
-         
-         Message msg8 = CoreMessageFactory.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()); 
-      String selector1 = binding1.getFilter() != null ? binding1.getFilter().getFilterString() : null;
-      String selector2 = binding2.getFilter() != null ? binding2.getFilter().getFilterString() : null;
-      assertEquals(selector1, selector2);
-      assertEquals(binding1.getChannelId(), binding2.getChannelId());
-      assertEquals(binding1.isDurable(), binding2.isDurable());
-   }
-   
-   protected PostOffice createPostOffice() throws Exception
-   {
-      PostOfficeImpl postOffice = 
-         new PostOfficeImpl(sc.getDataSource(), sc.getTransactionManager(),
-                              null, true, "node1", "Simple", ms, tr);
-      
-      postOffice.start();      
-      
-      return postOffice;
-   }
-   // Private -------------------------------------------------------
-
-   // Inner classes -------------------------------------------------
-   
-}
-

Added: trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/SimpleFilter.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/SimpleFilter.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/SimpleFilter.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -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.test.messaging.core.plugin.postoffice;
+
+import org.jboss.messaging.core.Filter;
+import org.jboss.messaging.core.Routable;
+
+/**
+ * A SimpleFilter
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class SimpleFilter implements Filter
+{
+   long idMatch;
+   
+   public SimpleFilter(long idMatch)
+   {
+      this.idMatch = idMatch;
+   }
+
+   public boolean accept(Routable routable)
+   {
+      return routable.getMessageID() == idMatch;
+   }
+
+   public String getFilterString()
+   {
+      return String.valueOf(idMatch);
+   }
+   
+}

Added: trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/SimpleFilterFactory.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/SimpleFilterFactory.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/SimpleFilterFactory.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -0,0 +1,44 @@
+/*
+ * 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.postoffice;
+
+import org.jboss.messaging.core.Filter;
+import org.jboss.messaging.core.FilterFactory;
+
+/**
+ * A SimpleFilterFactory
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class SimpleFilterFactory implements FilterFactory
+{
+
+   public Filter createFilter(String filterString) throws Exception
+   {
+      return filterString == null ? null : new SimpleFilter(Long.valueOf(filterString).longValue());
+   }
+   
+}

Added: trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/SimplePostOfficeTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/SimplePostOfficeTest.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/SimplePostOfficeTest.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -0,0 +1,1132 @@
+/*
+  * 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.postoffice;
+
+import java.util.Collection;
+import java.util.Iterator;
+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.FilterFactory;
+import org.jboss.messaging.core.Message;
+import org.jboss.messaging.core.MessageReference;
+import org.jboss.messaging.core.local.PagingFilteredQueue;
+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.plugin.contract.PostOffice;
+import org.jboss.messaging.core.plugin.postoffice.Binding;
+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 org.jboss.test.messaging.util.CoreMessageFactory;
+
+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'");
+         
+         PagingFilteredQueue queue1 = new PagingFilteredQueue("durableQueue", im.getId(), ms, pm, true, true, (QueuedExecutor)pool.get(), null);
+         
+         
+         Binding binding1 =
+            office1.bindQueue("condition1", queue1);
+         
+         //Binding twice with the same name should fail      
+         try
+         {
+            Binding bindFail = office1.bindQueue("condition1", queue1);
+            fail();
+         }
+         catch (IllegalArgumentException e)
+         {
+            //Ok
+         }
+               
+         //Bind one non durable
+         PagingFilteredQueue queue2 = new PagingFilteredQueue("nonDurableQueue", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);
+         
+         Binding binding2 =
+            office1.bindQueue("condition2", 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 office 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 office 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();
+         
+         PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);
+         
+         Binding binding1 =
+            office.bindQueue("condition1", queue1);
+         
+         PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         
+         Binding binding2 =
+            office.bindQueue("condition1", queue2);
+         
+         PagingFilteredQueue queue3 = new PagingFilteredQueue("queue3", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         
+         Binding binding3 =
+            office.bindQueue("condition1", queue3);
+         
+         PagingFilteredQueue queue4 = new PagingFilteredQueue("queue4", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         
+         Binding binding4 =
+            office.bindQueue("condition1", queue4);
+         
+         PagingFilteredQueue queue5 = new PagingFilteredQueue("queue5", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         
+         Binding binding5 =
+            office.bindQueue("condition2", queue5);
+         
+         PagingFilteredQueue queue6 = new PagingFilteredQueue("queue6", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         
+         Binding binding6 =
+            office.bindQueue("condition2", queue6);
+         
+         PagingFilteredQueue queue7 = new PagingFilteredQueue("queue7", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         
+         Binding binding7 =
+            office.bindQueue("condition2", queue7);
+         
+         PagingFilteredQueue queue8 = new PagingFilteredQueue("queue8", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         
+         Binding binding8 =
+            office.bindQueue("condition2", queue8);
+         
+         
+         Collection 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());
+         
+         Iterator iter = bindings.iterator();
+         assertEquivalent((Binding)iter.next(), binding1);
+         assertEquivalent((Binding)iter.next(), binding2);
+         assertEquivalent((Binding)iter.next(), binding3);
+         assertEquivalent((Binding)iter.next(), binding4);
+         
+         bindings = office.listBindingsForCondition("condition2");
+         assertNotNull(bindings);
+         assertEquals(4, bindings.size());
+         
+         iter = bindings.iterator();
+         assertEquivalent((Binding)iter.next(), binding5);
+         assertEquivalent((Binding)iter.next(), binding6);
+         assertEquivalent((Binding)iter.next(), binding7);
+         assertEquivalent((Binding)iter.next(), binding8);
+      }
+      finally
+      {
+         if (office != null)
+         {
+            office.stop();
+         }
+      }
+         
+   }
+   
+   public void testRouteNonPersistentWithFilter() throws Throwable
+   {
+      routeWithFilter(false);
+   }
+   
+   public void testRoutePersistentWithFilter() throws Throwable
+   {
+      routeWithFilter(true);
+   }
+   
+   
+
+   
+   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();
+         
+         PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         
+         Binding binding1 =
+            postOffice.bindQueue("topic1", queue1);
+         
+         PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         
+         Binding binding2 =
+            postOffice.bindQueue("topic1", queue2);
+         
+         PagingFilteredQueue queue3 = new PagingFilteredQueue("queue3", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         
+         Binding binding3 =
+            postOffice.bindQueue("topic1", queue3);
+         
+         PagingFilteredQueue queue4 = new PagingFilteredQueue("queue4", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         
+         Binding binding4 =
+            postOffice.bindQueue("topic2", queue4);
+         
+         PagingFilteredQueue queue5 = new PagingFilteredQueue("queue5", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         
+         Binding binding5 =
+            postOffice.bindQueue("topic2", queue5);
+         
+         PagingFilteredQueue queue6 = new PagingFilteredQueue("queue6", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         
+         Binding binding6 =
+            postOffice.bindQueue("topic2", 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);
+         
+         queue1.deactivate();
+         queue2.deactivate();
+         queue5.deactivate();
+         queue6.deactivate();
+         
+         assertFalse(queue1.isActive());      
+         assertFalse(queue2.isActive());
+         assertFalse(queue5.isActive());
+         assertFalse(queue6.isActive()); 
+         assertTrue(queue3.isActive());
+         assertTrue(queue4.isActive());      
+         
+         Message msg1 = CoreMessageFactory.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 = CoreMessageFactory.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();
+         
+         PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         
+         Binding binding1 =
+            postOffice.bindQueue("condition1", queue1);
+              
+         SimpleReceiver receiver1 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
+         queue1.add(receiver1);
+   
+         assertTrue(queue1.isActive());
+   
+         Message msg1 = CoreMessageFactory.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 routeWithFilter(boolean persistentMessage) throws Throwable
+   {
+      PostOffice postOffice = null;
+      
+      try
+      {      
+         postOffice = createPostOffice();
+         
+         SimpleFilter filter = new SimpleFilter(2);
+      
+         PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), filter);         
+         
+         Binding binding1 =
+            postOffice.bindQueue("topic1", queue1);
+         
+         PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         
+         Binding binding2 =
+            postOffice.bindQueue("topic1", queue2);
+         
+         PagingFilteredQueue queue3 = new PagingFilteredQueue("queue3", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         
+         Binding binding3 =
+            postOffice.bindQueue("topic1", queue3);   
+         
+         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);
+         
+         Message msg1 = CoreMessageFactory.createCoreMessage(1);      
+         MessageReference ref1 = ms.reference(msg1);         
+         boolean routed = postOffice.route(ref1, "topic1", null);      
+         assertTrue(routed);
+         Message msg2 = CoreMessageFactory.createCoreMessage(2);      
+         MessageReference ref2 = ms.reference(msg2);         
+         routed = postOffice.route(ref2, "topic1", null);      
+         assertTrue(routed);
+         Message msg3 = CoreMessageFactory.createCoreMessage(3);      
+         MessageReference ref3 = ms.reference(msg3);         
+         routed = postOffice.route(ref3, "topic1", null);      
+         assertTrue(routed);
+         
+         List msgs = receiver1.getMessages();
+         assertNotNull(msgs);
+         assertEquals(1, msgs.size());
+         Message msgRec = (Message)msgs.get(0);
+         assertTrue(msg2 == msgRec);
+         receiver1.acknowledge(msgRec, null);
+         msgs = queue1.browse();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());  
+         
+         msgs = receiver2.getMessages();
+         assertNotNull(msgs);
+         assertEquals(3, msgs.size());
+         Message msgRec1 = (Message)msgs.get(0);
+         assertTrue(msg1 == msgRec1);
+         Message msgRec2 = (Message)msgs.get(1);
+         assertTrue(msg2 == msgRec2);
+         Message msgRec3 = (Message)msgs.get(2);
+         assertTrue(msg3 == msgRec3);
+          
+         receiver2.acknowledge(msgRec1, null);
+         receiver2.acknowledge(msgRec2, null);
+         receiver2.acknowledge(msgRec3, null);
+         msgs = queue2.browse();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());  
+         
+         msgs = receiver3.getMessages();
+         assertNotNull(msgs);
+         assertEquals(3, msgs.size());
+         msgRec1 = (Message)msgs.get(0);
+         assertTrue(msg1 == msgRec1);
+         msgRec2 = (Message)msgs.get(1);
+         assertTrue(msg2 == msgRec2);
+         msgRec3 = (Message)msgs.get(2);
+         assertTrue(msg3 == msgRec3);
+          
+         receiver3.acknowledge(msgRec1, null);
+         receiver3.acknowledge(msgRec2, null);
+         receiver3.acknowledge(msgRec3, null);
+         msgs = queue3.browse();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty()); 
+         
+      }
+      finally
+      {
+         if (postOffice != null)
+         {
+            postOffice.stop();
+         }
+      }
+   }
+   
+   protected void route(boolean persistentMessage) throws Throwable
+   {
+      PostOffice postOffice = null;
+      
+      try
+      {      
+         postOffice = createPostOffice();
+      
+         PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         
+         Binding binding1 =
+            postOffice.bindQueue("topic1", queue1);
+         
+         PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         
+         Binding binding2 =
+            postOffice.bindQueue("topic1", queue2);
+         
+         PagingFilteredQueue queue3 = new PagingFilteredQueue("queue3", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         
+         Binding binding3 =
+            postOffice.bindQueue("topic1", queue3);
+         
+         PagingFilteredQueue queue4 = new PagingFilteredQueue("queue4", im.getId(), ms, pm, true, true, (QueuedExecutor)pool.get(), null);         
+         
+         Binding binding4 =
+            postOffice.bindQueue("topic2", queue4);
+         
+         PagingFilteredQueue queue5 = new PagingFilteredQueue("queue5", im.getId(), ms, pm, true, true, (QueuedExecutor)pool.get(), null);         
+         
+         Binding binding5 =
+            postOffice.bindQueue("topic2", queue5);
+         
+         PagingFilteredQueue queue6 = new PagingFilteredQueue("queue6", im.getId(), ms, pm, true, true, (QueuedExecutor)pool.get(), null);         
+         
+         Binding binding6 =
+            postOffice.bindQueue("topic2", 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(queue1.isActive());      
+         assertTrue(queue2.isActive());
+         assertTrue(queue3.isActive());      
+         assertTrue(queue4.isActive());
+         assertTrue(queue5.isActive());      
+         assertTrue(queue6.isActive());
+         
+         Message msg1 = CoreMessageFactory.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 = CoreMessageFactory.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();
+      
+         PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);
+         
+         Binding binding1 =
+            postOffice.bindQueue("topic1", queue1);
+         
+         PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", im.getId(), ms, pm, true, true, (QueuedExecutor)pool.get(), null);
+         
+         Binding binding2 =
+            postOffice.bindQueue("topic1", queue2);
+          
+         SimpleReceiver receiver1 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
+         queue1.add(receiver1);
+
+         SimpleReceiver receiver2 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);;
+         queue2.add(receiver2);
+   
+         assertTrue(queue1.isActive());
+         assertTrue(queue2.isActive());
+   
+         Message msg1 = CoreMessageFactory.createCoreMessage(1, persistentMessage, null);      
+         MessageReference ref1 = ms.reference(msg1);
+         
+         Message msg2 = CoreMessageFactory.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 = CoreMessageFactory.createCoreMessage(3, persistentMessage, null);      
+         MessageReference ref3 = ms.reference(msg3);
+         
+         Message msg4 = CoreMessageFactory.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 = CoreMessageFactory.createCoreMessage(5, persistentMessage, null);      
+         MessageReference ref5 = ms.reference(msg5);
+         
+         Message msg6 = CoreMessageFactory.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 = CoreMessageFactory.createCoreMessage(7, persistentMessage, null);      
+         MessageReference ref7 = ms.reference(msg7);
+         
+         Message msg8 = CoreMessageFactory.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.getQueue().getName(), binding2.getQueue().getName()); 
+      String selector1 = binding1.getQueue().getFilter() != null ? binding1.getQueue().getFilter().getFilterString() : null;
+      String selector2 = binding2.getQueue().getFilter() != null ? binding2.getQueue().getFilter().getFilterString() : null;
+      assertEquals(selector1, selector2);
+      assertEquals(binding1.getQueue().getChannelID(), binding2.getQueue().getChannelID());
+      assertEquals(binding1.getQueue().isRecoverable(), binding2.getQueue().isRecoverable());
+   }
+   
+   protected PostOffice createPostOffice() throws Exception
+   {
+      FilterFactory ff = new SimpleFilterFactory();
+      
+      PostOfficeImpl postOffice = 
+         new PostOfficeImpl(sc.getDataSource(), sc.getTransactionManager(),
+                            null, true, "node1", "Simple", ms, pm, tr, ff, pool);
+      
+      postOffice.start();      
+      
+      return postOffice;
+   }
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}
+

Added: trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/BasicRedistributionPolicyTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/BasicRedistributionPolicyTest.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/BasicRedistributionPolicyTest.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -0,0 +1,76 @@
+/*
+  * 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.postoffice.cluster;
+
+import org.jboss.test.messaging.MessagingTestCase;
+import org.jboss.test.messaging.tools.ServerManagement;
+import org.jboss.test.messaging.tools.jmx.ServiceContainer;
+
+
+public class BasicRedistributionPolicyTest extends MessagingTestCase
+{
+   // Constants -----------------------------------------------------
+
+   // Static --------------------------------------------------------
+   
+   // Attributes ----------------------------------------------------
+
+   protected ServiceContainer sc;
+
+   // Constructors --------------------------------------------------
+
+   public BasicRedistributionPolicyTest(String name)
+   {
+      super(name);
+   }
+
+   // Public --------------------------------------------------------
+
+   public void setUp() throws Exception
+   {
+      super.setUp();
+
+      sc = new ServiceContainer("all");
+      
+      sc.start();                
+    
+      log.debug("setup done");
+   }
+
+   public void tearDown() throws Exception
+   {      
+      if (!ServerManagement.isRemote())
+      {
+         sc.stop();
+         sc = null;
+      }
+
+      super.tearDown();
+   }
+   
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}
+
+

Added: trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/ClusteredPostOfficeTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/ClusteredPostOfficeTest.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/ClusteredPostOfficeTest.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -0,0 +1,1501 @@
+/*
+  * 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.postoffice.cluster;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.jboss.messaging.core.FilterFactory;
+import org.jboss.messaging.core.Message;
+import org.jboss.messaging.core.MessageReference;
+import org.jboss.messaging.core.local.PagingFilteredQueue;
+import org.jboss.messaging.core.plugin.contract.ClusteredPostOffice;
+import org.jboss.messaging.core.plugin.postoffice.Binding;
+import org.jboss.messaging.core.plugin.postoffice.cluster.BasicRedistributionPolicy;
+import org.jboss.messaging.core.plugin.postoffice.cluster.ClusteredPostOfficeImpl;
+import org.jboss.messaging.core.plugin.postoffice.cluster.LocalClusteredQueue;
+import org.jboss.messaging.core.plugin.postoffice.cluster.RedistributionPolicy;
+import org.jboss.messaging.core.tx.Transaction;
+import org.jboss.test.messaging.core.SimpleReceiver;
+import org.jboss.test.messaging.core.plugin.postoffice.SimpleFilter;
+import org.jboss.test.messaging.core.plugin.postoffice.SimpleFilterFactory;
+import org.jboss.test.messaging.core.plugin.postoffice.SimplePostOfficeTest;
+import org.jboss.test.messaging.util.CoreMessageFactory;
+
+import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
+
+/**
+ * 
+ * A ClusteredPostOfficeTest
+ *
+ * @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 testClusteredBindUnbind() throws Throwable
+   {
+      ClusteredPostOffice office1 = null;
+      
+      ClusteredPostOffice office2 = null;
+      
+      ClusteredPostOffice office3 = null;
+      
+      try
+      {         
+         //Start one office
+         
+         office1 = createClusteredPostOffice("node1", "testgroup");
+         
+         //Add a couple of bindings
+         
+         LocalClusteredQueue queue1 = new LocalClusteredQueue("node1", "sub1", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);
+         
+         Binding binding1 =
+            office1.bindClusteredQueue("topic1", queue1);
+         LocalClusteredQueue queue2 = new LocalClusteredQueue("node1", "sub2", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);
+
+         Binding binding2 =
+            office1.bindClusteredQueue("topic1", queue2);
+         
+         //Start another office - make sure it picks up the bindings from the first node
+         
+         office2 = createClusteredPostOffice("node2", "testgroup");
+         
+         Collection bindings = office2.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(2, bindings.size());
+         
+         Iterator iter = bindings.iterator();
+         assertEquivalent(binding1, (Binding)iter.next());
+         assertEquivalent(binding2, (Binding)iter.next());         
+         
+         //Add another binding on node 2
+         
+         LocalClusteredQueue queue3 = new LocalClusteredQueue("node2", "sub3", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);
+
+         Binding binding3 =
+            office2.bindClusteredQueue("topic1", queue3);
+  
+         //Make sure both nodes pick it up
+         
+         bindings = office1.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(3, bindings.size());
+         
+         iter = bindings.iterator();
+         assertEquivalent(binding1, (Binding)iter.next());
+         assertEquivalent(binding2, (Binding)iter.next());
+         assertEquivalent(binding3, (Binding)iter.next());
+
+         bindings = office2.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(3, bindings.size());
+         
+         iter = bindings.iterator();
+         assertEquivalent(binding1, (Binding)iter.next());
+         assertEquivalent(binding2, (Binding)iter.next());
+         assertEquivalent(binding3, (Binding)iter.next());
+
+         //Add another binding on node 1
+         
+         LocalClusteredQueue queue4 = new LocalClusteredQueue("node2", "sub4", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);
+         Binding binding4 =
+            office2.bindClusteredQueue("topic1", queue4);
+         
+         // Make sure both nodes pick it up
+         
+         bindings = office1.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(4, bindings.size());
+         
+         iter = bindings.iterator();
+         assertEquivalent(binding1, (Binding)iter.next());
+         assertEquivalent(binding2, (Binding)iter.next());
+         assertEquivalent(binding3, (Binding)iter.next());
+         assertEquivalent(binding4, (Binding)iter.next());
+         
+         bindings = office2.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(4, bindings.size());
+         
+         iter = bindings.iterator();
+         assertEquivalent(binding1, (Binding)iter.next());
+         assertEquivalent(binding2, (Binding)iter.next());
+         assertEquivalent(binding3, (Binding)iter.next());
+         assertEquivalent(binding4, (Binding)iter.next());
+         
+         //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());
+         
+         iter = bindings.iterator();
+         assertEquivalent(binding3, (Binding)iter.next());
+         assertEquivalent(binding4, (Binding)iter.next());
+   
+         bindings = office2.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(2, bindings.size());
+         
+         iter = bindings.iterator();
+         assertEquivalent(binding3, (Binding)iter.next());
+         assertEquivalent(binding4, (Binding)iter.next());
+         
+         //Add a third office
+                  
+         office3 = createClusteredPostOffice("node3", "testgroup");
+         
+         //Maks sure it picks up the bindings
+         
+         bindings = office3.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(2, bindings.size());
+         
+         iter = bindings.iterator();
+         assertEquivalent(binding3, (Binding)iter.next());
+         assertEquivalent(binding4, (Binding)iter.next());
+         
+         //Add another binding on node 3
+                  
+         LocalClusteredQueue queue5 = new LocalClusteredQueue("node3", "sub5", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);
+         
+         Binding binding5 =
+            office3.bindClusteredQueue("topic1", queue5);
+         
+         // Make sure all nodes pick it up
+         
+         bindings = office1.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(3, bindings.size());
+         
+         iter = bindings.iterator();
+         assertEquivalent(binding3, (Binding)iter.next());
+         assertEquivalent(binding4, (Binding)iter.next());
+         assertEquivalent(binding5, (Binding)iter.next());
+         
+         bindings = office2.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(3, bindings.size());
+         
+         iter = bindings.iterator();
+         assertEquivalent(binding3, (Binding)iter.next());
+         assertEquivalent(binding4, (Binding)iter.next());
+         assertEquivalent(binding5, (Binding)iter.next());
+         
+         bindings = office3.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(3, bindings.size());
+         
+         iter = bindings.iterator();
+         assertEquivalent(binding3, (Binding)iter.next());
+         assertEquivalent(binding4, (Binding)iter.next());
+         assertEquivalent(binding5, (Binding)iter.next());
+         
+         //Add a durable and a non durable binding on node 1
+         
+         LocalClusteredQueue queue6 = new LocalClusteredQueue("node1", "sub6", im.getId(), ms, pm, true, true, (QueuedExecutor)pool.get(), null);         
+         
+         Binding binding6 =
+            office1.bindClusteredQueue("topic1", queue6);
+         
+         LocalClusteredQueue queue7 = new LocalClusteredQueue("node1", "sub7", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         
+         Binding binding7 =
+            office1.bindClusteredQueue("topic1", queue7);
+         
+         // Make sure all nodes pick them up
+         
+         bindings = office1.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(5, bindings.size());
+         
+         iter = bindings.iterator();
+         assertEquivalent(binding3, (Binding)iter.next());
+         assertEquivalent(binding4, (Binding)iter.next());
+         assertEquivalent(binding5, (Binding)iter.next());
+         assertEquivalent(binding6, (Binding)iter.next());
+         assertEquivalent(binding7, (Binding)iter.next());
+         
+         bindings = office2.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(5, bindings.size());
+         
+         iter = bindings.iterator();
+         assertEquivalent(binding3, (Binding)iter.next());
+         assertEquivalent(binding4, (Binding)iter.next());
+         assertEquivalent(binding5, (Binding)iter.next());
+         assertEquivalent(binding6, (Binding)iter.next());
+         assertEquivalent(binding7, (Binding)iter.next());
+         
+         bindings = office3.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(5, bindings.size());
+         
+         iter = bindings.iterator();
+         assertEquivalent(binding3, (Binding)iter.next());
+         assertEquivalent(binding4, (Binding)iter.next());
+         assertEquivalent(binding5, (Binding)iter.next());
+         assertEquivalent(binding6, (Binding)iter.next());
+         assertEquivalent(binding7, (Binding)iter.next());
+               
+         //Stop office 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());
+         
+         iter = bindings.iterator();
+         assertEquivalent(binding3, (Binding)iter.next());
+         assertEquivalent(binding4, (Binding)iter.next());
+         assertEquivalent(binding5, (Binding)iter.next());
+         assertEquivalent(binding6, (Binding)iter.next());
+         
+         bindings = office3.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(4, bindings.size());
+         
+         iter = bindings.iterator();
+         assertEquivalent(binding3, (Binding)iter.next());
+         assertEquivalent(binding4, (Binding)iter.next());
+         assertEquivalent(binding5, (Binding)iter.next());
+         assertEquivalent(binding6, (Binding)iter.next());
+         
+         //Stop office 2
+         office2.stop();
+         
+         bindings = office3.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(2, bindings.size());
+         
+         iter = bindings.iterator();
+         assertEquivalent(binding5, (Binding)iter.next());
+         assertEquivalent(binding6, (Binding)iter.next());
+         
+         //Restart office 1 and office 2
+         office1 = createClusteredPostOffice("node1", "testgroup");
+         
+         office2 = createClusteredPostOffice("node2", "testgroup");
+         
+         bindings = office1.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(2, bindings.size());
+         
+         iter = bindings.iterator();
+         assertEquivalent(binding5, (Binding)iter.next());
+         assertEquivalent(binding6, (Binding)iter.next());
+         
+         bindings = office2.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(2, bindings.size());
+         
+         iter = bindings.iterator();
+         assertEquivalent(binding5, (Binding)iter.next());
+         assertEquivalent(binding6, (Binding)iter.next());
+         
+         bindings = office3.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(2, bindings.size());
+         
+         iter = bindings.iterator();
+         assertEquivalent(binding5, (Binding)iter.next());
+         assertEquivalent(binding6, (Binding)iter.next());
+         
+         //Stop all offices
+         
+         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());
+         
+         iter = bindings.iterator();
+         assertEquivalent(binding6, (Binding)iter.next());
+         
+         bindings = office2.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(1, bindings.size());
+         
+         iter = bindings.iterator();
+         assertEquivalent(binding6, (Binding)iter.next());
+         
+         bindings = office3.listBindingsForCondition("topic1");
+         assertNotNull(bindings);
+         assertEquals(1, bindings.size());
+         
+         iter = bindings.iterator();
+         assertEquivalent(binding6, (Binding)iter.next());
+                  
+      }
+      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);
+   }
+   
+   public void testClusteredNonPersistentRouteWithFilter() throws Throwable
+   {
+      this.clusteredRouteWithFilter(false);
+   }
+   
+   public void testClusteredPersistentRouteWithFilter() throws Throwable
+   {
+      this.clusteredRouteWithFilter(true);
+   }
+   
+   public final void testRedistribute() throws Exception
+   {
+      ClusteredPostOffice office1 = null;
+      
+      ClusteredPostOffice office2 = null;
+          
+      try
+      {   
+         office1 = createClusteredPostOffice("node1", "testgroup");
+         office2 = createClusteredPostOffice("node2", "testgroup");
+         
+         LocalClusteredQueue queue1 = new LocalClusteredQueue("node1", "queue1", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);
+         
+         Binding binding1 = office1.bindClusteredQueue("queue1", queue1);
+         
+         LocalClusteredQueue queue2 = new LocalClusteredQueue("node2", "queue1", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);
+         
+         Binding binding2 = office2.bindClusteredQueue("queue1", queue1);
+         
+         final int NUM_MESSAGES = 10;
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            Message msg = CoreMessageFactory.createCoreMessage(i, false, null);      
+            MessageReference ref = ms.reference(msg);         
+            boolean routed = office1.route(ref, "queue1", null);
+         }
+         
+         List msgs = queue1.browse();
+         assertEquals(NUM_MESSAGES, msgs.size());
+         msgs = queue2.browse();
+         assertEquals(0, msgs.size());
+         
+         
+      
+      }
+      finally
+      {
+         if (office1 != null)
+         {            
+            office1.stop();
+         }
+         
+         if (office2 != null)
+         {
+            office2.stop();
+         }
+      }
+   }
+   
+   /*
+    * We should allow the clustered bind of queues with the same queue name on different nodes of the
+    * cluster
+    */
+   public void testClusteredNameUniqueness() throws Throwable
+   {
+      ClusteredPostOffice office1 = null;
+      
+      ClusteredPostOffice office2 = null;
+          
+      try
+      {   
+         office1 = createClusteredPostOffice("node1", "testgroup");
+         
+         office2 = createClusteredPostOffice("node2", "testgroup");
+         
+         LocalClusteredQueue queue1 = new LocalClusteredQueue("node1", "queue1", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);
+         
+         Binding binding1 = office1.bindClusteredQueue("queue1", queue1);
+         
+         LocalClusteredQueue queue2 = new LocalClusteredQueue("node2", "queue1", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);
+         
+         Binding binding2 = office2.bindClusteredQueue("queue1", queue2);
+                  
+         LocalClusteredQueue queue3 = new LocalClusteredQueue("node1", "queue1", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);
+         
+         try
+         {
+            Binding binding3 = office1.bindClusteredQueue("queue1", queue3);
+            fail();
+         }
+         catch (Exception e)
+         {
+            //Ok
+         }
+         LocalClusteredQueue queue4 = new LocalClusteredQueue("node2", "queue1", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);
+         
+         try
+         {
+            Binding binding4 = office2.bindClusteredQueue("queue1", queue4);
+            fail();
+         }
+         catch (Exception e)
+         {
+            //Ok
+         }
+         
+         office1.unbindClusteredQueue("queue1");
+         
+         office2.unbindClusteredQueue("queue1");
+         
+         LocalClusteredQueue queue5 = new LocalClusteredQueue("node1", "queue1", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);
+         
+         Binding binding5 = office1.bindClusteredQueue("queue1", queue5);
+         
+         PagingFilteredQueue queue6 = new PagingFilteredQueue("queue1", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);       
+         try
+         {
+            Binding binding6 = office1.bindQueue("queue1", queue6);
+            fail();
+         }
+         catch (Exception e)
+         {
+            //ok
+         }
+         
+         try
+         {
+            office1.unbindQueue("queue1");
+            fail();
+         }
+         catch (Exception e)
+         {
+            //ok
+         }
+         
+         office1.unbindClusteredQueue("queue1");
+         
+         PagingFilteredQueue queue7 = new PagingFilteredQueue("queue1", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);       
+         Binding binding7 = office1.bindQueue("queue1", queue7);
+         
+         PagingFilteredQueue queue8 = new PagingFilteredQueue("queue1", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);       
+         Binding binding8 = office2.bindQueue("queue1", queue8);
+         
+         PagingFilteredQueue queue9 = new PagingFilteredQueue("queue1", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);    
+         try
+         {
+            Binding binding9 = office1.bindQueue("queue1", queue9);
+            fail();
+         }
+         catch (Exception e)
+         {
+            //Ok
+         }
+
+      }
+      finally
+      {
+         if (office1 != null)
+         {            
+            office1.stop();
+         }
+         
+         if (office2 != null)
+         {
+            office2.stop();
+         }
+      }
+   }
+   
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+   
+   protected void clusteredRouteWithFilter(boolean persistentMessage) throws Throwable
+   {
+      ClusteredPostOffice office1 = null;
+      
+      ClusteredPostOffice office2 = null;
+          
+      try
+      {   
+         office1 = createClusteredPostOffice("node1", "testgroup");
+         office2 = createClusteredPostOffice("node2", "testgroup");
+         
+         SimpleFilter filter1 = new SimpleFilter(2);
+         SimpleFilter filter2 = new SimpleFilter(3);
+      
+         LocalClusteredQueue queue1 = new LocalClusteredQueue("node1", "queue1", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), filter1);         
+         Binding binding1 =
+            office1.bindClusteredQueue("topic1", queue1);
+         
+         LocalClusteredQueue queue2 = new LocalClusteredQueue("node2", "queue2", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), filter2);         
+         Binding binding2 =
+            office2.bindClusteredQueue("topic1", queue2);
+         
+         LocalClusteredQueue queue3 = new LocalClusteredQueue("node3", "queue3", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         Binding binding3 =
+            office2.bindClusteredQueue("topic1", queue3);   
+         
+         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);
+         
+         Message msg1 = CoreMessageFactory.createCoreMessage(1);      
+         MessageReference ref1 = ms.reference(msg1);         
+         boolean routed = office1.route(ref1, "topic1", null);      
+         assertTrue(routed);
+         Message msg2 = CoreMessageFactory.createCoreMessage(2);      
+         MessageReference ref2 = ms.reference(msg2);         
+         routed = office1.route(ref2, "topic1", null);      
+         assertTrue(routed);
+         Message msg3 = CoreMessageFactory.createCoreMessage(3);      
+         MessageReference ref3 = ms.reference(msg3);         
+         routed = office1.route(ref3, "topic1", null);      
+         assertTrue(routed);
+         
+         List msgs = receiver1.getMessages();
+         assertNotNull(msgs);
+         assertEquals(1, msgs.size());
+         Message msgRec = (Message)msgs.get(0);
+         assertTrue(msg2 == 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(msg3 == msgRec);
+         receiver2.acknowledge(msgRec, null);
+         msgs = queue2.browse();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty());  
+         
+         msgs = receiver3.getMessages();
+         assertNotNull(msgs);
+         assertEquals(3, msgs.size());
+         Message msgRec1 = (Message)msgs.get(0);
+         assertTrue(msg1 == msgRec1);
+         Message msgRec2 = (Message)msgs.get(1);
+         assertTrue(msg2 == msgRec2);
+         Message msgRec3 = (Message)msgs.get(2);
+         assertTrue(msg3 == msgRec3);
+          
+         receiver3.acknowledge(msgRec1, null);
+         receiver3.acknowledge(msgRec2, null);
+         receiver3.acknowledge(msgRec3, null);
+         msgs = queue3.browse();
+         assertNotNull(msgs);
+         assertTrue(msgs.isEmpty()); 
+         
+      }
+      finally
+      {
+         if (office1 != null)
+         {
+            office1.stop();
+         }
+         
+         if (office2 != null)
+         {
+            office2.stop();
+         }
+      }
+   }
+   
+   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
+         
+         LocalClusteredQueue[] queues = new LocalClusteredQueue[16];
+         Binding[] bindings = new Binding[16];
+         
+         queues[0] = new LocalClusteredQueue("node1", "sub1", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         bindings[0] = office1.bindClusteredQueue("topic1", queues[0]);
+         
+         queues[1] = new LocalClusteredQueue("node1", "sub2", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         bindings[1] = office1.bindClusteredQueue("topic1", queues[1]);
+         
+         queues[2] = new LocalClusteredQueue("node2", "sub3", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         bindings[2] = office2.bindClusteredQueue("topic1", queues[2]);
+         
+         queues[3] = new LocalClusteredQueue("node2", "sub4", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         bindings[3] = office2.bindClusteredQueue("topic1", queues[3]);
+         
+         queues[4] = new LocalClusteredQueue("node2", "sub5", im.getId(), ms, pm, true, true, (QueuedExecutor)pool.get(), null);         
+         bindings[4] = office2.bindClusteredQueue("topic1", queues[4]);
+         
+         queues[5] = new LocalClusteredQueue("node1", "sub6", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         bindings[5] = office1.bindClusteredQueue("topic1", queues[5]);
+         
+         queues[6] = new LocalClusteredQueue("node1", "sub7", im.getId(), ms, pm, true, true, (QueuedExecutor)pool.get(), null);         
+         bindings[6] = office1.bindClusteredQueue("topic1", queues[6]);
+         
+         queues[7] = new LocalClusteredQueue("node1", "sub8", im.getId(), ms, pm, true, true, (QueuedExecutor)pool.get(), null);         
+         bindings[7] = office1.bindClusteredQueue("topic1", queues[7]);
+         
+         queues[8] = new LocalClusteredQueue("node2", "sub9", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         bindings[8] = office1.bindClusteredQueue("topic2", queues[8]);
+         
+         queues[9] = new LocalClusteredQueue("node2", "sub10", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         bindings[9] = office1.bindClusteredQueue("topic2", queues[9]);
+         
+         queues[10] = new LocalClusteredQueue("node2", "sub11", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         bindings[10] = office2.bindClusteredQueue("topic2", queues[10]);
+         
+         queues[11] = new LocalClusteredQueue("node2", "sub12", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         bindings[11] = office2.bindClusteredQueue("topic2", queues[11]);
+         
+         queues[12] = new LocalClusteredQueue("node2", "sub13", im.getId(), ms, pm, true, true, (QueuedExecutor)pool.get(), null);         
+         bindings[12] = office2.bindClusteredQueue("topic2", queues[12]);
+         
+         queues[13] = new LocalClusteredQueue("node1", "sub14", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         bindings[13] = office1.bindClusteredQueue("topic2", queues[13]);
+         
+         queues[14] = new LocalClusteredQueue("node1", "sub15", im.getId(), ms, pm, true, true, (QueuedExecutor)pool.get(), null);         
+         bindings[14] = office1.bindClusteredQueue("topic2", queues[14]);
+         
+         queues[15] = new LocalClusteredQueue("node1", "sub16", im.getId(), ms, pm, true, true, (QueuedExecutor)pool.get(), null);         
+         bindings[15] = office1.bindClusteredQueue("topic2", 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 = CoreMessageFactory.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++)
+         {         
+            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 = CoreMessageFactory.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");
+     
+         LocalClusteredQueue[] queues = new LocalClusteredQueue[16];
+         Binding[] bindings = new Binding[16];
+         
+         queues[0] = new LocalClusteredQueue("node1", "sub1", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         bindings[0] = office1.bindClusteredQueue("topic1", queues[0]);
+         
+         queues[1] = new LocalClusteredQueue("node1", "sub2", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         bindings[1] = office1.bindClusteredQueue("topic1", queues[1]);
+         
+         queues[2] = new LocalClusteredQueue("node2", "sub3", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         bindings[2] = office2.bindClusteredQueue("topic1", queues[2]);
+         
+         queues[3] = new LocalClusteredQueue("node2", "sub4", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         bindings[3] = office2.bindClusteredQueue("topic1", queues[3]);
+         
+         queues[4] = new LocalClusteredQueue("node2", "sub5", im.getId(), ms, pm, true, true, (QueuedExecutor)pool.get(), null);         
+         bindings[4] = office2.bindClusteredQueue("topic1", queues[4]);
+         
+         queues[5] = new LocalClusteredQueue("node1", "sub6", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         bindings[5] = office1.bindClusteredQueue("topic1", queues[5]);
+         
+         queues[6] = new LocalClusteredQueue("node1", "sub7", im.getId(), ms, pm, true, true, (QueuedExecutor)pool.get(), null);         
+         bindings[6] = office1.bindClusteredQueue("topic1", queues[6]);
+         
+         queues[7] = new LocalClusteredQueue("node1", "sub8", im.getId(), ms, pm, true, true, (QueuedExecutor)pool.get(), null);         
+         bindings[7] = office1.bindClusteredQueue("topic1", queues[7]);
+         
+         queues[8] = new LocalClusteredQueue("node1", "sub9", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         bindings[8] = office1.bindClusteredQueue("topic2", queues[8]);
+         
+         queues[9] = new LocalClusteredQueue("node1", "sub10", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         bindings[9] = office1.bindClusteredQueue("topic2", queues[9]);
+         
+         queues[10] = new LocalClusteredQueue("node2", "sub11", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         bindings[10] = office2.bindClusteredQueue("topic2", queues[10]);
+         
+         queues[11] = new LocalClusteredQueue("node2", "sub12", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         bindings[11] = office2.bindClusteredQueue("topic2", queues[11]);
+         
+         queues[12] = new LocalClusteredQueue("node2", "sub13", im.getId(), ms, pm, true, true, (QueuedExecutor)pool.get(), null);         
+         bindings[12] = office2.bindClusteredQueue("topic2", queues[12]);
+         
+         queues[13] = new LocalClusteredQueue("node1", "sub14", im.getId(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);         
+         bindings[13] = office1.bindClusteredQueue("topic2", queues[13]);
+         
+         queues[14] = new LocalClusteredQueue("node1", "sub15", im.getId(), ms, pm, true, true, (QueuedExecutor)pool.get(), null);         
+         bindings[14] = office1.bindClusteredQueue("topic2", queues[14]);
+         
+         queues[15] = new LocalClusteredQueue("node1", "sub16", im.getId(), ms, pm, true, true, (QueuedExecutor)pool.get(), null);         
+         bindings[15] = office1.bindClusteredQueue("topic2", 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 = CoreMessageFactory.createCoreMessage(1, persistent, null);;      
+         MessageReference ref1 = ms.reference(msg1);
+         
+         Message msg2 = CoreMessageFactory.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 = CoreMessageFactory.createCoreMessage(1, persistent, null);;      
+         ref1 = ms.reference(msg1);
+         
+         msg2 = CoreMessageFactory.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 = CoreMessageFactory.createCoreMessage(1, persistent, null);
+         ref1 = ms.reference(msg1);
+         
+         msg2 = CoreMessageFactory.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 = CoreMessageFactory.createCoreMessage(1, persistent, null);;      
+         ref1 = ms.reference(msg1);
+         
+         msg2 = CoreMessageFactory.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 = CoreMessageFactory.createCoreMessage(1, persistent, null);    
+         ref1 = ms.reference(msg1);
+         
+         msg2 = CoreMessageFactory.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 = CoreMessageFactory.createCoreMessage(1, persistent, null);;      
+         ref1 = ms.reference(msg1);
+         
+         msg2 = CoreMessageFactory.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 = CoreMessageFactory.createCoreMessage(1, persistent, null);      
+         ref1 = ms.reference(msg1);
+         
+         msg2 = CoreMessageFactory.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 = CoreMessageFactory.createCoreMessage(1, persistent, null);;      
+         ref1 = ms.reference(msg1);
+         
+         msg2 = CoreMessageFactory.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
+   {
+      RedistributionPolicy redistPolicy = new BasicRedistributionPolicy(nodeId);
+      
+      FilterFactory ff = new SimpleFilterFactory();
+      
+      ClusteredPostOfficeImpl postOffice = 
+         new ClusteredPostOfficeImpl(sc.getDataSource(), sc.getTransactionManager(),
+                                 null, true, nodeId, "Clustered", ms, pm, tr, ff, pool,
+                                 groupName,
+                                 JGroupsUtil.getControlStackProperties(50, 1),
+                                 JGroupsUtil.getDataStackProperties(50, 1),
+                                 5000, 5000, redistPolicy, 1000);
+      
+      postOffice.start();      
+      
+      return postOffice;
+   }
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}
+
+
+

Added: trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/JGroupsUtil.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/JGroupsUtil.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/JGroupsUtil.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -0,0 +1,100 @@
+/**
+ * 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.postoffice.cluster;
+
+/**
+ * @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: 1252 $</tt>
+ *
+ * $Id: JGroupsUtil.java 1252 2006-09-01 22:07:43Z timfox $
+ */
+public class JGroupsUtil
+{
+   // Constants -----------------------------------------------------
+
+   // Static --------------------------------------------------------
+
+   
+   public static String getDataStackProperties(int PING_timeout,
+                                               int PING_num_initial_members)
+   {
+      String host = System.getProperty("test.bind.address");
+      if (host == null)
+      {
+         host = "localhost";
+      }
+
+      return
+         "UDP(mcast_addr=228.8.8.8;mcast_port=45566;ip_ttl=32;bind_addr=" + host + "):" +
+         "PING(timeout=" + PING_timeout + ";num_initial_members=" + PING_num_initial_members + "):"+
+         "FD(timeout=3000):"+
+         "VERIFY_SUSPECT(timeout=1500):"+
+         "pbcast.NAKACK(gc_lag=10;retransmit_timeout=600,1200,2400,4800):"+
+         "pbcast.STABLE(desired_avg_gossip=10000):"+
+         "FRAG:"+
+         "pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=true;print_local_addr=true)"; 
+   }
+   
+
+   
+   /*
+    * The control stack is used for sending control messages and maintaining state
+    * It must be reliable and have the state protocol enabled
+    */
+   public static String getControlStackProperties(int PING_timeout,
+                                                  int PING_num_initial_members)
+   {
+      String host = System.getProperty("test.bind.address");
+      if (host == null)
+      {
+         host = "localhost";
+      }
+
+      return
+         "UDP(mcast_addr=228.8.8.8;mcast_port=45568;ip_ttl=32;bind_addr=" + host + "):" +
+         "PING(timeout=" + PING_timeout + ";num_initial_members=" + PING_num_initial_members + "):"+
+         "FD(timeout=3000):"+
+         "VERIFY_SUSPECT(timeout=1500):"+
+         "pbcast.NAKACK(gc_lag=10;retransmit_timeout=600,1200,2400,4800):"+
+         "pbcast.STABLE(desired_avg_gossip=10000):"+
+         "FRAG:"+
+         "pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;shun=true;print_local_addr=true):" +
+         "pbcast.STATE_TRANSFER";     
+   }
+
+   // Attributes ----------------------------------------------------
+   
+   // Constructors --------------------------------------------------
+   
+   // Public --------------------------------------------------------
+
+   // Package protected ---------------------------------------------
+   
+   // Protected -----------------------------------------------------
+   
+   // Private -------------------------------------------------------
+   
+   // Inner classes -------------------------------------------------   
+}

Deleted: trunk/tests/src/org/jboss/test/messaging/jms/DurableSubscriberTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/DurableSubscriberTest.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/jms/DurableSubscriberTest.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -1,473 +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.jms;
-
-import javax.jms.Connection;
-import javax.jms.ConnectionFactory;
-import javax.jms.DeliveryMode;
-import javax.jms.InvalidDestinationException;
-import javax.jms.InvalidSelectorException;
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageProducer;
-import javax.jms.Session;
-import javax.jms.TextMessage;
-import javax.jms.Topic;
-import javax.management.ObjectName;
-import javax.naming.InitialContext;
-import javax.naming.NamingException;
-
-import org.jboss.test.messaging.MessagingTestCase;
-import org.jboss.test.messaging.tools.ServerManagement;
-
-/**
- * Tests focused on durable subscription behavior. More durable subscription tests can be found in
- * MessageConsumerTest.
- *
- * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
- * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
- *
- * $Id$
- */
-public class DurableSubscriberTest extends MessagingTestCase
-{
-   // Constants -----------------------------------------------------
-
-   // Static --------------------------------------------------------
-
-   // Attributes ----------------------------------------------------
-
-   protected InitialContext ic;
-
-   // Constructors --------------------------------------------------
-
-   public DurableSubscriberTest(String name)
-   {
-      super(name);
-   }
-
-   // Public --------------------------------------------------------
-
-   public void setUp() throws Exception
-   {
-      super.setUp();
-
-      ServerManagement.start("all");
-            
-      ServerManagement.undeployTopic("Topic");
-      ServerManagement.deployTopic("Topic");
-
-      ic = new InitialContext(ServerManagement.getJNDIEnvironment());
-
-      log.debug("setup done");
-   }
-
-   public void tearDown() throws Exception
-   {
-      log.debug("starting tear down");
-
-      ic.close();
-
-      ServerManagement.undeployTopic("Topic");
-        
-      super.tearDown();
-   }
-
-   public void testSimplestDurableSubscription() throws Exception
-   {
-      ConnectionFactory cf = (ConnectionFactory)ic.lookup("ConnectionFactory");
-      Topic topic = (Topic)ic.lookup("/topic/Topic");
-      Connection conn = cf.createConnection();
-
-      conn.setClientID("brookeburke");
-
-      Session s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-      MessageProducer prod = s.createProducer(topic);
-      prod.setDeliveryMode(DeliveryMode.PERSISTENT);
-
-      s.createDurableSubscriber(topic, "monicabelucci");
-      
-      ObjectName destObjectName = 
-         new ObjectName("jboss.messaging.destination:service=Topic,name=Topic");
-      String text = (String)ServerManagement.invoke(destObjectName, "listSubscriptionsAsText", null, null);
-       
-      assertTrue(text.indexOf("monicabelucci") != -1);
-
-      prod.send(s.createTextMessage("k"));
-
-      conn.close();
-
-      text = (String)ServerManagement.invoke(destObjectName, "listSubscriptionsAsText", null, null);
-      
-      assertTrue(text.indexOf("monicabelucci") != -1);
-
-      conn = cf.createConnection();
-      conn.setClientID("brookeburke");
-
-      s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
-      MessageConsumer durable = s.createDurableSubscriber(topic, "monicabelucci");
-
-      conn.start();
-
-      TextMessage tm = (TextMessage)durable.receive();
-      assertEquals("k", tm.getText());
-
-      Message m = durable.receive(1000);
-      assertNull(m);
-   }
-
-   /**
-    * JMS 1.1 6.11.1: A client can change an existing durable subscription by creating a durable
-    * TopicSubscriber with the same name and a new topic and/or message selector, or NoLocal
-    * attribute. Changing a durable subscription is equivalent to deleting and recreating it.
-    *
-    * Test with a different topic (a redeployed topic is a different topic).
-    */
-   public void testDurableSubscriptionOnNewTopic() throws Exception
-   {
-      ServerManagement.deployTopic("CompletelyNewTopic");
-
-      ConnectionFactory cf = (ConnectionFactory)ic.lookup("ConnectionFactory");
-      Topic topic = (Topic)ic.lookup("/topic/CompletelyNewTopic");
-      Connection conn = cf.createConnection();
-
-      conn.setClientID("brookeburke");
-
-      Session s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-      MessageProducer prod = s.createProducer(topic);
-      prod.setDeliveryMode(DeliveryMode.PERSISTENT);
-
-      s.createDurableSubscriber(topic, "monicabelucci");
-
-      prod.send(s.createTextMessage("one"));
-
-      conn.close();
-
-      ServerManagement.deployTopic("CompletelyNewTopic2");
-
-      Topic topic2 = (Topic)ic.lookup("/topic/CompletelyNewTopic2");
-      conn = cf.createConnection();
-
-      conn.setClientID("brookeburke");
-
-      s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-      MessageConsumer durable = s.createDurableSubscriber(topic2, "monicabelucci");
-
-      conn.start();
-
-      Message m = durable.receive(1000);
-      assertNull(m);
-
-      ServerManagement.undeployTopic("CompletelyNewTopic");
-      ServerManagement.undeployTopic("CompletelyNewTopic2");
-   }
-
-   /**
-    * JMS 1.1 6.11.1: A client can change an existing durable subscription by creating a durable
-    * TopicSubscriber with the same name and a new topic and/or message selector, or NoLocal
-    * attribute. Changing a durable subscription is equivalent to deleting and recreating it.
-    *
-    * Test with a different selector.
-    */
-   public void testDurableSubscriptionDifferentSelector() throws Exception
-   {
-      ServerManagement.deployTopic("CompletelyNewTopic2");
-      
-      ConnectionFactory cf = (ConnectionFactory)ic.lookup("ConnectionFactory");
-      Topic topic = (Topic)ic.lookup("/topic/Topic");
-      Connection conn = cf.createConnection();
-
-      conn.setClientID("brookeburke");
-
-      Session s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-      MessageProducer prod = s.createProducer(topic);
-      prod.setDeliveryMode(DeliveryMode.PERSISTENT);
-
-      
-      //fails here
-      MessageConsumer durable =
-         s.createDurableSubscriber(topic,
-                                   "monicabelucci",
-                                   "color = 'red' AND shape = 'square'",
-                                   false);
-
-      TextMessage tm = s.createTextMessage("A red square message");
-      tm.setStringProperty("color", "red");
-      tm.setStringProperty("shape", "square");
-      prod.send(tm);
-
-      conn.start();
-
-      TextMessage rm = (TextMessage)durable.receive(5000);
-      assertEquals("A red square message", rm.getText());
-
-      tm = s.createTextMessage("Another red square message");
-      tm.setStringProperty("color", "red");
-      tm.setStringProperty("shape", "square");
-      prod.send(tm);
-
-      // TODO: when subscriptions/durable subscription will be registered as MBean, use the JMX
-      //       interface to make sure the 'another red square message' is maintained by the
-      //       durable subascription
-      //       http://jira.jboss.org/jira/browse/JBMESSAGING-217
-
-      conn.close();
-
-      conn = cf.createConnection();
-
-      conn.setClientID("brookeburke");
-
-      s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
-      // modify the selector
-      durable = s.createDurableSubscriber(topic,
-                                          "monicabelucci",
-                                          "color = 'red'",
-                                          false);
-
-      conn.start();
-
-      Message m = durable.receive(1000);
-
-      // the durable subscription is destroyed and re-created. The red square message stored by
-      // the previous durable subscription is lost and (hopefully) garbage collected.
-      assertNull(m);
-      
-      ServerManagement.undeployTopic("CompletelyNewTopic2");
-   }
-
-   /**
-    * JMS 1.1 6.11.1: A client can change an existing durable subscription by creating a durable
-    * TopicSubscriber with the same name and a new topic and/or message selector, or NoLocal
-    * attribute. Changing a durable subscription is equivalent to deleting and recreating it.
-    *
-    * Test with a different noLocal flag.
-    */
-   public void testDurableSubscriptionDifferentNoLocal() throws Exception
-   {
-      ConnectionFactory cf = (ConnectionFactory)ic.lookup("ConnectionFactory");
-      Topic topic = (Topic)ic.lookup("/topic/Topic");
-
-      Connection conn = cf.createConnection();
-      conn.setClientID("ID0");
-
-      Session s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-      MessageProducer prod = s.createProducer(topic);
-      prod.setDeliveryMode(DeliveryMode.PERSISTENT);
-
-      MessageConsumer durable = s.createDurableSubscriber(topic, "mySubscription", null, false);
-
-      TextMessage tm = null;
-      tm = s.createTextMessage("Message One");
-      prod.send(tm);
-      tm = s.createTextMessage("Message Two");
-      prod.send(tm);
-
-
-      conn.start();
-
-      TextMessage rm = (TextMessage)durable.receive(5000);
-      assertEquals("Message One", rm.getText());
-
-      // TODO: when subscriptions/durable subscription will be registered as MBean, use the JMX
-      //       interface to make sure the 'another red square message' is maintained by the
-      //       durable subascription
-
-      conn.close();
-
-      conn = cf.createConnection();
-      conn.setClientID("ID0");
-      s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
-      // modify the nolocal flag
-      durable = s.createDurableSubscriber(topic, "mySubscription", null, true);
-
-      conn.start();
-
-      Message m = durable.receive(1000);
-
-      // the durable subscription is destroyed and re-created. "Message Two" stored by the previous
-      // durable subscription is lost and (hopefully) garbage collected.
-      assertNull(m);
-   }
-
-   public void testDurableSubscriptionOnTemporaryTopic() throws Exception
-   {
-      ConnectionFactory cf = (ConnectionFactory)ic.lookup("ConnectionFactory");
-      Connection conn = cf.createConnection();
-      conn.setClientID("doesn't actually matter");
-      Session s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-      Topic temporaryTopic = s.createTemporaryTopic();
-
-      try
-      {
-         s.createDurableSubscriber(temporaryTopic, "mySubscription");
-         fail("this should throw exception");
-      }
-      catch(InvalidDestinationException e)
-      {
-         // OK
-      }
-   }
-
-   /**
-    * Topic undeployment/redeployment has an activation/deactivation semantic, so undeploying a
-    * topic for which there are durable subscriptions preserves the content of those durable
-    * subscriptions, which can be then access upon topic redeployment.
-    * @throws Exception
-    */
-   public void testDurableSubscriptionOnTopicRedeployment() throws Exception
-   {
-      try
-      {
-         ic.lookup("/topic/TopicToBeRedeployed");
-         fail("should throw exception, topic shouldn't be deployed on the server");
-      }
-      catch(NamingException e)
-      {
-         // OK
-      }
-
-      ServerManagement.deployTopic("TopicToBeRedeployed");
-
-      ConnectionFactory cf = (ConnectionFactory)ic.lookup("ConnectionFactory");
-      Topic topic = (Topic)ic.lookup("/topic/TopicToBeRedeployed");
-
-      Connection conn = cf.createConnection();
-      conn.setClientID("brookeburke");
-
-      Session s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-      MessageProducer prod = s.createProducer(topic);
-      prod.setDeliveryMode(DeliveryMode.PERSISTENT);
-      MessageConsumer ds = s.createDurableSubscriber(topic, "monicabelucci");
-      conn.start();
-
-      prod.send(s.createTextMessage("one"));
-      prod.send(s.createTextMessage("two"));
-      
-      ServerManagement.undeployTopic("TopicToBeRedeployed");
-      log.debug("topic undeployed");
-
-      try
-      {
-         topic = (Topic)ic.lookup("/topic/TopicToBeRedeployed");
-         fail("should throw exception");
-      }
-      catch(NamingException e)
-      {
-         // OK
-      }
-
-      TextMessage tm = (TextMessage)ds.receive();
-      assertEquals("one", tm.getText());
-      conn.close();
-
-      conn = cf.createConnection();
-      conn.setClientID("brookeburke");
-
-      s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
-      try
-      {
-         s.createDurableSubscriber(topic, "monicabelucci");
-         fail("should throw exception");
-      }
-      catch(JMSException e)
-      {
-         // OK
-      }
-
-      ServerManagement.deployTopic("TopicToBeRedeployed");
-      log.debug("topic redeployed");
-
-      // since redeployment has an activation semantic, I expect to find the messages there
-
-      topic = (Topic)ic.lookup("/topic/TopicToBeRedeployed");
-      ds =  s.createDurableSubscriber(topic, "monicabelucci");
-      conn.start();
-
-      tm = (TextMessage)ds.receive(1000);
-      assertEquals("two", tm.getText());
-
-      conn.close();
-      ServerManagement.undeployTopic("TopicToBeRedeployed");
-   }
-
-   public void testUnsubscribeDurableSubscription() throws Exception
-   {
-      ConnectionFactory cf = (ConnectionFactory)ic.lookup("ConnectionFactory");
-      Topic topic = (Topic)ic.lookup("/topic/Topic");
-
-      Connection conn = cf.createConnection();
-      conn.setClientID("ak47");
-
-      Session s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-      s.createDurableSubscriber(topic, "uzzi");
-      MessageProducer prod = s.createProducer(topic);
-      prod.setDeliveryMode(DeliveryMode.PERSISTENT);
-
-      prod.send(s.createTextMessage("one"));
-
-      log.debug("unsubscribing ...");
-
-      s.unsubscribe("uzzi");
-
-      log.debug("resubscribing ...");
-
-      MessageConsumer ds = s.createDurableSubscriber(topic, "uzzi");
-      conn.start();
-
-      assertNull(ds.receive(1000));
-
-      conn.close();
-   }
-
-   public void testInvalidSelectorException() throws Exception
-   {
-      ConnectionFactory cf = (ConnectionFactory)ic.lookup("ConnectionFactory");
-      Topic topic = (Topic)ic.lookup("/topic/Topic");
-      Connection c = cf.createConnection();
-      c.setClientID("sofiavergara");
-      Session s = c.createSession(false, Session.AUTO_ACKNOWLEDGE);
-
-      try
-      {
-         s.createDurableSubscriber(topic, "mysubscribption", "=TEST 'test'", true);
-         fail("this should fail");
-      }
-      catch(InvalidSelectorException e)
-      {
-         // OK
-      }
-   }
-   
-   // Package protected ---------------------------------------------
-
-   // Protected -----------------------------------------------------
-
-   // Private -------------------------------------------------------
-
-   // Inner classes -------------------------------------------------
-
-}

Added: trunk/tests/src/org/jboss/test/messaging/jms/DurableSubscriptionTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/DurableSubscriptionTest.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/jms/DurableSubscriptionTest.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -0,0 +1,473 @@
+/*
+  * 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.jms;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.DeliveryMode;
+import javax.jms.InvalidDestinationException;
+import javax.jms.InvalidSelectorException;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+import javax.jms.Topic;
+import javax.management.ObjectName;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+import org.jboss.test.messaging.MessagingTestCase;
+import org.jboss.test.messaging.tools.ServerManagement;
+
+/**
+ * Tests focused on durable subscription behavior. More durable subscription tests can be found in
+ * MessageConsumerTest.
+ *
+ * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ * $Id: DurableSubscriberTest.java 1273 2006-09-10 11:53:54Z timfox $
+ */
+public class DurableSubscriptionTest extends MessagingTestCase
+{
+   // Constants -----------------------------------------------------
+
+   // Static --------------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   protected InitialContext ic;
+
+   // Constructors --------------------------------------------------
+
+   public DurableSubscriptionTest(String name)
+   {
+      super(name);
+   }
+
+   // Public --------------------------------------------------------
+
+   public void setUp() throws Exception
+   {
+      super.setUp();
+
+      ServerManagement.start("all");
+            
+      ServerManagement.undeployTopic("Topic");
+      ServerManagement.deployTopic("Topic");
+
+      ic = new InitialContext(ServerManagement.getJNDIEnvironment());
+
+      log.debug("setup done");
+   }
+
+   public void tearDown() throws Exception
+   {
+      log.debug("starting tear down");
+
+      ic.close();
+
+      ServerManagement.undeployTopic("Topic");
+        
+      super.tearDown();
+   }
+
+   public void testSimplestDurableSubscription() throws Exception
+   {
+      ConnectionFactory cf = (ConnectionFactory)ic.lookup("ConnectionFactory");
+      Topic topic = (Topic)ic.lookup("/topic/Topic");
+      Connection conn = cf.createConnection();
+
+      conn.setClientID("brookeburke");
+
+      Session s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+      MessageProducer prod = s.createProducer(topic);
+      prod.setDeliveryMode(DeliveryMode.PERSISTENT);
+
+      s.createDurableSubscriber(topic, "monicabelucci");
+      
+      ObjectName destObjectName = 
+         new ObjectName("jboss.messaging.destination:service=Topic,name=Topic");
+      String text = (String)ServerManagement.invoke(destObjectName, "listSubscriptionsAsText", null, null);
+       
+      assertTrue(text.indexOf("monicabelucci") != -1);
+
+      prod.send(s.createTextMessage("k"));
+
+      conn.close();
+
+      text = (String)ServerManagement.invoke(destObjectName, "listSubscriptionsAsText", null, null);
+      
+      assertTrue(text.indexOf("monicabelucci") != -1);
+
+      conn = cf.createConnection();
+      conn.setClientID("brookeburke");
+
+      s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+      MessageConsumer durable = s.createDurableSubscriber(topic, "monicabelucci");
+
+      conn.start();
+
+      TextMessage tm = (TextMessage)durable.receive();
+      assertEquals("k", tm.getText());
+
+      Message m = durable.receive(1000);
+      assertNull(m);
+   }
+
+   /**
+    * JMS 1.1 6.11.1: A client can change an existing durable subscription by creating a durable
+    * TopicSubscriber with the same name and a new topic and/or message selector, or NoLocal
+    * attribute. Changing a durable subscription is equivalent to deleting and recreating it.
+    *
+    * Test with a different topic (a redeployed topic is a different topic).
+    */
+   public void testDurableSubscriptionOnNewTopic() throws Exception
+   {
+      ServerManagement.deployTopic("CompletelyNewTopic");
+
+      ConnectionFactory cf = (ConnectionFactory)ic.lookup("ConnectionFactory");
+      Topic topic = (Topic)ic.lookup("/topic/CompletelyNewTopic");
+      Connection conn = cf.createConnection();
+
+      conn.setClientID("brookeburke");
+
+      Session s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+      MessageProducer prod = s.createProducer(topic);
+      prod.setDeliveryMode(DeliveryMode.PERSISTENT);
+
+      s.createDurableSubscriber(topic, "monicabelucci");
+
+      prod.send(s.createTextMessage("one"));
+
+      conn.close();
+
+      ServerManagement.deployTopic("CompletelyNewTopic2");
+
+      Topic topic2 = (Topic)ic.lookup("/topic/CompletelyNewTopic2");
+      conn = cf.createConnection();
+
+      conn.setClientID("brookeburke");
+
+      s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+      MessageConsumer durable = s.createDurableSubscriber(topic2, "monicabelucci");
+
+      conn.start();
+
+      Message m = durable.receive(1000);
+      assertNull(m);
+
+      ServerManagement.undeployTopic("CompletelyNewTopic");
+      ServerManagement.undeployTopic("CompletelyNewTopic2");
+   }
+
+   /**
+    * JMS 1.1 6.11.1: A client can change an existing durable subscription by creating a durable
+    * TopicSubscriber with the same name and a new topic and/or message selector, or NoLocal
+    * attribute. Changing a durable subscription is equivalent to deleting and recreating it.
+    *
+    * Test with a different selector.
+    */
+   public void testDurableSubscriptionDifferentSelector() throws Exception
+   {
+      ServerManagement.deployTopic("CompletelyNewTopic2");
+      
+      ConnectionFactory cf = (ConnectionFactory)ic.lookup("ConnectionFactory");
+      Topic topic = (Topic)ic.lookup("/topic/Topic");
+      Connection conn = cf.createConnection();
+
+      conn.setClientID("brookeburke");
+
+      Session s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+      MessageProducer prod = s.createProducer(topic);
+      prod.setDeliveryMode(DeliveryMode.PERSISTENT);
+
+      
+      //fails here
+      MessageConsumer durable =
+         s.createDurableSubscriber(topic,
+                                   "monicabelucci",
+                                   "color = 'red' AND shape = 'square'",
+                                   false);
+
+      TextMessage tm = s.createTextMessage("A red square message");
+      tm.setStringProperty("color", "red");
+      tm.setStringProperty("shape", "square");
+      prod.send(tm);
+
+      conn.start();
+
+      TextMessage rm = (TextMessage)durable.receive(5000);
+      assertEquals("A red square message", rm.getText());
+
+      tm = s.createTextMessage("Another red square message");
+      tm.setStringProperty("color", "red");
+      tm.setStringProperty("shape", "square");
+      prod.send(tm);
+
+      // TODO: when subscriptions/durable subscription will be registered as MBean, use the JMX
+      //       interface to make sure the 'another red square message' is maintained by the
+      //       durable subascription
+      //       http://jira.jboss.org/jira/browse/JBMESSAGING-217
+
+      conn.close();
+
+      conn = cf.createConnection();
+
+      conn.setClientID("brookeburke");
+
+      s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+      // modify the selector
+      durable = s.createDurableSubscriber(topic,
+                                          "monicabelucci",
+                                          "color = 'red'",
+                                          false);
+
+      conn.start();
+
+      Message m = durable.receive(1000);
+
+      // the durable subscription is destroyed and re-created. The red square message stored by
+      // the previous durable subscription is lost and (hopefully) garbage collected.
+      assertNull(m);
+      
+      ServerManagement.undeployTopic("CompletelyNewTopic2");
+   }
+
+   /**
+    * JMS 1.1 6.11.1: A client can change an existing durable subscription by creating a durable
+    * TopicSubscriber with the same name and a new topic and/or message selector, or NoLocal
+    * attribute. Changing a durable subscription is equivalent to deleting and recreating it.
+    *
+    * Test with a different noLocal flag.
+    */
+   public void testDurableSubscriptionDifferentNoLocal() throws Exception
+   {
+      ConnectionFactory cf = (ConnectionFactory)ic.lookup("ConnectionFactory");
+      Topic topic = (Topic)ic.lookup("/topic/Topic");
+
+      Connection conn = cf.createConnection();
+      conn.setClientID("ID0");
+
+      Session s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+      MessageProducer prod = s.createProducer(topic);
+      prod.setDeliveryMode(DeliveryMode.PERSISTENT);
+
+      MessageConsumer durable = s.createDurableSubscriber(topic, "mySubscription", null, false);
+
+      TextMessage tm = null;
+      tm = s.createTextMessage("Message One");
+      prod.send(tm);
+      tm = s.createTextMessage("Message Two");
+      prod.send(tm);
+
+
+      conn.start();
+
+      TextMessage rm = (TextMessage)durable.receive(5000);
+      assertEquals("Message One", rm.getText());
+
+      // TODO: when subscriptions/durable subscription will be registered as MBean, use the JMX
+      //       interface to make sure the 'another red square message' is maintained by the
+      //       durable subascription
+
+      conn.close();
+
+      conn = cf.createConnection();
+      conn.setClientID("ID0");
+      s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+      // modify the nolocal flag
+      durable = s.createDurableSubscriber(topic, "mySubscription", null, true);
+
+      conn.start();
+
+      Message m = durable.receive(1000);
+
+      // the durable subscription is destroyed and re-created. "Message Two" stored by the previous
+      // durable subscription is lost and (hopefully) garbage collected.
+      assertNull(m);
+   }
+
+   public void testDurableSubscriptionOnTemporaryTopic() throws Exception
+   {
+      ConnectionFactory cf = (ConnectionFactory)ic.lookup("ConnectionFactory");
+      Connection conn = cf.createConnection();
+      conn.setClientID("doesn't actually matter");
+      Session s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+      Topic temporaryTopic = s.createTemporaryTopic();
+
+      try
+      {
+         s.createDurableSubscriber(temporaryTopic, "mySubscription");
+         fail("this should throw exception");
+      }
+      catch(InvalidDestinationException e)
+      {
+         // OK
+      }
+   }
+
+   /**
+    * Topic undeployment/redeployment has an activation/deactivation semantic, so undeploying a
+    * topic for which there are durable subscriptions preserves the content of those durable
+    * subscriptions, which can be then access upon topic redeployment.
+    * @throws Exception
+    */
+   public void testDurableSubscriptionOnTopicRedeployment() throws Exception
+   {
+      try
+      {
+         ic.lookup("/topic/TopicToBeRedeployed");
+         fail("should throw exception, topic shouldn't be deployed on the server");
+      }
+      catch(NamingException e)
+      {
+         // OK
+      }
+
+      ServerManagement.deployTopic("TopicToBeRedeployed");
+
+      ConnectionFactory cf = (ConnectionFactory)ic.lookup("ConnectionFactory");
+      Topic topic = (Topic)ic.lookup("/topic/TopicToBeRedeployed");
+
+      Connection conn = cf.createConnection();
+      conn.setClientID("brookeburke");
+
+      Session s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+      MessageProducer prod = s.createProducer(topic);
+      prod.setDeliveryMode(DeliveryMode.PERSISTENT);
+      MessageConsumer ds = s.createDurableSubscriber(topic, "monicabelucci");
+      conn.start();
+
+      prod.send(s.createTextMessage("one"));
+      prod.send(s.createTextMessage("two"));
+      
+      ServerManagement.undeployTopic("TopicToBeRedeployed");
+      log.debug("topic undeployed");
+
+      try
+      {
+         topic = (Topic)ic.lookup("/topic/TopicToBeRedeployed");
+         fail("should throw exception");
+      }
+      catch(NamingException e)
+      {
+         // OK
+      }
+
+      TextMessage tm = (TextMessage)ds.receive();
+      assertEquals("one", tm.getText());
+      conn.close();
+
+      conn = cf.createConnection();
+      conn.setClientID("brookeburke");
+
+      s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+      try
+      {
+         s.createDurableSubscriber(topic, "monicabelucci");
+         fail("should throw exception");
+      }
+      catch(JMSException e)
+      {
+         // OK
+      }
+
+      ServerManagement.deployTopic("TopicToBeRedeployed");
+      log.debug("topic redeployed");
+
+      // since redeployment has an activation semantic, I expect to find the messages there
+
+      topic = (Topic)ic.lookup("/topic/TopicToBeRedeployed");
+      ds =  s.createDurableSubscriber(topic, "monicabelucci");
+      conn.start();
+
+      tm = (TextMessage)ds.receive(1000);
+      assertEquals("two", tm.getText());
+
+      conn.close();
+      ServerManagement.undeployTopic("TopicToBeRedeployed");
+   }
+
+   public void testUnsubscribeDurableSubscription() throws Exception
+   {
+      ConnectionFactory cf = (ConnectionFactory)ic.lookup("ConnectionFactory");
+      Topic topic = (Topic)ic.lookup("/topic/Topic");
+
+      Connection conn = cf.createConnection();
+      conn.setClientID("ak47");
+
+      Session s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+      s.createDurableSubscriber(topic, "uzzi");
+      MessageProducer prod = s.createProducer(topic);
+      prod.setDeliveryMode(DeliveryMode.PERSISTENT);
+
+      prod.send(s.createTextMessage("one"));
+
+      log.debug("unsubscribing ...");
+
+      s.unsubscribe("uzzi");
+
+      log.debug("resubscribing ...");
+
+      MessageConsumer ds = s.createDurableSubscriber(topic, "uzzi");
+      conn.start();
+
+      assertNull(ds.receive(1000));
+
+      conn.close();
+   }
+
+   public void testInvalidSelectorException() throws Exception
+   {
+      ConnectionFactory cf = (ConnectionFactory)ic.lookup("ConnectionFactory");
+      Topic topic = (Topic)ic.lookup("/topic/Topic");
+      Connection c = cf.createConnection();
+      c.setClientID("sofiavergara");
+      Session s = c.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+      try
+      {
+         s.createDurableSubscriber(topic, "mysubscribption", "=TEST 'test'", true);
+         fail("this should fail");
+      }
+      catch(InvalidSelectorException e)
+      {
+         // OK
+      }
+   }
+   
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}

Modified: trunk/tests/src/org/jboss/test/messaging/tools/jmx/ServiceContainer.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/tools/jmx/ServiceContainer.java	2006-09-15 22:09:37 UTC (rev 1296)
+++ trunk/tests/src/org/jboss/test/messaging/tools/jmx/ServiceContainer.java	2006-09-17 15:47:58 UTC (rev 1297)
@@ -375,7 +375,7 @@
 
          log.info("remoting = \"" +
             (remotingSocket ? "socket" : (remotingMultiplex ? "multiplex" : "disabled")) + "\", " +
-            "serialization = \"" + config.getSerializationType() + "\", " + 
+            "serialization = \"" + "jms" + "\", " + 
             "database = \"" + getDatabaseType() + "\"");
          log.debug(this + " started");
       }
@@ -978,8 +978,10 @@
               
       RemotingJMXWrapper mbean;
 
-      String serializationType = config.getSerializationType();
+      //String serializationType = config.getSerializationType();
       
+      String serializationType = "jms";
+      
       String params = "/?marshaller=org.jboss.jms.server.remoting.JMSWireFormat&" +
                       "unmarshaller=org.jboss.jms.server.remoting.JMSWireFormat&" +
                       "serializationtype=" + serializationType + "&" +




More information about the jboss-cvs-commits mailing list