[jboss-cvs] JBoss Messaging SVN: r1930 - in trunk: src/etc/xmdesc and 26 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Tue Jan 9 13:17:00 EST 2007


Author: timfox
Date: 2007-01-09 13:16:04 -0500 (Tue, 09 Jan 2007)
New Revision: 1930

Added:
   trunk/src/main/org/jboss/jms/server/MyTimeoutFactory.java
   trunk/src/main/org/jboss/jms/server/ServerPeerMBean.java
   trunk/src/main/org/jboss/jms/server/destination/DestinationMBean.java
   trunk/src/main/org/jboss/jms/server/destination/QueueMBean.java
   trunk/src/main/org/jboss/jms/server/destination/SubscriptionInfo.java
   trunk/src/main/org/jboss/jms/server/destination/TopicMBean.java
   trunk/src/main/org/jboss/jms/server/messagecounter/
   trunk/src/main/org/jboss/jms/server/messagecounter/MessageCounter.java
   trunk/src/main/org/jboss/jms/server/messagecounter/MessageCounterManager.java
   trunk/src/main/org/jboss/jms/server/messagecounter/MessageStatistics.java
   trunk/tests/src/org/jboss/test/messaging/jms/ScheduledDeliveryTest.java
Modified:
   trunk/src/etc/server/default/deploy/clustered-mysql-persistence-service.xml
   trunk/src/etc/server/default/deploy/destinations-service.xml
   trunk/src/etc/server/default/deploy/messaging-service.xml
   trunk/src/etc/server/default/deploy/mysql-persistence-service.xml
   trunk/src/etc/xmdesc/Queue-xmbean.xml
   trunk/src/etc/xmdesc/ServerPeer-xmbean.xml
   trunk/src/etc/xmdesc/Topic-xmbean.xml
   trunk/src/main/org/jboss/jms/message/JBossBytesMessage.java
   trunk/src/main/org/jboss/jms/message/JBossMapMessage.java
   trunk/src/main/org/jboss/jms/message/JBossMessage.java
   trunk/src/main/org/jboss/jms/message/JBossObjectMessage.java
   trunk/src/main/org/jboss/jms/message/JBossStreamMessage.java
   trunk/src/main/org/jboss/jms/message/JBossTextMessage.java
   trunk/src/main/org/jboss/jms/server/ServerPeer.java
   trunk/src/main/org/jboss/jms/server/destination/DestinationServiceSupport.java
   trunk/src/main/org/jboss/jms/server/destination/ManagedDestination.java
   trunk/src/main/org/jboss/jms/server/destination/ManagedQueue.java
   trunk/src/main/org/jboss/jms/server/destination/ManagedTopic.java
   trunk/src/main/org/jboss/jms/server/destination/QueueService.java
   trunk/src/main/org/jboss/jms/server/destination/TopicService.java
   trunk/src/main/org/jboss/jms/server/endpoint/ServerConnectionEndpoint.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/Distributor.java
   trunk/src/main/org/jboss/messaging/core/PagingChannelSupport.java
   trunk/src/main/org/jboss/messaging/core/Routable.java
   trunk/src/main/org/jboss/messaging/core/local/FirstReceiverPointToPointRouter.java
   trunk/src/main/org/jboss/messaging/core/local/PagingFilteredQueue.java
   trunk/src/main/org/jboss/messaging/core/local/RoundRobinPointToPointRouter.java
   trunk/src/main/org/jboss/messaging/core/message/CoreMessage.java
   trunk/src/main/org/jboss/messaging/core/message/MessageFactory.java
   trunk/src/main/org/jboss/messaging/core/message/MessageSupport.java
   trunk/src/main/org/jboss/messaging/core/message/RoutableSupport.java
   trunk/src/main/org/jboss/messaging/core/plugin/JDBCPersistenceManager.java
   trunk/src/main/org/jboss/messaging/core/plugin/SimpleMessageReference.java
   trunk/src/main/org/jboss/messaging/core/plugin/contract/PersistenceManager.java
   trunk/src/main/org/jboss/messaging/core/plugin/contract/PostOffice.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/DefaultPostOffice.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/DefaultClusteredPostOffice.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/DefaultRouter.java
   trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/FailedOverQueue.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/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/StatsSender.java
   trunk/src/main/org/jboss/messaging/core/tx/TransactionRepository.java
   trunk/tests/src/org/jboss/test/messaging/core/SimpleChannel.java
   trunk/tests/src/org/jboss/test/messaging/core/local/NonRecoverablePagingFilteredQueueTest.java
   trunk/tests/src/org/jboss/test/messaging/core/local/RecoverablePagingFilteredQueueTest.java
   trunk/tests/src/org/jboss/test/messaging/core/local/base/PagingFilteredQueueTestBase.java
   trunk/tests/src/org/jboss/test/messaging/core/message/JBossMessageTest.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/core/plugin/postoffice/DefaultPostOfficeTest.java
   trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/DefaultClusteredPostOfficeTest.java
   trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/DefaultClusteredPostOfficeWithDefaultRouterTest.java
   trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/DefaultMessagePullPolicyTest.java
   trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/DefaultRouterTest.java
   trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/RecoveryTest.java
   trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/RedistributionWithDefaultMessagePullPolicyTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/ConsumerClosedTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/DLQTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/DurableSubscriberTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/ExpiryQueueTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/MessageConsumerTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/MessageProducerTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/MiscellaneousTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/SessionTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/TransactedSessionTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/XATest.java
   trunk/tests/src/org/jboss/test/messaging/jms/message/JMSExpirationHeaderTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/message/MessageTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/server/ServerPeerTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/server/destination/QueueManagementTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/server/destination/TopicManagementTest.java
   trunk/tests/src/org/jboss/test/messaging/jms/server/destination/base/DestinationManagementTestBase.java
   trunk/tests/src/org/jboss/test/messaging/tools/jmx/ClassLoaderJMXWrapper.java
Log:
Scheduled delivery and redelivery, full JMX functionality


Modified: trunk/src/etc/server/default/deploy/clustered-mysql-persistence-service.xml
===================================================================
--- trunk/src/etc/server/default/deploy/clustered-mysql-persistence-service.xml	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/etc/server/default/deploy/clustered-mysql-persistence-service.xml	2007-01-09 18:16:04 UTC (rev 1930)
@@ -17,16 +17,17 @@
       <attribute name="CreateTablesOnStartup">true</attribute>
       <attribute name="UsingBatchUpdates">true</attribute>
       <attribute name="SqlProperties"><![CDATA[
-CREATE_MESSAGE_REFERENCE=CREATE TABLE JMS_MESSAGE_REFERENCE (CHANNELID BIGINT, MESSAGEID BIGINT, TRANSACTIONID BIGINT, STATE CHAR(1), ORD BIGINT, PAGE_ORD BIGINT, DELIVERYCOUNT INTEGER, RELIABLE CHAR(1), LOADED CHAR(1), PRIMARY KEY(CHANNELID, MESSAGEID))
+CREATE_MESSAGE_REFERENCE=CREATE TABLE JMS_MESSAGE_REFERENCE (CHANNELID BIGINT, MESSAGEID BIGINT, TRANSACTIONID BIGINT, STATE CHAR(1), ORD BIGINT, PAGE_ORD BIGINT, DELIVERYCOUNT INTEGER, RELIABLE CHAR(1), LOADED CHAR(1), SCHED_DELIVERY BIGINT, PRIMARY KEY(CHANNELID, MESSAGEID))
 CREATE_IDX_MESSAGE_REF_TX=CREATE INDEX JMS_MESSAGE_REF_TX ON JMS_MESSAGE_REFERENCE (TRANSACTIONID)
 CREATE_IDX_MESSAGE_REF_ORD=CREATE INDEX JMS_MESSAGE_REF_ORD ON JMS_MESSAGE_REFERENCE (ORD)
 CREATE_IDX_MESSAGE_REF_PAGE_ORD=CREATE INDEX JMS_MESSAGE_REF_LOADED ON JMS_MESSAGE_REFERENCE (PAGE_ORD)
 CREATE_IDX_MESSAGE_REF_MESSAGEID=CREATE INDEX JMS_MESSAGE_REF_MESSAGEID ON JMS_MESSAGE_REFERENCE (MESSAGEID)
 CREATE_IDX_MESSAGE_REF_RELIABLE=CREATE INDEX JMS_MESSAGE_REF_RELIABLE ON JMS_MESSAGE_REFERENCE (RELIABLE)
+CREATE_IDX_MESSAGE_REF_SCHED_DELIVERY=CREATE INDEX JMS_MESSAGE_REF_SCHED_DELIVERY ON JMS_MESSAGE_REFERENCE (SCHED_DELIVERY)
 CREATE_MESSAGE=CREATE TABLE JMS_MESSAGE (MESSAGEID BIGINT, RELIABLE CHAR(1), EXPIRATION BIGINT, TIMESTAMP BIGINT, PRIORITY TINYINT, COREHEADERS MEDIUMBLOB, PAYLOAD LONGBLOB, CHANNELCOUNT INTEGER, TYPE TINYINT, JMSTYPE VARCHAR(255), CORRELATIONID VARCHAR(255), CORRELATIONID_BYTES VARBINARY(254), DESTINATION VARCHAR(255), REPLYTO VARCHAR(255), JMSPROPERTIES MEDIUMBLOB, PRIMARY KEY (MESSAGEID))
 CREATE_TRANSACTION=CREATE TABLE JMS_TRANSACTION (TRANSACTIONID BIGINT, BRANCH_QUAL VARBINARY(254), FORMAT_ID INTEGER, GLOBAL_TXID VARBINARY(254), PRIMARY KEY (TRANSACTIONID))
 CREATE_COUNTER=CREATE TABLE JMS_COUNTER (NAME VARCHAR(255), NEXT_ID BIGINT, PRIMARY KEY(NAME))
-INSERT_MESSAGE_REF=INSERT INTO JMS_MESSAGE_REFERENCE (CHANNELID, MESSAGEID, TRANSACTIONID, STATE, ORD, PAGE_ORD, DELIVERYCOUNT, RELIABLE) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
+INSERT_MESSAGE_REF=INSERT INTO JMS_MESSAGE_REFERENCE (CHANNELID, MESSAGEID, TRANSACTIONID, STATE, ORD, PAGE_ORD, DELIVERYCOUNT, RELIABLE, SCHED_DELIVERY) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
 DELETE_MESSAGE_REF=DELETE FROM JMS_MESSAGE_REFERENCE WHERE MESSAGEID=? AND CHANNELID=? AND STATE='C'
 UPDATE_MESSAGE_REF=UPDATE JMS_MESSAGE_REFERENCE SET TRANSACTIONID=?, STATE='-' WHERE MESSAGEID=? AND CHANNELID=? AND STATE='C'
 UPDATE_PAGE_ORDER=UPDATE JMS_MESSAGE_REFERENCE SET PAGE_ORD = ? WHERE MESSAGEID=? AND CHANNELID=?
@@ -34,13 +35,13 @@
 COMMIT_MESSAGE_REF2=DELETE FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID=? AND STATE='-'
 ROLLBACK_MESSAGE_REF1=DELETE FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID=? AND STATE='+'
 ROLLBACK_MESSAGE_REF2=UPDATE JMS_MESSAGE_REFERENCE SET STATE='C', TRANSACTIONID = NULL WHERE TRANSACTIONID=? AND STATE='-'
-LOAD_PAGED_REFS=SELECT MESSAGEID, DELIVERYCOUNT, PAGE_ORD, RELIABLE FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID = ? AND PAGE_ORD BETWEEN ? AND ? ORDER BY PAGE_ORD
-LOAD_UNPAGED_REFS=SELECT MESSAGEID, DELIVERYCOUNT, RELIABLE FROM JMS_MESSAGE_REFERENCE WHERE STATE = 'C' AND CHANNELID = ? AND PAGE_ORD IS NULL ORDER BY ORD
+LOAD_PAGED_REFS=SELECT MESSAGEID, DELIVERYCOUNT, PAGE_ORD, RELIABLE, SCHED_DELIVERY FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID = ? AND PAGE_ORD BETWEEN ? AND ? ORDER BY PAGE_ORD
+LOAD_UNPAGED_REFS=SELECT MESSAGEID, DELIVERYCOUNT, RELIABLE, SCHED_DELIVERY FROM JMS_MESSAGE_REFERENCE WHERE STATE = 'C' AND CHANNELID = ? AND PAGE_ORD IS NULL ORDER BY ORD
 UPDATE_RELIABLE_REFS_NOT_PAGED=UPDATE JMS_MESSAGE_REFERENCE SET PAGE_ORD = NULL WHERE PAGE_ORD BETWEEN ? AND ? AND CHANNELID=?
 SELECT_MIN_MAX_PAGE_ORD=SELECT MIN(PAGE_ORD), MAX(PAGE_ORD) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID = ?
 SELECT_EXISTS_REF=SELECT MESSAGEID FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID = ? AND MESSAGEID = ?
 UPDATE_DELIVERYCOUNT=UPDATE JMS_MESSAGE_REFERENCE SET DELIVERYCOUNT = ? WHERE CHANNELID = ? AND MESSAGEID = ?
-LOAD_MESSAGES=SELECT MESSAGEID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, COREHEADERS, PAYLOAD, CHANNELCOUNT, TYPE, JMSTYPE, CORRELATIONID, CORRELATIONID_BYTES, DESTINATION, REPLYTO, JMSPROPERTIES FROM JMS_MESSAGE
+LOAD_MESSAGES=SELECT MESSAGEID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, COREHEADERS, PAYLOAD, TYPE, JMSTYPE, CORRELATIONID, CORRELATIONID_BYTES, DESTINATION, REPLYTO, JMSPROPERTIES FROM JMS_MESSAGE
 INSERT_MESSAGE=INSERT INTO JMS_MESSAGE (MESSAGEID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, COREHEADERS, PAYLOAD, CHANNELCOUNT, TYPE, JMSTYPE, CORRELATIONID, CORRELATIONID_BYTES, DESTINATION, REPLYTO, JMSPROPERTIES) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
 INC_CHANNELCOUNT=UPDATE JMS_MESSAGE SET CHANNELCOUNT = CHANNELCOUNT + 1 WHERE MESSAGEID=?
 DEC_CHANNELCOUNT=UPDATE JMS_MESSAGE SET CHANNELCOUNT = CHANNELCOUNT - 1 WHERE MESSAGEID=?

Modified: trunk/src/etc/server/default/deploy/destinations-service.xml
===================================================================
--- trunk/src/etc/server/default/deploy/destinations-service.xml	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/etc/server/default/deploy/destinations-service.xml	2007-01-09 18:16:04 UTC (rev 1930)
@@ -158,6 +158,24 @@
       <attribute name="ExpiryQueue">jboss.messaging.destination:service=Queue,name=PrivateExpiryQueue</attribute>
    </mbean>       
    
+   <!-- Queues and Topics can also specify their own redelivery delay -->
+   
+   <mbean code="org.jboss.jms.server.destination.QueueService"
+      name="jboss.messaging.destination:service=Queue,name=QueueWithOwnRedeliveryDelay"
+      xmbean-dd="xmdesc/Queue-xmbean.xml">
+      <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
+      <depends>jboss.messaging:service=PostOffice</depends>
+      <attribute name="RedeliveryDelay">5000</attribute>
+   </mbean>
+   
+   <mbean code="org.jboss.jms.server.destination.TopicService"
+      name="jboss.messaging.destination:service=Topic,name=TopicWithOwnRedeliveryDelay"
+      xmbean-dd="xmdesc/Topic-xmbean.xml">
+      <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
+      <depends>jboss.messaging:service=PostOffice</depends>
+      <attribute name="RedeliveryDelay">5000</attribute>
+   </mbean>     
+   
    <!--
         Example clustered destinations.
    -->

Modified: trunk/src/etc/server/default/deploy/messaging-service.xml
===================================================================
--- trunk/src/etc/server/default/deploy/messaging-service.xml	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/etc/server/default/deploy/messaging-service.xml	2007-01-09 18:16:04 UTC (rev 1930)
@@ -43,9 +43,15 @@
       
       <attribute name="DefaultExpiryQueue">jboss.messaging.destination:service=Queue,name=ExpiryQueue</attribute> 
 
+      <attribute name="DefaultRedeliveryDelay">0</attribute>
+      
+      <attribute name="QueueStatsSamplePeriod">5000</attribute>
+      
       <attribute name="FailoverStartTimeout">3000</attribute>
       
       <attribute name="FailoverCompleteTimeout">12000</attribute>
+      
+      <attribute name="DefaultMessageCounterHistoryDayLimit">-1</attribute>
    </mbean>
 
 </server>
\ No newline at end of file

Modified: trunk/src/etc/server/default/deploy/mysql-persistence-service.xml
===================================================================
--- trunk/src/etc/server/default/deploy/mysql-persistence-service.xml	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/etc/server/default/deploy/mysql-persistence-service.xml	2007-01-09 18:16:04 UTC (rev 1930)
@@ -17,16 +17,17 @@
          <attribute name="CreateTablesOnStartup">true</attribute>
          <attribute name="UsingBatchUpdates">true</attribute>
          <attribute name="SqlProperties"><![CDATA[
-   CREATE_MESSAGE_REFERENCE=CREATE TABLE JMS_MESSAGE_REFERENCE (CHANNELID BIGINT, MESSAGEID BIGINT, TRANSACTIONID BIGINT, STATE CHAR(1), ORD BIGINT, PAGE_ORD BIGINT, DELIVERYCOUNT INTEGER, RELIABLE CHAR(1), LOADED CHAR(1), PRIMARY KEY(CHANNELID, MESSAGEID))
+   CREATE_MESSAGE_REFERENCE=CREATE TABLE JMS_MESSAGE_REFERENCE (CHANNELID BIGINT, MESSAGEID BIGINT, TRANSACTIONID BIGINT, STATE CHAR(1), ORD BIGINT, PAGE_ORD BIGINT, DELIVERYCOUNT INTEGER, RELIABLE CHAR(1), LOADED CHAR(1), SCHED_DELIVERY BIGINT, PRIMARY KEY(CHANNELID, MESSAGEID))
    CREATE_IDX_MESSAGE_REF_TX=CREATE INDEX JMS_MESSAGE_REF_TX ON JMS_MESSAGE_REFERENCE (TRANSACTIONID)
    CREATE_IDX_MESSAGE_REF_ORD=CREATE INDEX JMS_MESSAGE_REF_ORD ON JMS_MESSAGE_REFERENCE (ORD)
    CREATE_IDX_MESSAGE_REF_PAGE_ORD=CREATE INDEX JMS_MESSAGE_REF_LOADED ON JMS_MESSAGE_REFERENCE (PAGE_ORD)
    CREATE_IDX_MESSAGE_REF_MESSAGEID=CREATE INDEX JMS_MESSAGE_REF_MESSAGEID ON JMS_MESSAGE_REFERENCE (MESSAGEID)
    CREATE_IDX_MESSAGE_REF_RELIABLE=CREATE INDEX JMS_MESSAGE_REF_RELIABLE ON JMS_MESSAGE_REFERENCE (RELIABLE)
+   CREATE_IDX_MESSAGE_REF_SCHED_DELIVERY=CREATE INDEX JMS_MESSAGE_REF_SCHED_DELIVERY ON JMS_MESSAGE_REFERENCE (SCHED_DELIVERY)
    CREATE_MESSAGE=CREATE TABLE JMS_MESSAGE (MESSAGEID BIGINT, RELIABLE CHAR(1), EXPIRATION BIGINT, TIMESTAMP BIGINT, PRIORITY TINYINT, COREHEADERS MEDIUMBLOB, PAYLOAD LONGBLOB, CHANNELCOUNT INTEGER, TYPE TINYINT, JMSTYPE VARCHAR(255), CORRELATIONID VARCHAR(255), CORRELATIONID_BYTES VARBINARY(254), DESTINATION VARCHAR(255), REPLYTO VARCHAR(255), JMSPROPERTIES MEDIUMBLOB, PRIMARY KEY (MESSAGEID))
    CREATE_TRANSACTION=CREATE TABLE JMS_TRANSACTION (TRANSACTIONID BIGINT, BRANCH_QUAL VARBINARY(254), FORMAT_ID INTEGER, GLOBAL_TXID VARBINARY(254), PRIMARY KEY (TRANSACTIONID))
    CREATE_COUNTER=CREATE TABLE JMS_COUNTER (NAME VARCHAR(255), NEXT_ID BIGINT, PRIMARY KEY(NAME))
-   INSERT_MESSAGE_REF=INSERT INTO JMS_MESSAGE_REFERENCE (CHANNELID, MESSAGEID, TRANSACTIONID, STATE, ORD, PAGE_ORD, DELIVERYCOUNT, RELIABLE) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
+   INSERT_MESSAGE_REF=INSERT INTO JMS_MESSAGE_REFERENCE (CHANNELID, MESSAGEID, TRANSACTIONID, STATE, ORD, PAGE_ORD, DELIVERYCOUNT, RELIABLE, SCHED_DELIVERY) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
    DELETE_MESSAGE_REF=DELETE FROM JMS_MESSAGE_REFERENCE WHERE MESSAGEID=? AND CHANNELID=? AND STATE='C'
    UPDATE_MESSAGE_REF=UPDATE JMS_MESSAGE_REFERENCE SET TRANSACTIONID=?, STATE='-' WHERE MESSAGEID=? AND CHANNELID=? AND STATE='C'
    UPDATE_PAGE_ORDER=UPDATE JMS_MESSAGE_REFERENCE SET PAGE_ORD = ? WHERE MESSAGEID=? AND CHANNELID=?
@@ -34,13 +35,13 @@
    COMMIT_MESSAGE_REF2=DELETE FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID=? AND STATE='-'
    ROLLBACK_MESSAGE_REF1=DELETE FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID=? AND STATE='+'
    ROLLBACK_MESSAGE_REF2=UPDATE JMS_MESSAGE_REFERENCE SET STATE='C', TRANSACTIONID = NULL WHERE TRANSACTIONID=? AND STATE='-'
-   LOAD_PAGED_REFS=SELECT MESSAGEID, DELIVERYCOUNT, PAGE_ORD, RELIABLE FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID = ? AND PAGE_ORD BETWEEN ? AND ? ORDER BY PAGE_ORD
-   LOAD_UNPAGED_REFS=SELECT MESSAGEID, DELIVERYCOUNT, RELIABLE FROM JMS_MESSAGE_REFERENCE WHERE STATE = 'C' AND CHANNELID = ? AND PAGE_ORD IS NULL ORDER BY ORD
+   LOAD_PAGED_REFS=SELECT MESSAGEID, DELIVERYCOUNT, PAGE_ORD, RELIABLE, SCHED_DELIVERY FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID = ? AND PAGE_ORD BETWEEN ? AND ? ORDER BY PAGE_ORD
+   LOAD_UNPAGED_REFS=SELECT MESSAGEID, DELIVERYCOUNT, RELIABLE, SCHED_DELIVERY FROM JMS_MESSAGE_REFERENCE WHERE STATE = 'C' AND CHANNELID = ? AND PAGE_ORD IS NULL ORDER BY ORD
    UPDATE_RELIABLE_REFS_NOT_PAGED=UPDATE JMS_MESSAGE_REFERENCE SET PAGE_ORD = NULL WHERE PAGE_ORD BETWEEN ? AND ? AND CHANNELID=?
    SELECT_MIN_MAX_PAGE_ORD=SELECT MIN(PAGE_ORD), MAX(PAGE_ORD) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID = ?
    SELECT_EXISTS_REF=SELECT MESSAGEID FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID = ? AND MESSAGEID = ?
    UPDATE_DELIVERYCOUNT=UPDATE JMS_MESSAGE_REFERENCE SET DELIVERYCOUNT = ? WHERE CHANNELID = ? AND MESSAGEID = ?
-   LOAD_MESSAGES=SELECT MESSAGEID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, COREHEADERS, PAYLOAD, CHANNELCOUNT, TYPE, JMSTYPE, CORRELATIONID, CORRELATIONID_BYTES, DESTINATION, REPLYTO, JMSPROPERTIES FROM JMS_MESSAGE
+   LOAD_MESSAGES=SELECT MESSAGEID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, COREHEADERS, PAYLOAD, TYPE, JMSTYPE, CORRELATIONID, CORRELATIONID_BYTES, DESTINATION, REPLYTO, JMSPROPERTIES FROM JMS_MESSAGE
    INSERT_MESSAGE=INSERT INTO JMS_MESSAGE (MESSAGEID, RELIABLE, EXPIRATION, TIMESTAMP, PRIORITY, COREHEADERS, PAYLOAD, CHANNELCOUNT, TYPE, JMSTYPE, CORRELATIONID, CORRELATIONID_BYTES, DESTINATION, REPLYTO, JMSPROPERTIES) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    INC_CHANNELCOUNT=UPDATE JMS_MESSAGE SET CHANNELCOUNT = CHANNELCOUNT + 1 WHERE MESSAGEID=?
    DEC_CHANNELCOUNT=UPDATE JMS_MESSAGE SET CHANNELCOUNT = CHANNELCOUNT - 1 WHERE MESSAGEID=?

Modified: trunk/src/etc/xmdesc/Queue-xmbean.xml
===================================================================
--- trunk/src/etc/xmdesc/Queue-xmbean.xml	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/etc/xmdesc/Queue-xmbean.xml	2007-01-09 18:16:04 UTC (rev 1930)
@@ -31,15 +31,6 @@
       <type>java.lang.String</type>
    </attribute>
 
-   <!-- This managed attribute is exposed here for backward compatibility with JBossMQ queues
-        management interface only. It will probably dissapear in the future.
-   -->
-   <attribute access="read-only" getMethod="getName">
-      <description>The queue name (deprecated management attribute)</description>
-      <name>QueueName</name>
-      <type>java.lang.String</type>
-   </attribute>
-
    <!-- This attribute is writable to allow configuring an arbitrary JNDI name in the queue's
         service deployment descriptor. Any attempt to change the attribute after initialization
         will be ignored.
@@ -71,6 +62,12 @@
       <name>ExpiryQueue</name>
       <type>javax.management.ObjectName</type>
    </attribute>
+   
+   <attribute access="read-write" getMethod="getRedeliveryDelay" setMethod="setRedeliveryDelay">
+      <description>The delay before redelivering</description>
+      <name>RedeliveryDelay</name>
+      <type>long</type>
+   </attribute>   
 
    <attribute access="read-write" getMethod="getSecurityConfig" setMethod="setSecurityConfig">
       <description>The destination's security configuration</description>
@@ -89,6 +86,18 @@
       <name>MessageCount</name>
       <type>int</type>
    </attribute>
+   
+   <attribute access="read-only" getMethod="getScheduledMessageCount">
+      <description>The number of scheduled messages in the queue</description>
+      <name>ScheduledMessageCount</name>
+      <type>int</type>
+   </attribute>
+   
+   <attribute access="read-write" getMethod="getMaxSize" setMethod="setMaxSize">
+      <description>The maximum number of messages this queue can hold before they are dropped</description>
+      <name>MaxSize</name>
+      <type>int</type>
+   </attribute>   
 
    <attribute access="read-write" getMethod="getFullSize" setMethod="setFullSize">
       <description>The in-memory message limit, can only be set when queue is stopped</description>
@@ -114,6 +123,30 @@
       <type>boolean</type>
    </attribute>   
    
+   <attribute access="read-only" getMethod="getMessageCounter">
+      <description>Get the message counter for the queue</description>
+      <name>MessageCounter</name>
+      <type>org.jboss.jms.server.messagecounter.MessageCounter</type>
+   </attribute>
+   
+   <attribute access="read-only" getMethod="getMessageStatistics">
+      <description>Get the message statistics for the queue</description>
+      <name>MessageStatistics</name>
+      <type>org.jboss.jms.server.messagecounter.MessageStatistics</type>
+   </attribute>   
+   
+   <attribute access="read-write" getMethod="getMessageCounterHistoryDayLimit" setMethod="setMessageCounterHistoryDayLimit">
+      <description>The day limit for the message counter</description>
+      <name>MessageCounterHistoryDayLimit</name>
+      <type>int</type>
+   </attribute>
+   
+   <attribute access="read-only" getMethod="getConsumerCount">
+      <description>The number of consumers on the queue</description>
+      <name>ConsumerCount</name>
+      <type>int</type>
+   </attribute>   
+   
    <!-- instance access -->
 
    <attribute access="read-only" getMethod="getInstance">
@@ -150,6 +183,57 @@
    </operation>
 
    <operation>
+      <description>List all messages</description>
+      <name>listAllMessages</name>
+      <return-type>java.util.List</return-type>
+   </operation>
+   
+   <operation>
+      <description>List all messages with selector</description>
+      <name>listAllMessages</name>
+      <parameter>
+         <description>Expression to define the selector</description>
+         <name>selector</name>
+         <type>java.lang.String</type>
+      </parameter>
+      <return-type>java.util.List</return-type>
+   </operation>   
+   
+   <operation>
+      <description>List durable messages</description>
+      <name>listDurableMessages</name>
+      <return-type>java.util.List</return-type>
+   </operation>
+   
+   <operation>
+      <description>List durable messages with selector</description>
+      <name>listDurableMessages</name>
+      <parameter>
+         <description>Expression to define the selector</description>
+         <name>selector</name>
+         <type>java.lang.String</type>
+      </parameter>
+      <return-type>java.util.List</return-type>
+   </operation>  
+   
+   <operation>
+      <description>List non durable messages</description>
+      <name>listNonDurableMessages</name>
+      <return-type>java.util.List</return-type>
+   </operation>
+   
+   <operation>
+      <description>List non durable messages with selector</description>
+      <name>listNonDurableMessages</name>
+      <parameter>
+         <description>Expression to define the selector</description>
+         <name>selector</name>
+         <type>java.lang.String</type>
+      </parameter>
+      <return-type>java.util.List</return-type>
+   </operation>      
+
+   <operation>
       <description>List all messages which meet the condition described in selector</description>
       <name>listMessages</name>
       <parameter>
@@ -160,4 +244,26 @@
       <return-type>java.util.List</return-type>
    </operation>
    
+   <operation>
+      <description>Reset the message counter</description>
+      <name>resetMessageCounter</name>
+   </operation>   
+   
+   <operation>
+      <description>Reset the message counter history</description>
+      <name>resetMessageCounterHistory</name>
+   </operation>   
+   
+   <operation>
+      <description>Get the message counter as HTML</description>
+      <name>getMessageCounterAsHTML</name>
+      <return-type>java.lang.String</return-type>
+   </operation>
+   
+   <operation>
+      <description>Get the message counter history as HTML</description>
+      <name>getMessageCounterHistoryAsHTML</name>
+      <return-type>java.lang.String</return-type>
+   </operation>       
+   
 </mbean>

Modified: trunk/src/etc/xmdesc/ServerPeer-xmbean.xml
===================================================================
--- trunk/src/etc/xmdesc/ServerPeer-xmbean.xml	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/etc/xmdesc/ServerPeer-xmbean.xml	2007-01-09 18:16:04 UTC (rev 1930)
@@ -57,7 +57,7 @@
       <name>DefaultExpiryQueue</name>
       <type>javax.management.ObjectName</type>
    </attribute>    
-   
+     
    <!-- instance access -->
 
    <attribute access="read-only" getMethod="getInstance">
@@ -169,6 +169,24 @@
       <name>FailoverCompleteTimeout</name>
       <type>long</type>
    </attribute>      
+   
+   <attribute access="read-write" getMethod="getDefaultRedeliveryDelay" setMethod="setDefaultRedeliveryDelay">
+      <description>How long to wait before redelivery, can be overridden on the destination</description>
+      <name>DefaultRedeliveryDelay</name>
+      <type>long</type>
+   </attribute>  
+   
+   <attribute access="read-write" getMethod="getQueueStatsSamplePeriod" setMethod="setQueueStatsSamplePeriod">
+      <description>The period between which queue statistics are obtained</description>
+      <name>QueueStatsSamplePeriod</name>
+      <type>long</type>
+   </attribute> 
+   
+   <attribute access="read-write" getMethod="getDefaultMessageCounterHistoryDayLimit" setMethod="setDefaultMessageCounterHistoryDayLimit">
+      <description>The default max number of messages per day in message counter history</description>
+      <name>DefaultMessageCounterHistoryDayLimit</name>
+      <type>int</type>
+   </attribute>   
 
    <!-- Managed operations -->
 
@@ -303,5 +321,60 @@
       </parameter>
       <return-type>boolean</return-type>
    </operation>
+   
+   <operation>
+      <description>
+         Get all message counters
+      </description>
+      <name>getMessageCounters</name>
+      <return-type>java.util.List</return-type>
+   </operation> 
+   
+   <operation>
+      <description>
+         Get all message statistics
+      </description>
+      <name>getMessageStatistics</name>
+      <return-type>java.util.List</return-type>
+   </operation>    
+   
+   <operation>
+      <description>
+         List all message counters in HTML
+      </description>
+      <name>listMessageCountersAsHTML</name>
+      <return-type>java.lang.String</return-type>
+   </operation>    
+   
+   <operation>
+      <description>
+         Reset all message counters
+      </description>
+      <name>resetAllMessageCounters</name>
+   </operation>  
+   
+   <operation>
+      <description>
+         Reset all message counter histories
+      </description>
+      <name>resetAllMessageCounterHistories</name>
+   </operation>    
+   
+   <operation>
+      <description>
+         Retrieve list of all prepared transaction ids
+      </description>
+      <name>retrievePreparedTransactions</name>
+      <return-type>java.util.List</return-type>
+   </operation>  
+   
+   <operation>
+      <description>
+         Show of all prepared transaction ids in HTML
+      </description>
+      <name>showPreparedTransactionsAsHTML</name>
+      <return-type>java.lang.String</return-type>
+   </operation>      
+   
 
 </mbean>
\ No newline at end of file

Modified: trunk/src/etc/xmdesc/Topic-xmbean.xml
===================================================================
--- trunk/src/etc/xmdesc/Topic-xmbean.xml	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/etc/xmdesc/Topic-xmbean.xml	2007-01-09 18:16:04 UTC (rev 1930)
@@ -29,15 +29,6 @@
       <type>java.lang.String</type>
    </attribute>
 
-   <!-- This managed attribute is exposed here for backward compatibility with JBossMQ topics
-        management interface only. It will probably dissapear in the future.
-   -->
-   <attribute access="read-only" getMethod="getName">
-      <description>The topic name (deprecated management attribute)</description>
-      <name>TopicName</name>
-      <type>java.lang.String</type>
-   </attribute>
-
    <!-- This attribute is writable to allow configuring an arbitrary JNDI name in the topic's
         service deployment descriptor. Any attempt to change the attribute after initialization
         will be ignored.
@@ -69,6 +60,12 @@
       <name>ExpiryQueue</name>
       <type>javax.management.ObjectName</type>
    </attribute>   
+   
+   <attribute access="read-write" getMethod="getRedeliveryDelay" setMethod="setRedeliveryDelay">
+      <description>The delay before redelivering</description>
+      <name>RedeliveryDelay</name>
+      <type>long</type>
+   </attribute>    
 
    <attribute access="read-write" getMethod="getSecurityConfig" setMethod="setSecurityConfig">
       <description>The destination's security configuration</description>
@@ -81,6 +78,12 @@
       <name>CreatedProgrammatically</name>
       <type>boolean</type>
    </attribute>
+   
+   <attribute access="read-write" getMethod="getMaxSize" setMethod="setMaxSize">
+      <description>The maximum number of messages subscriptions of this topic can hold before they are dropped</description>
+      <name>MaxSize</name>
+      <type>int</type>
+   </attribute>    
 
    <attribute access="read-write" getMethod="getFullSize" setMethod="setFullSize">
       <description>The in-memory message limit, can only be set when topic is stopped</description>
@@ -106,6 +109,55 @@
       <type>boolean</type>
    </attribute>
    
+   <attribute access="read-write" getMethod="getMessageCounterHistoryDayLimit" setMethod="setMessageCounterHistoryDayLimit">
+      <description>The day limit for the message counters of this topic</description>
+      <name>MessageCounterHistoryDayLimit</name>
+      <type>int</type>
+   </attribute>   
+   
+   <attribute access="read-only" getMethod="getMessageCounters">
+      <description>The message counters for the topic</description>
+      <name>MessageCounters</name>
+      <type>java.util.List</type>
+   </attribute>  
+   
+   <attribute access="read-only" getMethod="getAllMessageCount">
+      <description>The count of all messages in all subscriptions of this topic</description>
+      <name>AllMessageCount</name>
+      <type>int</type>
+   </attribute> 
+   
+   <attribute access="read-only" getMethod="getDurableMessageCount">
+      <description>The count of all messages in all durable subscriptions of this topic</description>
+      <name>DurableMessageCount</name>
+      <type>int</type>
+   </attribute>   
+   
+   <attribute access="read-only" getMethod="getNonDurableMessageCount">
+      <description>The count of all messages in all non durable subscriptions of this topic</description>
+      <name>NonDurableMessageCount</name>
+      <type>int</type>
+   </attribute>      
+   
+   <attribute access="read-only" getMethod="getAllSubscriptionsCount">
+      <description>The count of all subscriptions of this topic</description>
+      <name>AllSubscriptionsCount</name>
+      <type>int</type>
+   </attribute> 
+   
+   <attribute access="read-only" getMethod="getDurableSubscriptionsCount">
+      <description>The count of all durable subscriptions of this topic</description>
+      <name>DurableSubscriptionsCount</name>
+      <type>int</type>
+   </attribute>    
+   
+   <attribute access="read-only" getMethod="getNonDurableSubscriptionsCount">
+      <description>The count of all non durable subscriptions of this topic</description>
+      <name>NonDurableSubscriptionsCount</name>
+      <type>int</type>
+   </attribute>    
+   
+   
    <!-- instance access -->
 
    <attribute access="read-only" getMethod="getInstance">
@@ -142,73 +194,122 @@
    </operation>
 
    <operation>
-      <description>Get all subscription count</description>
-      <name>subscriptionCount</name>
-      <return-type>int</return-type>
+      <description>Return all subscriptions for the topic</description>
+      <name>listAllSubscriptions</name>
+      <return-type>java.util.List</return-type>
    </operation>
-
+   
    <operation>
-      <description>Get durable/nondurable subscription count</description>
-      <name>subscriptionCount</name>
-      <parameter>
-         <description>Set the value to true to get durable subscription count; false to get nondurable count</description>
-         <name>durable</name>
-         <type>boolean</type>
-      </parameter>
-      <return-type>int</return-type>
+      <description>Return all durable subscriptions for the topic</description>
+      <name>listDurableSubscriptions</name>
+      <return-type>java.util.List</return-type>
+   </operation> 
+   
+   <operation>
+      <description>Return all non durable subscriptions for the topic</description>
+      <name>listNonDurableSubscriptions</name>
+      <return-type>java.util.List</return-type>
+   </operation>     
+   
+   <operation>
+      <description>Return all subscriptions for the topic in HTML</description>
+      <name>listAllSubscriptionsAsHTML</name>
+      <return-type>java.lang.String</return-type>
    </operation>
-
+   
    <operation>
-      <description>Returns a readable list containing the names of current subscriptions.</description>
-      <name>listSubscriptionsAsText</name>
+      <description>Return all durable subscriptions for the topic in HTML</description>
+      <name>listDurableSubscriptionsAsHTML</name>
       <return-type>java.lang.String</return-type>
-   </operation>
+   </operation> 
+   
+   <operation>
+      <description>Return all non durable subscriptions for the topic in HTML</description>
+      <name>listNonDurableSubscriptionsAsHTML</name>
+      <return-type>java.lang.String</return-type>
+   </operation>      
 
    <operation>
-      <description>Returns a readable list containing the names of current subscriptions.</description>
-      <name>listSubscriptionsAsText</name>
+      <description>List all messages for the specified subscription</description>
+      <name>listAllMessages</name>
       <parameter>
-         <description>Set the value to true to get durable subscription list; false to get nondurable list</description>
-         <name>durable</name>
-         <type>boolean</type>
-      </parameter>
-      <return-type>java.lang.String</return-type>
+         <description>The subscription id</description>
+         <name>subscriptionID</name>
+         <type>java.lang.String</type>
+      </parameter>     
+      <return-type>java.util.List</return-type>
    </operation>
-
+   
    <operation>
-      <description>Get a list of messages for a durable subscription that filtered by selector</description>
-      <name>listMessagesDurableSub</name>
+      <description>List all messages for the specified subscription with the specified selector</description>
+      <name>listAllMessages</name>
       <parameter>
-         <description>The durable subscription name (must specify)</description>
-         <name>name</name>
+         <description>The subscription id</description>
+         <name>subscriptionID</name>
          <type>java.lang.String</type>
-      </parameter>
+      </parameter>     
       <parameter>
-         <description>The durable subscription client ID (if empty, the first matched subscription name will be chosen)</description>
-         <name>clientID</name>
+         <description>The selector</description>
+         <name>selector</name>
          <type>java.lang.String</type>
       </parameter>
+      <return-type>java.util.List</return-type>
+   </operation>   
+   
+   
+   <operation>
+      <description>List all durable messages for the specified subscription</description>
+      <name>listDurableMessages</name>
       <parameter>
-          <description>Expression to define the selector</description>
+         <description>The subscription id</description>
+         <name>subscriptionID</name>
+         <type>java.lang.String</type>
+      </parameter>     
+      <return-type>java.util.List</return-type>
+   </operation>
+   
+   <operation>
+      <description>List all durable messages for the specified subscription with the specified selector</description>
+      <name>listDurableMessages</name>
+      <parameter>
+         <description>The subscription id</description>
+         <name>subscriptionID</name>
+         <type>java.lang.String</type>
+      </parameter>     
+      <parameter>
+         <description>The selector</description>
          <name>selector</name>
          <type>java.lang.String</type>
       </parameter>
       <return-type>java.util.List</return-type>
+   </operation>  
+   
+   <operation>
+      <description>List all non durable messages for the specified subscription</description>
+      <name>listNonDurableMessages</name>
+      <parameter>
+         <description>The subscription id</description>
+         <name>subscriptionID</name>
+         <type>java.lang.String</type>
+      </parameter>     
+      <return-type>java.util.List</return-type>
    </operation>
-
+   
    <operation>
-      <description>Get a list of messages for a non-durable subscription that filtered by selector</description>
-      <name>listMessagesNonDurableSub</name>
+      <description>List all non durable messages for the specified subscription with the specified selector</description>
+      <name>listNonDurableMessages</name>
       <parameter>
-         <description>The non-durable subscription ID (must specify)</description>
+         <description>The subscription id</description>
          <name>subscriptionID</name>
-         <type>long</type>
-      </parameter>
+         <type>java.lang.String</type>
+      </parameter>     
       <parameter>
-         <description>Expression to define the selector</description>
+         <description>The selector</description>
          <name>selector</name>
          <type>java.lang.String</type>
       </parameter>
       <return-type>java.util.List</return-type>
-  </operation>
+   </operation>     
+   
+
 </mbean>

Modified: trunk/src/main/org/jboss/jms/message/JBossBytesMessage.java
===================================================================
--- trunk/src/main/org/jboss/jms/message/JBossBytesMessage.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/message/JBossBytesMessage.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -55,6 +55,8 @@
 {
    // Static -------------------------------------------------------
 
+   private static final long serialVersionUID = 5914561890366707664L;
+
    private static final Logger log = Logger.getLogger(JBossBytesMessage.class);
 
    public static final byte TYPE = 1;

Modified: trunk/src/main/org/jboss/jms/message/JBossMapMessage.java
===================================================================
--- trunk/src/main/org/jboss/jms/message/JBossMapMessage.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/message/JBossMapMessage.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -53,6 +53,8 @@
 {
    // Constants -----------------------------------------------------
 
+   private static final long serialVersionUID = 7939593521831220924L;
+   
    public static final byte TYPE = 2;
 
    // Attributes ----------------------------------------------------

Modified: trunk/src/main/org/jboss/jms/message/JBossMessage.java
===================================================================
--- trunk/src/main/org/jboss/jms/message/JBossMessage.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/message/JBossMessage.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -24,6 +24,7 @@
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.IOException;
+import java.io.Serializable;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
@@ -49,6 +50,7 @@
 import org.jboss.jms.destination.JBossTemporaryTopic;
 import org.jboss.jms.destination.JBossTopic;
 import org.jboss.jms.util.MessagingJMSException;
+import org.jboss.logging.Logger;
 import org.jboss.messaging.core.message.MessageSupport;
 import org.jboss.messaging.util.StreamUtils;
 import org.jboss.util.Primitives;
@@ -58,6 +60,12 @@
  * 
  * Implementation of a JMS Message
  * 
+ * Note that the only reason this class is Serializable is so that messages
+ * can be returned from JMX operations.
+ * 
+ * Java serialization is not used to serialize messages between client and server
+ * in normal JMS operations
+ * 
  * @author <a href="mailto:ovidiu at jboss.org">Ovidiu Feodorov</a>
  * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
  * 
@@ -70,10 +78,11 @@
  *
  * $Id$
  */
-public class JBossMessage extends MessageSupport implements javax.jms.Message
+public class JBossMessage extends MessageSupport implements javax.jms.Message, Serializable
 {
    // Constants -----------------------------------------------------
-          
+   private static final long serialVersionUID = 2833181306818971346L;
+
    public static final byte TYPE = 0;
    
    private static final byte NULL = 0;
@@ -85,7 +94,14 @@
    private static final byte TEMP_QUEUE = 5;
    
    private static final byte TEMP_TOPIC = 6;
+   
+   private static final String JMSX_DELIVERY_COUNT_PROP_NAME = "JMSXDeliveryCount";   
+   
+   public static final String JMS_JBOSS_SCHEDULED_DELIVERY_PROP_NAME = "JMS_JBOSS_SCHEDULED_DELIVERY";
+   
+   private static final Logger log = Logger.getLogger(JBossMessage.class);
 
+
    // Static --------------------------------------------------------
 
    private static final HashSet reservedIdentifiers = new HashSet();
@@ -265,7 +281,7 @@
             expiration,
             timestamp,
             priority,
-            0,
+            0, 0,
             coreHeaders,
             payloadAsByteArray);
 
@@ -346,14 +362,14 @@
          properties = new HashMap();
       }
 
-      for(Enumeration props = foreign.getPropertyNames(); props.hasMoreElements(); )
+      for (Enumeration props = foreign.getPropertyNames(); props.hasMoreElements(); )
       {
          String name = (String)props.nextElement();
          
          Object prop = foreign.getObjectProperty(name);
-         if ("JMSXDeliveryCount".equals(name))
+         if (JMSX_DELIVERY_COUNT_PROP_NAME.equals(name))
          {
-            deliveryCount = foreign.getIntProperty("JMSXDeliveryCount");
+            deliveryCount = foreign.getIntProperty(JMSX_DELIVERY_COUNT_PROP_NAME);
          }
          else
          {
@@ -548,7 +564,8 @@
 
    public boolean propertyExists(String name) throws JMSException
    {
-      return properties.containsKey(name) || "JMSXDeliveryCount".equals(name);
+      return properties.containsKey(name) || JMSX_DELIVERY_COUNT_PROP_NAME.equals(name) ||
+      (this.scheduledDeliveryTime != 0 && JMS_JBOSS_SCHEDULED_DELIVERY_PROP_NAME.equals(name));
    }
 
    public boolean getBooleanProperty(String name) throws JMSException
@@ -597,11 +614,11 @@
 
    public int getIntProperty(String name) throws JMSException
    {
-      if ("JMSXDeliveryCount".equals(name))
+      if (JMSX_DELIVERY_COUNT_PROP_NAME.equals(name))
       {
          return deliveryCount;
       }
-      
+               
       Object value = properties.get(name);
 
       if (value == null)
@@ -633,10 +650,14 @@
 
    public long getLongProperty(String name) throws JMSException
    {
-      if ("JMSXDeliveryCount".equals(name))
+      if (JMSX_DELIVERY_COUNT_PROP_NAME.equals(name))
       {
          return (long)deliveryCount;
       }
+      else if (JMS_JBOSS_SCHEDULED_DELIVERY_PROP_NAME.equals(name) && scheduledDeliveryTime > 0)
+      {
+         return scheduledDeliveryTime;
+      }
 
       Object value = properties.get(name);
 
@@ -703,10 +724,14 @@
 
    public String getStringProperty(String name) throws JMSException
    {
-      if ("JMSXDeliveryCount".equals(name))
+      if (JMSX_DELIVERY_COUNT_PROP_NAME.equals(name))
       {
          return String.valueOf(deliveryCount);
       }
+      else if (JMS_JBOSS_SCHEDULED_DELIVERY_PROP_NAME.equals(name) && scheduledDeliveryTime > 0)
+      {
+         return String.valueOf(scheduledDeliveryTime);
+      }
 
       Object value = properties.get(name);
       if (value == null)
@@ -759,7 +784,11 @@
    {
       HashSet set = new HashSet();
       set.addAll(properties.keySet());
-      set.add("JMSXDeliveryCount");
+      set.add(JMSX_DELIVERY_COUNT_PROP_NAME);
+      if (this.scheduledDeliveryTime > 0)
+      {
+         set.add(JMS_JBOSS_SCHEDULED_DELIVERY_PROP_NAME);
+      }
       return Collections.enumeration(set);
    }
 
@@ -793,9 +822,16 @@
 
    public void setLongProperty(String name, long value) throws JMSException
    {
-      Long l = new Long(value);
-      checkProperty(name, l);
-      properties.put(name, l);
+      if (JMS_JBOSS_SCHEDULED_DELIVERY_PROP_NAME.equals(name))
+      {
+         this.scheduledDeliveryTime = value;
+      }
+      else
+      {
+         Long l = new Long(value);
+         checkProperty(name, l);
+         properties.put(name, l);
+      }
    }
 
    public void setFloatProperty(String name, float value) throws JMSException

Modified: trunk/src/main/org/jboss/jms/message/JBossObjectMessage.java
===================================================================
--- trunk/src/main/org/jboss/jms/message/JBossObjectMessage.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/message/JBossObjectMessage.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -44,6 +44,8 @@
 {
    // Constants -----------------------------------------------------
 
+   private static final long serialVersionUID = -2374448267737763502L;
+   
    public static final byte TYPE = 3;
 
    // Attributes ----------------------------------------------------

Modified: trunk/src/main/org/jboss/jms/message/JBossStreamMessage.java
===================================================================
--- trunk/src/main/org/jboss/jms/message/JBossStreamMessage.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/message/JBossStreamMessage.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -54,6 +54,8 @@
 {
    // Constants -----------------------------------------------------
 
+   private static final long serialVersionUID = 7469150228071568233L;
+
    public static final byte TYPE = 4;
 
    // Attributes ----------------------------------------------------

Modified: trunk/src/main/org/jboss/jms/message/JBossTextMessage.java
===================================================================
--- trunk/src/main/org/jboss/jms/message/JBossTextMessage.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/message/JBossTextMessage.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -50,6 +50,8 @@
 {
    // Constants -----------------------------------------------------
 
+   private static final long serialVersionUID = -5661567664746852006L;
+   
    public static final byte TYPE = 5;
 
    // Attributes ----------------------------------------------------

Added: trunk/src/main/org/jboss/jms/server/MyTimeoutFactory.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/MyTimeoutFactory.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/server/MyTimeoutFactory.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -0,0 +1,68 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jms.server;
+
+import org.jboss.util.threadpool.BasicThreadPool;
+import org.jboss.util.threadpool.ThreadPool;
+import org.jboss.util.timeout.TimeoutFactory;
+
+/**
+ * A TimeoutFactory
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class MyTimeoutFactory
+{
+   public static MyTimeoutFactory instance = new MyTimeoutFactory();
+   
+   private ThreadPool threadPool;
+   
+   private TimeoutFactory factory;
+   
+   private MyTimeoutFactory()
+   {
+      createFactory();
+   }
+   
+   public TimeoutFactory getFactory()
+   {
+      return factory;
+   }
+   
+   public synchronized void reset()
+   {
+      factory.cancel();
+      
+      createFactory();
+   }
+   
+   private void createFactory()
+   {
+      threadPool = new BasicThreadPool();
+      
+      factory = new TimeoutFactory(threadPool);
+   }
+}

Modified: trunk/src/main/org/jboss/jms/server/ServerPeer.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/ServerPeer.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/server/ServerPeer.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -25,29 +25,36 @@
 import java.io.InputStream;
 import java.io.Serializable;
 import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.StringTokenizer;
 
 import javax.management.Attribute;
 import javax.management.InstanceNotFoundException;
 import javax.management.MBeanServer;
 import javax.management.ObjectName;
+import javax.transaction.xa.Xid;
 
 import org.jboss.aop.AspectXmlLoader;
+import org.jboss.jms.client.ClientAOPStackProvider;
 import org.jboss.jms.server.connectionfactory.ConnectionFactoryJNDIMapper;
 import org.jboss.jms.server.connectionmanager.SimpleConnectionManager;
 import org.jboss.jms.server.connectormanager.SimpleConnectorManager;
 import org.jboss.jms.server.destination.ManagedQueue;
 import org.jboss.jms.server.endpoint.ServerSessionEndpoint;
 import org.jboss.jms.server.endpoint.advised.ClientAOPStackProviderAdvised;
+import org.jboss.jms.server.messagecounter.MessageCounter;
+import org.jboss.jms.server.messagecounter.MessageCounterManager;
 import org.jboss.jms.server.plugin.contract.JMSUserManager;
+import org.jboss.jms.server.remoting.JMSDispatcher;
 import org.jboss.jms.server.remoting.JMSServerInvocationHandler;
 import org.jboss.jms.server.remoting.JMSWireFormat;
-import org.jboss.jms.server.remoting.JMSDispatcher;
 import org.jboss.jms.server.security.SecurityMetadataStore;
 import org.jboss.jms.util.ExceptionUtil;
-import org.jboss.jms.client.ClientAOPStackProvider;
 import org.jboss.logging.Logger;
 import org.jboss.messaging.core.Queue;
 import org.jboss.messaging.core.memory.MemoryManager;
@@ -69,6 +76,7 @@
 import org.jboss.remoting.marshal.MarshalFactory;
 import org.jboss.system.ServiceCreator;
 import org.jboss.system.ServiceMBeanSupport;
+import org.jboss.util.JBossStringBuilder;
 import org.w3c.dom.Element;
 
 import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap;
@@ -84,7 +92,7 @@
  *
  * $Id$
  */
-public class ServerPeer extends ServiceMBeanSupport implements ClientAOPStackProvider
+public class ServerPeer extends ServiceMBeanSupport implements ClientAOPStackProvider, ServerPeerMBean
 {
    // Constants -----------------------------------------------------
 
@@ -121,6 +129,12 @@
    private long failoverCompleteTimeout = 12000;
    
    private Map sessions;
+   
+   private long defaultRedeliveryDelay;
+   
+   private long queueStatsSamplePeriod = 10000;
+   
+   private int defaultMessageCounterHistoryDayLimit;
       
    // wired components
 
@@ -136,6 +150,7 @@
    private MemoryManager memoryManager;
    private QueuedExecutorPool queuedExecutorPool;
    private MessageStore messageStore;
+   private MessageCounterManager messageCounterManager;
 
    // plugins
 
@@ -236,6 +251,7 @@
          memoryManager = new SimpleMemoryManager();
          messageStore = new SimpleMessageStore();
          txRepository = new TransactionRepository(persistenceManager, messageStore, transactionIDManager);
+         messageCounterManager = new MessageCounterManager(queueStatsSamplePeriod);
 
          // Start the wired components
 
@@ -250,6 +266,7 @@
          messageStore.start();
          securityStore.start();
          txRepository.start();
+         messageCounterManager.start();
          txRepository.loadPreparedTransactions();
          
          initializeRemoting(mbeanServer);
@@ -306,12 +323,16 @@
          securityStore = null;
          txRepository.stop();
          txRepository = null;
+         messageCounterManager.stop();
+         messageCounterManager = null;
 
          unloadServerAOPConfig();
 
          // TODO unloadClientAOPConfig();
 
          queuedExecutorPool.shutdown();
+         
+         MyTimeoutFactory.instance.reset();
 
          log.info("JMS " + this + " stopped");
       }
@@ -388,8 +409,8 @@
    public synchronized void setDefaultExpiryQueue(ObjectName on)
    {
       this.defaultExpiryQueueObjectName = on;
-   }
-   
+   }     
+      
    // Instance access
 
    public Object getInstance()
@@ -523,6 +544,51 @@
       this.defaultMaxDeliveryAttempts = attempts;
    }
    
+   public synchronized long getQueueStatsSamplePeriod()
+   {
+      return queueStatsSamplePeriod;
+   }
+
+   public synchronized void setQueueStatsSamplePeriod(long newPeriod)
+   {
+      if (newPeriod < 1000)
+      {
+         throw new IllegalArgumentException("Cannot set QueueStatsSamplePeriod < 1000 ms");
+      }
+      
+      if (messageCounterManager != null && newPeriod != queueStatsSamplePeriod)
+      {
+         messageCounterManager.reschedule(newPeriod);
+      }            
+      
+      this.queueStatsSamplePeriod = newPeriod;
+   }
+   
+   public synchronized long getDefaultRedeliveryDelay()
+   {
+      return defaultRedeliveryDelay;
+   }
+   
+   public synchronized void setDefaultRedeliveryDelay(long delay)
+   {
+      this.defaultRedeliveryDelay = delay;
+   }
+   
+   public synchronized int getDefaultMessageCounterHistoryDayLimit()
+   {
+      return defaultMessageCounterHistoryDayLimit;
+   }
+   
+   public void setDefaultMessageCounterHistoryDayLimit(int limit)
+   {
+      if (limit < -1)
+      {
+         limit = -1;
+      }
+      
+      this.defaultMessageCounterHistoryDayLimit = limit;
+   }
+   
    // JMX Operations ------------------------------------------------
 
    public String createQueue(String name, String jndiName) throws Exception
@@ -608,7 +674,220 @@
          throw ExceptionUtil.handleJMXInvocation(t, this + " getDestinations");
       }
    }
+   
+   public List getMessageCounters() throws Exception
+   {
+      Collection counters = messageCounterManager.getMessageCounters();
+      
+      return new ArrayList(counters);
+   }
 
+   public List getMessageStatistics() throws Exception
+   {
+      return MessageCounter.getMessageStatistics(getMessageCounters());
+   }
+
+   public String listMessageCountersAsHTML() throws Exception
+   {
+      List counters = getMessageCounters();
+
+      String ret =
+         "<table width=\"100%\" border=\"1\" cellpadding=\"1\" cellspacing=\"1\">"
+            + "<tr>"
+            + "<th>Type</th>"
+            + "<th>Name</th>"
+            + "<th>Subscription</th>"
+            + "<th>Durable</th>"
+            + "<th>Count</th>"
+            + "<th>CountDelta</th>"
+            + "<th>Depth</th>"
+            + "<th>DepthDelta</th>"
+            + "<th>Last Add</th>"
+            + "</tr>";
+
+      String strNameLast = null;
+      String strTypeLast = null;
+      String strDestLast = null;
+
+      String destData = "";
+      int destCount = 0;
+
+      int countTotal = 0;
+      int countDeltaTotal = 0;
+      int depthTotal = 0;
+      int depthDeltaTotal = 0;
+
+      int i = 0; // define outside of for statement, so variable
+      // still exists after for loop, because it is
+      // needed during output of last module data string
+
+      Iterator iter = counters.iterator();
+      
+      while (iter.hasNext())
+      {
+         MessageCounter counter = (MessageCounter)iter.next();
+         
+         // get counter data
+         StringTokenizer tokens = new StringTokenizer(counter.getCounterAsString(), ",");
+
+         String strType = tokens.nextToken();
+         String strName = tokens.nextToken();
+         String strSub = tokens.nextToken();
+         String strDurable = tokens.nextToken();
+
+         String strDest = strType + "-" + strName;
+
+         String strCount = tokens.nextToken();
+         String strCountDelta = tokens.nextToken();
+         String strDepth = tokens.nextToken();
+         String strDepthDelta = tokens.nextToken();
+         String strDate = tokens.nextToken();
+
+         // update total count / depth values
+         countTotal += Integer.parseInt(strCount);
+         depthTotal += Integer.parseInt(strDepth);
+
+         countDeltaTotal += Integer.parseInt(strCountDelta);
+         depthDeltaTotal += Integer.parseInt(strDepthDelta);
+
+         if (strCountDelta.equalsIgnoreCase("0"))
+            strCountDelta = "-"; // looks better
+
+         if (strDepthDelta.equalsIgnoreCase("0"))
+            strDepthDelta = "-"; // looks better
+
+         // output destination counter data as HTML table row
+         // ( for topics with multiple subscriptions output
+         //   type + name field as rowspans, looks better )
+         if (strDestLast != null && strDestLast.equals(strDest))
+         {
+            // still same destination -> append destination subscription data
+            destData += "<tr bgcolor=\"#" + ((i % 2) == 0 ? "FFFFFF" : "F0F0F0") + "\">";
+            destCount += 1;
+         }
+         else
+         {
+            // start new destination data
+            if (strDestLast != null)
+            {
+               // store last destination data string
+               ret += "<tr bgcolor=\"#"
+                  + ((i % 2) == 0 ? "FFFFFF" : "F0F0F0")
+                  + "\"><td rowspan=\""
+                  + destCount
+                  + "\">"
+                  + strTypeLast
+                  + "</td><td rowspan=\""
+                  + destCount
+                  + "\">"
+                  + strNameLast
+                  + "</td>"
+                  + destData;
+
+               destData = "";
+            }
+
+            destCount = 1;
+         }
+
+         // counter data row
+         destData += "<td>"
+            + strSub
+            + "</td>"
+            + "<td>"
+            + strDurable
+            + "</td>"
+            + "<td>"
+            + strCount
+            + "</td>"
+            + "<td>"
+            + strCountDelta
+            + "</td>"
+            + "<td>"
+            + strDepth
+            + "</td>"
+            + "<td>"
+            + strDepthDelta
+            + "</td>"
+            + "<td>"
+            + strDate
+            + "</td>";
+
+         // store current destination data for change detection
+         strTypeLast = strType;
+         strNameLast = strName;
+         strDestLast = strDest;
+      }
+
+      if (strDestLast != null)
+      {
+         // store last module data string
+         ret += "<tr bgcolor=\"#"
+            + ((i % 2) == 0 ? "FFFFFF" : "F0F0F0")
+            + "\"><td rowspan=\""
+            + destCount
+            + "\">"
+            + strTypeLast
+            + "</td><td rowspan=\""
+            + destCount
+            + "\">"
+            + strNameLast
+            + "</td>"
+            + destData;
+      }
+
+      // append summation info
+      ret += "<tr>"
+         + "<td><![CDATA[ ]]></td><td><![CDATA[ ]]></td>"
+         + "<td><![CDATA[ ]]></td><td><![CDATA[ ]]></td><td>"
+         + countTotal
+         + "</td><td>"
+         + (countDeltaTotal == 0 ? "-" : Integer.toString(countDeltaTotal))
+         + "</td><td>"
+         + depthTotal
+         + "</td><td>"
+         + (depthDeltaTotal == 0 ? "-" : Integer.toString(depthDeltaTotal))
+         + "</td><td>Total</td></tr></table>";
+
+      return ret;
+   }
+
+   public void resetAllMessageCounters()
+   {
+      messageCounterManager.resetAllCounters();
+   }
+   
+   public void resetAllMessageCounterHistories()
+   {
+      messageCounterManager.resetAllCounterHistories();
+   }
+   
+   public List retrievePreparedTransactions()
+   {
+      return txRepository.getPreparedTransactions();
+   }
+
+   public String showPreparedTransactionsAsHTML()
+   {
+      List txs = txRepository.getPreparedTransactions();
+      JBossStringBuilder buffer = new JBossStringBuilder();
+      buffer.append("<table width=\"100%\" border=\"1\" cellpadding=\"1\" cellspacing=\"1\">");
+      buffer.append("<tr><th>Xid</th></tr>");
+      for (Iterator i = txs.iterator(); i.hasNext();)
+      {
+         Xid xid = (Xid)i.next();
+         if (xid != null)
+         {
+            buffer.append("<tr><td>");
+            buffer.append(xid);
+            buffer.append("</td></tr>");
+         }
+      }
+      buffer.append("</table>");
+      return buffer.toString();
+   }
+   
+
    // ClientAOPStackProvider implementation -------------------------------
 
    public byte[] getClientAOPStack()
@@ -618,6 +897,11 @@
 
    // Public --------------------------------------------------------
    
+   public MessageCounterManager getMessageCounterManager()
+   {
+      return messageCounterManager;
+   }
+   
    public IDManager getMessageIDManager()
    {
       return messageIDManager;
@@ -1108,7 +1392,7 @@
    private boolean destroyDestination(boolean isQueue, String name) throws Exception
    {
       String destType = isQueue ? "Queue" : "Topic";
-      String ons ="jboss.messaging.destination:service="+ destType + ",name=" + name;
+      String ons ="jboss.messaging.destination:service=" + destType + ",name=" + name;
       ObjectName on = new ObjectName(ons);
 
       MBeanServer mbeanServer = getServer();

Added: trunk/src/main/org/jboss/jms/server/ServerPeerMBean.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/ServerPeerMBean.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/server/ServerPeerMBean.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -0,0 +1,150 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jms.server;
+
+import java.util.List;
+import java.util.Set;
+
+import javax.management.ObjectName;
+
+import org.w3c.dom.Element;
+
+/**
+ * A ServerPeerMBean
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public interface ServerPeerMBean
+{
+   // JMX attributes
+   
+   int getServerPeerID();
+   
+   String getJMSVersion();
+
+   int getJMSMajorVersion();
+
+   int getJMSMinorVersion();
+
+   String getJMSProviderName();
+
+   String getProviderVersion();
+
+   int getProviderMajorVersion();
+
+   int getProviderMinorVersion();
+
+   String getDefaultQueueJNDIContext();
+
+   String getDefaultTopicJNDIContext();
+   
+   void setSecurityDomain(String securityDomain) throws Exception;
+
+   String getSecurityDomain();
+
+   void setDefaultSecurityConfig(Element conf) throws Exception;
+
+   Element getDefaultSecurityConfig();
+   
+   ObjectName getPersistenceManager();
+
+   void setPersistenceManager(ObjectName on);
+
+   ObjectName getPostOffice();
+
+   void setPostOffice(ObjectName on);
+
+   ObjectName getJmsUserManager();
+
+   void setJMSUserManager(ObjectName on);
+   
+   ObjectName getDefaultDLQ();
+
+   void setDefaultDLQ(ObjectName on);
+   
+   ObjectName getDefaultExpiryQueue();
+
+   void setDefaultExpiryQueue(ObjectName on);
+      
+          
+   int getQueuedExecutorPoolSize();
+
+   void setQueuedExecutorPoolSize(int poolSize);
+   
+   long getFailoverStartTimeout();
+   
+   void setFailoverStartTimeout(long timeout);
+   
+   long getFailoverCompleteTimeout();
+   
+   void setFailoverCompleteTimeout(long timeout);
+   
+   int getDefaultMaxDeliveryAttempts();
+
+   void setDefaultMaxDeliveryAttempts(int attempts);   
+   
+   long getQueueStatsSamplePeriod();
+
+   void setQueueStatsSamplePeriod(long newPeriod);
+   
+   long getDefaultRedeliveryDelay();
+   
+   void setDefaultRedeliveryDelay(long delay);
+   
+   int getDefaultMessageCounterHistoryDayLimit();
+   
+   void setDefaultMessageCounterHistoryDayLimit(int limit);
+   
+   // JMX operations
+   
+   String createQueue(String name, String jndiName) throws Exception;
+
+   String createQueue(String name, String jndiName, int fullSize, int pageSize, int downCacheSize) throws Exception;
+
+   boolean destroyQueue(String name) throws Exception;
+
+   String createTopic(String name, String jndiName) throws Exception;
+
+   String createTopic(String name, String jndiName, int fullSize, int pageSize, int downCacheSize) throws Exception;  
+
+   boolean destroyTopic(String name) throws Exception;
+
+   Set getDestinations() throws Exception;
+   
+   List getMessageCounters() throws Exception;
+
+   List getMessageStatistics() throws Exception;
+
+   String listMessageCountersAsHTML() throws Exception;
+   
+   void resetAllMessageCounters();
+   
+   void resetAllMessageCounterHistories();
+   
+   List retrievePreparedTransactions();
+
+   String showPreparedTransactionsAsHTML();
+}

Added: trunk/src/main/org/jboss/jms/server/destination/DestinationMBean.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/DestinationMBean.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/server/destination/DestinationMBean.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -0,0 +1,97 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jms.server.destination;
+
+import javax.management.ObjectName;
+
+import org.w3c.dom.Element;
+
+/**
+ * A DestinationMBean
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public interface DestinationMBean
+{
+   // JMX attributes
+   
+   String getName();
+
+   String getJNDIName();
+
+   void setJNDIName(String jndiName) throws Exception;
+
+   ObjectName getServerPeer();
+      
+   void setServerPeer(ObjectName on);
+
+   ObjectName getDLQ();
+   
+   void setDLQ(ObjectName on) throws Exception;
+     
+   ObjectName getExpiryQueue();   
+   
+   void setExpiryQueue(ObjectName on) throws Exception;
+   
+   long getRedeliveryDelay();
+   
+   void setRedeliveryDelay(long delay);
+   
+   int getMaxSize();
+   
+   void setMaxSize(int maxSize) throws Exception;
+   
+   Element getSecurityConfig();
+   
+   void setSecurityConfig(Element securityConfig) throws Exception;
+
+   int getFullSize();
+
+   void setFullSize(int fullSize);
+
+   int getPageSize();
+
+   void setPageSize(int pageSize);
+
+   int getDownCacheSize();
+
+   void setDownCacheSize(int downCacheSize);
+   
+   boolean isClustered();
+   
+   void setClustered(boolean clustered);
+   
+   boolean isCreatedProgrammatically();
+   
+   int getMessageCounterHistoryDayLimit();
+   
+   void setMessageCounterHistoryDayLimit(int limit) throws Exception;
+   
+   // JMX operations
+   
+   void removeAllMessages() throws Exception;
+   
+}

Modified: trunk/src/main/org/jboss/jms/server/destination/DestinationServiceSupport.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/DestinationServiceSupport.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/server/destination/DestinationServiceSupport.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -6,6 +6,8 @@
  */
 package org.jboss.jms.server.destination;
 
+import java.util.StringTokenizer;
+
 import javax.management.InstanceNotFoundException;
 import javax.management.ObjectName;
 
@@ -13,6 +15,7 @@
 import org.jboss.jms.server.QueuedExecutorPool;
 import org.jboss.jms.server.SecurityManager;
 import org.jboss.jms.server.ServerPeer;
+import org.jboss.jms.server.messagecounter.MessageCounter;
 import org.jboss.jms.util.ExceptionUtil;
 import org.jboss.messaging.core.Queue;
 import org.jboss.messaging.core.plugin.IDManager;
@@ -38,7 +41,8 @@
  *
  * $Id$
  */
-public abstract class DestinationServiceSupport extends ServiceMBeanSupport implements ServerPlugin
+public abstract class DestinationServiceSupport extends ServiceMBeanSupport
+   implements ServerPlugin, DestinationMBean
 {
    // Constants -----------------------------------------------------
 
@@ -75,9 +79,10 @@
    protected IDManager idm;
    
    protected int nodeId;
-   
+    
    private boolean createdProgrammatically;
    
+   
    // Constructors --------------------------------------------------
    
    public DestinationServiceSupport(boolean createdProgrammatically)
@@ -151,20 +156,32 @@
    
    // JMX managed attributes ----------------------------------------
    
+   public String getName()
+   {
+      return destination.getName();
+   }
+   
    public String getJNDIName()
    {
       return destination.getJndiName();
    }
 
-   public void setJNDIName(String jndiName)
+   public void setJNDIName(String jndiName) throws Exception
    {
-      if (started)
+      try
       {
-         log.warn("Cannot change the value of the JNDI name after initialization!");
-         return;
+         if (started)
+         {
+            log.warn("Cannot change the value of the JNDI name after initialization!");
+            return;
+         }
+   
+         destination.setJndiName(jndiName);      
       }
-
-      destination.setJndiName(jndiName);
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " setJNDIName");
+      }
    }
 
    public void setServerPeer(ObjectName on)
@@ -184,7 +201,7 @@
       return serverPeerObjectName;
    }
    
-   public void setDLQ(ObjectName on)
+   public void setDLQ(ObjectName on) throws Exception
    {
       dlqObjectName = on;
       
@@ -215,11 +232,11 @@
             }
          }
          
-         destination.setDLQ(dlq); 
+         destination.setDLQ(dlq);       
       }
-      catch (Exception e)
+      catch (Throwable t)
       {
-         log.error("Failed to set DLQ", e);
+         throw ExceptionUtil.handleJMXInvocation(t, this + " setDLQ");
       }
    }
    
@@ -228,7 +245,7 @@
       return dlqObjectName;
    }
    
-   public void setExpiryQueue(ObjectName on)
+   public void setExpiryQueue(ObjectName on) throws Exception
    {
       expiryQueueObjectName = on;
       
@@ -236,14 +253,22 @@
       
       try
       {
-         expiryQueue = (Queue)server.getAttribute(expiryQueueObjectName, "Instance");
+         
+         try
+         {
+            expiryQueue = (Queue)server.getAttribute(expiryQueueObjectName, "Instance");
+         }
+         catch (Exception e)
+         {
+            //Ok
+         }
+         
+         destination.setExpiryQueue(expiryQueue);
       }
-      catch (Exception e)
+      catch (Throwable t)
       {
-         //Ok
+         throw ExceptionUtil.handleJMXInvocation(t, this + " setExpiryQueue");
       }
-      
-      destination.setExpiryQueue(expiryQueue);
    }
    
    public ObjectName getExpiryQueue()
@@ -251,6 +276,31 @@
       return expiryQueueObjectName;
    }
    
+   public long getRedeliveryDelay()
+   {
+      return destination.getRedeliveryDelay();
+   }
+   
+   public void setRedeliveryDelay(long delay)
+   {
+      destination.setRedeliveryDelay(delay);
+   }
+   
+   public int getMaxSize()
+   {
+      return destination.getMaxSize();
+   }
+   
+   public void setMaxSize(int maxSize) throws Exception
+   {
+      destination.setMaxSize(maxSize);
+   }
+   
+   public Element getSecurityConfig()
+   {
+      return destination.getSecurityConfig();
+   }
+   
    public void setSecurityConfig(Element securityConfig) throws Exception
    {
       try
@@ -269,17 +319,6 @@
       }
    }
 
-   public Element getSecurityConfig()
-   {
-      return destination.getSecurityConfig();
-   }
-
-   public String getName()
-   {
-      return destination.getName();
-   }
-
-
    /**
     * Get in-memory message limit
     * @return message limit
@@ -368,53 +407,22 @@
    {
       return createdProgrammatically;
    }
-
+   
+   public int getMessageCounterHistoryDayLimit()
+   {
+      return destination.getMessageCounterHistoryDayLimit();
+   }
+   
+   public void setMessageCounterHistoryDayLimit(int limit) throws Exception
+   {
+      destination.setMessageCounterHistoryDayLimit(limit);
+   }
+   
    // JMX managed operations ----------------------------------------
    
-   // TODO implement the following:
+   public abstract void removeAllMessages() throws Exception;
+   
 
-//   void removeAllMessages() throws Exception;
-//
-//   public MessageCounter[] getMessageCounter();
-//
-//   public MessageStatistics[] getMessageStatistics() throws Exception;
-//
-//   public String listMessageCounter();
-//
-//   public void resetMessageCounter();
-//
-//   public String listMessageCounterHistory();
-//
-//   public void resetMessageCounterHistory();
-//
-//   public void setMessageCounterHistoryDayLimit( int days );
-//
-//   public int getMessageCounterHistoryDayLimit();
-//
-//   public int getMaxDepth();
-//
-//   public void setMaxDepth(int depth);
-//
-//   public boolean getInMemory();
-//
-//   public void setInMemory(boolean mode);
-//
-//   public int getRedeliveryLimit();
-//
-//   public void setRedeliveryLimit(int limit);
-//
-//   public long getRedeliveryDelay();
-//
-//   public void setRedeliveryDelay(long rDelay);
-//
-//   public Class getReceiversImpl();
-//
-//   public void setReceiversImpl(Class receivers);
-//
-//   public int getRecoveryRetries();
-//
-//   public void setRecoveryRetries(int retries);
-
    // Public --------------------------------------------------------
 
    public String toString()
@@ -454,7 +462,145 @@
    // Package protected ---------------------------------------------
 
    // Protected -----------------------------------------------------
+   
+   /**
+    * List message counters as HTML table
+    * 
+    * @return String
+    */
+   protected String listMessageCounterAsHTML(MessageCounter[] counters)
+   {
+      if (counters == null)
+         return null;
+      
+      String ret = "<table width=\"100%\" border=\"1\" cellpadding=\"1\" cellspacing=\"1\">"  +
+                   "<tr>"                  +
+                   "<th>Type</th>"         +
+                   "<th>Name</th>"         +
+                   "<th>Subscription</th>" +
+                   "<th>Durable</th>"      +
+                   "<th>Count</th>"        +
+                   "<th>CountDelta</th>"   +
+                   "<th>Depth</th>"        +
+                   "<th>DepthDelta</th>"   +
+                   "<th>Last Add</th>"     +
+                   "</tr>";
+      
+      for( int i=0; i<counters.length; i++ )
+      {
+         String            data = counters[i].getCounterAsString();
+         StringTokenizer   token = new StringTokenizer( data, ",");
+         String            value;
+         
+         ret += "<tr bgcolor=\"#" + ( (i%2)==0 ? "FFFFFF" : "F0F0F0") + "\">";
 
+         ret += "<td>" + token.nextToken() + "</td>"; // type
+         ret += "<td>" + token.nextToken() + "</td>"; // name
+         ret += "<td>" + token.nextToken() + "</td>"; // subscription
+         ret += "<td>" + token.nextToken() + "</td>"; // durable
+
+         ret += "<td>" + token.nextToken() + "</td>"; // count
+         
+         value = token.nextToken(); // countDelta
+
+         if( value.equalsIgnoreCase("0") )
+             value = "-";
+             
+         ret += "<td>" + value + "</td>";
+         
+         ret += "<td>" + token.nextToken() + "</td>"; // depth
+         
+         value = token.nextToken(); // depthDelta
+         
+         if( value.equalsIgnoreCase("0") )
+             value = "-";
+             
+         ret += "<td>" + value + "</td>";
+
+         ret += "<td>" + token.nextToken() + "</td>"; // date last add
+
+         ret += "</tr>";
+      }
+      
+      ret += "</table>";
+      
+      return ret;
+   }      
+   
+   /**
+    * List destination message counter history as HTML table
+    * 
+    * @return String
+    */
+   protected String listMessageCounterHistoryAsHTML(MessageCounter[] counters)
+   {
+      if (counters == null)
+         return null;
+      
+      String           ret = "";
+               
+      for( int i=0; i<counters.length; i++ )
+      {
+         // destination name
+         ret += ( counters[i].getDestinationTopic() ? "Topic '" : "Queue '" );
+         ret += counters[i].getDestinationName() + "'";
+         
+         if( counters[i].getDestinationSubscription() != null )
+            ret += "Subscription '" + counters[i].getDestinationSubscription() + "'";
+            
+                     
+         // table header
+         ret += "<table width=\"100%\" border=\"1\" cellpadding=\"1\" cellspacing=\"1\">"  +
+                "<tr>"                  +
+                "<th>Date</th>";
+
+         for( int j = 0; j < 24; j++ )
+            ret += "<th width=\"4%\">" + j + "</th>";
+
+         ret += "<th>Total</th></tr>";
+
+         // get history data as CSV string         
+         StringTokenizer tokens = new StringTokenizer( counters[i].getHistoryAsString(), ",\n");
+         
+         // get history day count
+         int days = Integer.parseInt( tokens.nextToken() );
+         
+         for( int j=0; j<days; j++ )
+         {
+            // next day counter row 
+            ret += "<tr bgcolor=\"#" + ((j%2)==0 ? "FFFFFF" : "F0F0F0") + "\">";
+         
+            // date 
+            ret += "<td>" + tokens.nextToken() + "</td>";
+             
+            // 24 hour counters
+            int total = 0;
+            
+            for( int k=0; k<24; k++ )
+            {
+               int value = Integer.parseInt( tokens.nextToken().trim() );
+            
+               if( value == -1 )
+               {
+                    ret += "<td></td>";
+               }  
+               else
+               {
+                    ret += "<td>" + value + "</td>";
+                    
+                    total += value;
+               } 
+            }
+
+            ret += "<td>" + total + "</td></tr>";
+         }
+
+         ret += "</table><br><br>";
+      }
+
+      return ret;
+   }
+
    protected abstract boolean isQueue();
 
    // Private -------------------------------------------------------

Modified: trunk/src/main/org/jboss/jms/server/destination/ManagedDestination.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/ManagedDestination.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/server/destination/ManagedDestination.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -21,9 +21,16 @@
  */
 package org.jboss.jms.server.destination;
 
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.jboss.jms.server.JMSCondition;
+import org.jboss.jms.server.ServerPeer;
 import org.jboss.messaging.core.Queue;
+import org.jboss.messaging.core.plugin.contract.Condition;
 import org.jboss.messaging.core.plugin.contract.MessagingComponent;
 import org.jboss.messaging.core.plugin.contract.PostOffice;
+import org.jboss.messaging.core.plugin.postoffice.Binding;
 import org.w3c.dom.Element;
 
 /**
@@ -37,11 +44,19 @@
  */
 public abstract class ManagedDestination implements MessagingComponent
 {
+   protected static final int ALL = 0;
+   
+   protected static final int DURABLE = 1;
+   
+   protected static final int NON_DURABLE = 2;
+   
+      
    private static final int DEFAULT_FULL_SIZE = 75000;
    
    private static final int DEFAULT_PAGE_SIZE = 2000;
    
    private static final int DEFAULT_DOWN_CACHE_SIZE = 2000;
+      
    
    protected String name;
    
@@ -62,12 +77,18 @@
    
    protected Element securityConfig;
    
-   protected PostOffice postOffice;
+   protected ServerPeer serverPeer;
    
    protected Queue dlq;
    
    protected Queue expiryQueue;
    
+   protected long redeliveryDelay;
+   
+   protected int maxSize = -1;
+   
+   protected int messageCounterHistoryDayLimit = -1;
+    
    public ManagedDestination()
    {      
    }
@@ -152,15 +173,15 @@
    {
       this.securityConfig = securityConfig;
    }
-
-   public PostOffice getPostOffice()
+   
+   public ServerPeer getServerPeer()
    {
-      return postOffice;
+      return serverPeer;
    }
 
-   public void setPostOffice(PostOffice postOffice)
+   public void setServerPeer(ServerPeer serverPeer)
    {
-      this.postOffice = postOffice;
+      this.serverPeer = serverPeer;
    }
 
    public boolean isTemporary()
@@ -193,6 +214,51 @@
       this.expiryQueue = expiryQueue;
    }
    
+   public long getRedeliveryDelay()
+   {
+      return redeliveryDelay;
+   }
+   
+   public void setRedeliveryDelay(long delay)
+   {
+      this.redeliveryDelay = delay;
+   }
+   
+   public int getMaxSize()
+   {
+      return maxSize;
+   }
+   
+   public void setMaxSize(int maxSize) throws Exception
+   {
+      Condition cond = new JMSCondition(isQueue(), name);
+      
+      PostOffice postOffice = serverPeer.getPostOfficeInstance();
+      
+      Collection subs = postOffice.getBindingsForCondition(cond);
+      
+      Iterator iter = subs.iterator();
+
+      while (iter.hasNext())
+      {
+         Binding binding = (Binding)iter.next();
+         
+         binding.getQueue().setMaxSize(maxSize);
+      }
+      
+      this.maxSize = maxSize;
+   }
+   
+   public int getMessageCounterHistoryDayLimit()
+   {
+      return this.messageCounterHistoryDayLimit;
+   }
+   
+   public void setMessageCounterHistoryDayLimit(int limit) throws Exception
+   {
+      this.messageCounterHistoryDayLimit = limit;
+   }
+     
    public abstract boolean isQueue();
 
    public void start() throws Exception

Modified: trunk/src/main/org/jboss/jms/server/destination/ManagedQueue.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/ManagedQueue.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/server/destination/ManagedQueue.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -21,16 +21,15 @@
  */
 package org.jboss.jms.server.destination;
 
+import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 
-import javax.jms.InvalidSelectorException;
-import javax.jms.JMSException;
-
 import org.jboss.jms.selector.Selector;
-import org.jboss.jms.server.JMSCondition;
+import org.jboss.jms.server.messagecounter.MessageCounter;
+import org.jboss.logging.Logger;
+import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.Queue;
-import org.jboss.messaging.core.plugin.postoffice.Binding;
-import org.jboss.logging.Logger;
 
 /**
  * A ManagedQueue
@@ -54,6 +53,10 @@
    private static boolean trace = log.isTraceEnabled();
 
    // Attributes -----------------------------------------------------------------------------------
+   
+   private MessageCounter messageCounter;
+   
+   private Queue queue;
 
    // Constructors ---------------------------------------------------------------------------------
 
@@ -72,88 +75,119 @@
    {
       return true;
    }
+   
+   public void setMessageCounterHistoryDayLimit(int limit) throws Exception
+   {
+      super.setMessageCounterHistoryDayLimit(limit);
+      
+      if (messageCounter != null)
+      {
+         messageCounter.setHistoryLimit(limit);
+      }
+   }
 
    // Public ---------------------------------------------------------------------------------------
 
    public int getMessageCount() throws Exception
    {
-      JMSCondition queueCond = new JMSCondition(true, name);
+      int count = queue.getMessageCount();
 
-      Binding binding = (Binding)postOffice.getBindingForCondition(queueCond).iterator().next();
+      if (trace) { log.trace(this + " returning MessageCount = " + count); }
 
-      if (binding == null)
-      {
-         throw new IllegalStateException("Cannot find binding for queue:" + name);
-      }
+      return count;
+   }
+   
+   public int getScheduledMessageCount() throws Exception
+   {     
+      int count = queue.getScheduledCount();
 
-      Queue queue = binding.getQueue();
+      if (trace) { log.trace(this + " returning ScheduledMessageCount = " + count); }
 
-      int count = queue.getMessageCount();
+      return count;
+   }
+   
+   public int getConsumersCount() throws Exception
+   {
+      int count = queue.getNumberOfReceivers();
 
-      if (trace) { log.trace(this + " returning MessageCount = " + count); }
+      if (trace) { log.trace(this + " returning ConsumersCount = " + count); }
 
       return count;
    }
 
    public void removeAllMessages() throws Throwable
    {
-      JMSCondition queueCond = new JMSCondition(true, name);
-
-      Binding binding = (Binding)postOffice.getBindingForCondition(queueCond).iterator().next();
-
-      if (binding == null)
-      {
-         throw new IllegalStateException("Cannot find binding for queue:" + name);
-      }
-
-      Queue queue = binding.getQueue();
-
       queue.removeAllReferences();
    }
 
-   public List listMessages(String selector) throws Exception
+   public List listAllMessages(String selector) throws Exception
    {
-      if (selector != null)
+      return this.listMessages(ALL, selector);
+   }
+   
+   public List listDurableMessages(String selector) throws Exception
+   {
+      return this.listMessages(DURABLE, selector);
+   }
+   
+   public List listNonDurableMessages(String selector) throws Exception
+   {
+      return this.listMessages(NON_DURABLE, selector);
+   }
+   
+   private List listMessages(int type, String selector) throws Exception
+   {
+      Selector sel = null;
+                        
+      if (selector != null && "".equals(selector.trim()))
       {
-         selector = selector.trim();
-         if (selector.equals(""))
-         {
-            selector = null;
-         }
+         selector = null;
       }
-
-      JMSCondition queueCond = new JMSCondition(true, name);
-
-      Binding binding = (Binding)postOffice.getBindingForCondition(queueCond).iterator().next();
-
-      if (binding == null)
-      {
-         throw new IllegalStateException("Cannot find binding for queue:" + name);
+      
+      if (selector != null)
+      {        
+         sel = new Selector(selector);
       }
-
-      Queue queue = binding.getQueue();
-
-      try
+      
+      List msgs = new ArrayList();
+      
+      List allMsgs = queue.browse(sel);
+      
+      Iterator iter = allMsgs.iterator();
+      
+      while (iter.hasNext())
       {
-         List msgs;
-         if (selector == null)
+         Message msg = (Message)iter.next();
+         
+         if (type == ALL || (type == DURABLE && msg.isReliable()) || (type == NON_DURABLE && !msg.isReliable()))
          {
-            msgs = queue.browse();
+            msgs.add(msg);
          }
-         else
-         {
-            msgs = queue.browse(new Selector(selector));
-         }
-         return msgs;
       }
-      catch (InvalidSelectorException e)
-      {
-         Throwable th = new JMSException(e.getMessage());
-         th.initCause(e);
-         throw (JMSException)th;
-      }
+      
+      return msgs;
    }
-
+   
+   public MessageCounter getMessageCounter()
+   {
+      return messageCounter;
+   }
+   
+   public void setMessageCounter(MessageCounter counter)
+   {
+      this.messageCounter = counter;
+   }
+   
+   public void setQueue(Queue queue)
+   {
+      this.queue = queue;
+   }
+   
+   public Queue getQueue()
+   {
+      return queue;
+   }
+   
    public String toString()
    {
       return "ManagedQueue[" + name + "]";

Modified: trunk/src/main/org/jboss/jms/server/destination/ManagedTopic.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/ManagedTopic.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/server/destination/ManagedTopic.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -26,11 +26,12 @@
 import java.util.Iterator;
 import java.util.List;
 
-import javax.jms.InvalidSelectorException;
-
 import org.jboss.jms.selector.Selector;
 import org.jboss.jms.server.JMSCondition;
+import org.jboss.jms.server.messagecounter.MessageCounter;
 import org.jboss.jms.util.MessageQueueNameHelper;
+import org.jboss.logging.Logger;
+import org.jboss.messaging.core.Message;
 import org.jboss.messaging.core.Queue;
 import org.jboss.messaging.core.plugin.postoffice.Binding;
 
@@ -46,7 +47,9 @@
  *
  */
 public class ManagedTopic extends ManagedDestination
-{
+{  
+   private static final Logger log = Logger.getLogger(ManagedTopic.class); 
+   
    public ManagedTopic()
    {      
    }
@@ -60,7 +63,7 @@
    {
       JMSCondition topicCond = new JMSCondition(false, name);
       
-      Collection subs = postOffice.getBindingForCondition(topicCond);
+      Collection subs = serverPeer.getPostOfficeInstance().getBindingsForCondition(topicCond);
       
       //XXX How to lock down all subscriptions?
       Iterator iter = subs.iterator();
@@ -72,203 +75,321 @@
       }
    }
    
-   public int subscriptionCount() throws Exception
+   public int getAllMessageCount() throws Exception
    {
-      JMSCondition topicCond = new JMSCondition(false, name);
-      
-      Collection subs = postOffice.getBindingForCondition(topicCond);
-      
-      return subs.size();         
+      return getMessageCount(ALL);
+   }     
+   
+   public int getDurableMessageCount() throws Exception
+   {
+      return getMessageCount(DURABLE);
    }
    
-   public int subscriptionCount(boolean durable) throws Exception
+   public int getNonDurableMessageCount() throws Exception
    {
+      return getMessageCount(NON_DURABLE);
+   }
+   
+   public int getAllSubscriptionsCount() throws Exception
+   {
       JMSCondition topicCond = new JMSCondition(false, name);
       
-      Collection subs = postOffice.getBindingForCondition(topicCond);
+      Collection subs = serverPeer.getPostOfficeInstance().getBindingsForCondition(topicCond);
       
-      Iterator iter = subs.iterator();
+      return subs.size();         
+   }
       
-      int count = 0;
-      
-      while (iter.hasNext())
-      {
-         Binding binding = (Binding)iter.next();
-         
-         if ((binding.getQueue().isRecoverable() && durable) || (!binding.getQueue().isRecoverable() && !durable))
-         {
-            count++;
-         }
-      }
-
-      return count;
+   public int getDurableSubscriptionsCount() throws Exception
+   {
+      return getSubscriptionsCount(true);
    }
    
-   public String listSubscriptionsAsText() throws Exception
+   public int getNonDurableSubscriptionsCount() throws Exception
    {
-      JMSCondition topicCond = new JMSCondition(false, name);
-      
-      Collection subs = postOffice.getBindingForCondition(topicCond);
-      
-      return getSubscriptionsAsText(subs, true) + getSubscriptionsAsText(subs, false);
+      return getSubscriptionsCount(false);
    }
    
-   public String listSubscriptionsAsText(boolean durable) throws Exception
+   public List listAllSubscriptions() throws Exception
    {
-      JMSCondition topicCond = new JMSCondition(false, name);
-      
-      Collection subs = postOffice.getBindingForCondition(topicCond);
-      
-      return getSubscriptionsAsText(subs, durable);
+      return listSubscriptions(ALL);
    }
    
-   public List listMessagesDurableSub(String subName, String clientID, String selector)
-      throws Exception
+   public List listDurableSubscriptions() throws Exception
    {
-      JMSCondition topicCond = new JMSCondition(false, name);
-      
-      Collection subs = postOffice.getBindingForCondition(topicCond);
-      
-      return getMessagesFromDurableSub(subs, subName, clientID, trimSelector(selector));
+      return listSubscriptions(DURABLE);
    }
    
-   public List listMessagesNonDurableSub(long channelID, String selector)
-      throws Exception
+   public List listNonDurableSubscriptions() throws Exception
    {
-      JMSCondition topicCond = new JMSCondition(false, name);
-      
-      Collection subs = postOffice.getBindingForCondition(topicCond);
-      
-      return getMessagesFromNonDurableSub(subs, channelID, trimSelector(selector));
+      return listSubscriptions(NON_DURABLE);
    }
    
-   public boolean isQueue()
+
+   public String listAllSubscriptionsAsHTML() throws Exception
    {
-      return false;
+      return listSubscriptionsAsHTML(ALL);
    }
    
-   // Private -------------------------------------------------------------
+   public String listDurableSubscriptionsAsHTML() throws Exception
+   {
+      return listSubscriptionsAsHTML(DURABLE);
+   }
    
+   public String listNonDurableSubscriptionsAsHTML() throws Exception
+   {
+      return listSubscriptionsAsHTML(NON_DURABLE);
+   }
    
    
-   private String getSubscriptionsAsText(Collection bindings, boolean durable)
+   public List listAllMessages(String subId, String selector) throws Exception
    {
-      StringBuffer sb = new StringBuffer();
+      return listMessages(ALL, subId, selector);
+   }
+   
+   public List listDurableMessages(String subId, String selector) throws Exception
+   {
+      return listMessages(DURABLE, subId, selector);
+   }
+   
+   public List listNonDurableMessages(String subId, String selector) throws Exception
+   {
+      return listMessages(NON_DURABLE, subId, selector);
+   }
+   
+   public List getMessageCounters() throws Exception
+   {
+      JMSCondition topicCond = new JMSCondition(false, name);
+      
+      List counters = new ArrayList();
+      
+      // We deploy any queues corresponding to pre-existing durable subscriptions
+      Collection bindings = serverPeer.getPostOfficeInstance().getBindingsForCondition(topicCond);
       Iterator iter = bindings.iterator();
       while (iter.hasNext())
       {
          Binding binding = (Binding)iter.next();
          
-         String filterString = binding.getQueue().getFilter() != null ? binding.getQueue().getFilter().getFilterString() : null;
-                  
-         if (durable && binding.getQueue().isRecoverable())
-         {                      
-            MessageQueueNameHelper helper = MessageQueueNameHelper.createHelper(binding.getQueue().getName());
-            
-            sb.append("Durable, subscriptionID=\"");
-            sb.append(binding.getQueue().getChannelID());    
-            sb.append("\", name=\"");
-            sb.append(helper.getSubName());
-            sb.append("\", clientID=\"");
-            sb.append(helper.getClientId());
-            sb.append("\", selector=\"");
-            sb.append(filterString);
-            sb.append("\"\n");
+         Queue queue = binding.getQueue();
+         
+         String counterName = TopicService.SUBSCRIPTION_MESSAGECOUNTER_PREFIX + queue.getName();
+         
+         MessageCounter counter = serverPeer.getMessageCounterManager().getMessageCounter(counterName);
+         
+         if (counter == null)
+         {
+            throw new IllegalStateException("Cannot find counter with name " + counterName);
          }
-         else if (!durable && !binding.getQueue().isRecoverable())
-         {            
-            sb.append("Non-durable, subscriptionID=\"");
-            sb.append(binding.getQueue().getChannelID());
-            sb.append("\", selector=\"");
-            sb.append(filterString);
-            sb.append("\"\n");
-         }
+         
+         counters.add(counter);
       }
-      return sb.toString();
-   }
-     
-   // Test if the durable subscriptions match
-   private boolean matchDurableSubscription(String name, String clientID, Binding binding)
-   {
-      // Validate the name
-      if (null == name)
-         throw new IllegalArgumentException();
-      // Must be durable
-      if (!binding.getQueue().isRecoverable())
-         return false;
       
-      MessageQueueNameHelper helper = MessageQueueNameHelper.createHelper(binding.getQueue().getName());
-
-      // Subscription name check
-      if (!name.equals(helper.getSubName()))
-         return false;
-      // Client ID check: if no client ID specified, it's considered as matched 
-      if (null == clientID || 0 == clientID.length())
-         return true;
-      if (!clientID.equals(helper.getClientId()))
-         return false;
-      return true;
+      return counters; 
    }
    
-   // Test if the non-durable subscriptions match
-   private boolean matchNonDurableSubscription(long channelID, Binding binding)
+   public boolean isQueue()
    {
-      // Must be non-durable
-      if (binding.getQueue().isRecoverable())
-         return false;
-      // Channel ID must be the same
-      if (channelID != binding.getQueue().getChannelID())
-         return false;
-      return true;
+      return false;
    }
    
-   private List getMessagesFromDurableSub(Collection bindings, String name,
-            String clientID, String selector) throws InvalidSelectorException
+   public void setMessageCounterHistoryDayLimit(int limit) throws Exception
    {
-      Iterator iter = bindings.iterator();
+      super.setMessageCounterHistoryDayLimit(limit);
+      
+      List counters = getMessageCounters();
+      
+      Iterator iter = counters.iterator();
+      
       while (iter.hasNext())
       {
-         Binding binding = (Binding)iter.next();
-         // If subID matches, then get message list from the subscription
-         if (matchDurableSubscription(name, clientID, binding))
+         MessageCounter counter = (MessageCounter)iter.next();
+         
+         counter.setHistoryLimit(limit);
+      }
+   }
+   
+   // Private -------------------------------------------------------------
+   
+   private List listMessages(int type, String subId, String selector) throws Exception
+   { 
+      List msgs = new ArrayList();
+      
+      Binding binding = serverPeer.getPostOfficeInstance().getBindingForQueueName(subId);
+      
+      if (binding == null)
+      {
+         throw new IllegalArgumentException("Cannot find subscription with id " + subId);
+      }
+      
+      Selector sel = null;
+      
+      if (selector != null && "".equals(selector.trim()))
+      {
+         selector = null;
+      }
+         
+      if (selector != null)
+      {  
+         sel = new Selector(selector);
+      }
+      
+      List allMsgs = binding.getQueue().browse(sel);
+      
+      Iterator iter = allMsgs.iterator();
+      
+      while (iter.hasNext())
+      {
+         Message msg = (Message)iter.next();
+         
+         if (type == ALL || (type == DURABLE && msg.isReliable()) || (type == NON_DURABLE && !msg.isReliable()))
          {
-            Queue queue = binding.getQueue();
-            return queue.browse(null == selector ? null : new Selector(selector));
+            msgs.add(msg);
          }
-      }   
-      // No match, return an empty list
-      return new ArrayList();
+      }
+      
+      return msgs;
    }
    
-   private List getMessagesFromNonDurableSub(Collection bindings, long channelID, String selector) throws InvalidSelectorException
-   {
+   private List listSubscriptions(int type) throws Exception
+   {      
+      List subs = new ArrayList();
+   
+      JMSCondition topicCond = new JMSCondition(false, name);      
+      
+      Collection bindings = serverPeer.getPostOfficeInstance().getBindingsForCondition(topicCond);
+      
       Iterator iter = bindings.iterator();
+      
       while (iter.hasNext())
       {
          Binding binding = (Binding)iter.next();
-         // If subID matches, then get message list from the subscription
-         if (matchNonDurableSubscription(channelID, binding))
-            return binding.getQueue().browse(null == selector ? null : new Selector(selector));
-      }   
-      // No match, return an empty list
-      return new ArrayList();
+         
+         Queue queue = binding.getQueue();
+         
+         if (type == ALL || (type == DURABLE && queue.isRecoverable()) || (type == NON_DURABLE && !queue.isRecoverable()))
+         {         
+            String subName = null;
+            String clientID = null;
+            
+            if (queue.isRecoverable())
+            {
+               MessageQueueNameHelper helper = MessageQueueNameHelper.createHelper(queue.getName());
+               subName = helper.getSubName();
+               clientID = helper.getClientId();
+            }
+            
+            SubscriptionInfo info = new SubscriptionInfo(queue.getName(), queue.isRecoverable(), subName, clientID,
+                     queue.getFilter() == null ? null : queue.getFilter().getFilterString(), queue.getMessageCount(), queue.getMaxSize());
+            
+            subs.add(info);
+         }
+      }
+      
+      return subs;
    }
    
-   private String trimSelector(String selector)
+   private int getMessageCount(int type) throws Exception
    {
-      if (selector == null)
+      JMSCondition topicCond = new JMSCondition(false, name);
+      
+      Collection subs = serverPeer.getPostOfficeInstance().getBindingsForCondition(topicCond);
+      
+      Iterator iter = subs.iterator();
+      
+      int count = 0;
+      
+      while (iter.hasNext())
       {
-         return null;
+         Binding binding = (Binding)iter.next();
+         
+         if (type == ALL || (type == DURABLE && binding.getQueue().isRecoverable())
+             || (type == NON_DURABLE && !binding.getQueue().isRecoverable()))
+         {            
+            count += binding.getQueue().getMessageCount();
+         }
       }
 
-      selector = selector.trim();
-
-      if (selector.length() == 0)
+      return count;
+   }  
+   
+   private int getSubscriptionsCount(boolean durable) throws Exception
+   {
+      JMSCondition topicCond = new JMSCondition(false, name);
+      
+      Collection subs = serverPeer.getPostOfficeInstance().getBindingsForCondition(topicCond);
+      
+      Iterator iter = subs.iterator();
+      
+      int count = 0;
+      
+      while (iter.hasNext())
       {
-         return null;
+         Binding binding = (Binding)iter.next();
+         
+         if ((binding.getQueue().isRecoverable() && durable) || (!binding.getQueue().isRecoverable() && !durable))
+         {
+            count++;
+         }
       }
 
-      return selector;
+      return count;
    }
-
+   
+   
+   private String listSubscriptionsAsHTML(int type) throws Exception
+   {
+      JMSCondition topicCond = new JMSCondition(false, name);
+      
+      Collection bindings = serverPeer.getPostOfficeInstance().getBindingsForCondition(topicCond);
+           
+      StringBuffer sb = new StringBuffer();
+      
+      sb.append("<table width=\"100%\" border=\"1\" cellpadding=\"1\" cellspacing=\"1\">"  +
+                  "<tr>"                  +
+                  "<th>Id</th>"         +
+                  "<th>Durable</th>" +
+                  "<th>Subscription Name</th>"      +
+                  "<th>Client ID</th>"        +
+                  "<th>Selector</th>"   +
+                  "<th>Message Count</th>"        +
+                  "<th>Max Size</th>"   +
+                  "</tr>");
+      
+      Iterator iter = bindings.iterator();
+      while (iter.hasNext())
+      {
+         Binding binding = (Binding)iter.next();
+         
+         Queue queue = binding.getQueue();
+         
+         if (type == ALL || (type == DURABLE && queue.isRecoverable())
+                  || (type == NON_DURABLE && !queue.isRecoverable()))
+         {
+            
+            String filterString = queue.getFilter() != null ? binding.getQueue().getFilter().getFilterString() : null;
+                     
+            String subName = null;
+            String clientID = null;
+            
+            if (queue.isRecoverable())
+            {
+               MessageQueueNameHelper helper = MessageQueueNameHelper.createHelper(queue.getName());
+               subName = helper.getSubName();
+               clientID = helper.getClientId();
+            }
+            
+            sb.append("<tr><td>").append(queue.getName()).append("</td>");
+            sb.append("<td>").append(queue.isRecoverable() ? "Durable" : "Non Durable").append("</td>");
+            sb.append("<td>").append(subName != null ? subName : "").append("</td>");
+            sb.append("<td>").append(clientID != null ? clientID : "").append("</td>");
+            sb.append("<td>").append(filterString != null ? filterString : "").append("</td>");
+            sb.append("<td>").append(queue.getMessageCount()).append("</td>");
+            sb.append("<td>").append(queue.getMaxSize()).append("</td>");
+            sb.append("</tr>");
+         }
+      }
+      sb.append("</table>");
+      
+      return sb.toString();                                
+   }
+      
 }

Added: trunk/src/main/org/jboss/jms/server/destination/QueueMBean.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/QueueMBean.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/server/destination/QueueMBean.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -0,0 +1,73 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jms.server.destination;
+
+import java.util.List;
+
+import org.jboss.jms.server.messagecounter.MessageCounter;
+import org.jboss.jms.server.messagecounter.MessageStatistics;
+
+/**
+ * A QueueMBean
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public interface QueueMBean
+{
+   // JMX attributes
+   
+   int getMessageCount() throws Exception;
+   
+   int getScheduledMessageCount() throws Exception;
+               
+   MessageCounter getMessageCounter();
+   
+   MessageStatistics getMessageStatistics() throws Exception;
+   
+   int getConsumerCount() throws Exception;
+   
+   // JMX operations
+   
+   void resetMessageCounter();
+   
+   void resetMessageCounterHistory();
+      
+   List listAllMessages() throws Exception;
+   
+   List listAllMessages(String selector) throws Exception;
+   
+   List listDurableMessages() throws Exception;
+   
+   List listDurableMessages(String selector) throws Exception;
+   
+   List listNonDurableMessages() throws Exception;
+   
+   List listNonDurableMessages(String selector) throws Exception;
+   
+   String getMessageCounterAsHTML();
+   
+   String getMessageCounterHistoryAsHTML();
+}

Modified: trunk/src/main/org/jboss/jms/server/destination/QueueService.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/QueueService.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/server/destination/QueueService.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -9,9 +9,14 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.jms.IllegalStateException;
+
 import org.jboss.jms.server.JMSCondition;
+import org.jboss.jms.server.messagecounter.MessageCounter;
+import org.jboss.jms.server.messagecounter.MessageStatistics;
 import org.jboss.jms.util.ExceptionUtil;
 import org.jboss.jms.util.XMLUtil;
+import org.jboss.messaging.core.Queue;
 import org.jboss.messaging.core.local.PagingFilteredQueue;
 import org.jboss.messaging.core.plugin.contract.ClusteredPostOffice;
 import org.jboss.messaging.core.plugin.postoffice.Binding;
@@ -29,9 +34,11 @@
  *
  * $Id$
  */
-public class QueueService extends DestinationServiceSupport
+public class QueueService extends DestinationServiceSupport implements QueueMBean
 {
    // Constants -----------------------------------------------------
+   
+   private static final String QUEUE_MESSAGECOUNTER_PREFIX = "Queue.";
 
    // Static --------------------------------------------------------
    
@@ -51,28 +58,8 @@
       destination = new ManagedQueue();      
    }
    
-   // JMX managed attributes ----------------------------------------
+   // ServiceMBeanSupport overrides --------------------------------
    
-   public int getMessageCount() throws Exception
-   {
-      try
-      {
-         if (!started)
-         {
-            log.warn("Queue is stopped");
-            return 0;
-         }
-         
-         return ((ManagedQueue)destination).getMessageCount();
-      }
-      catch (Throwable t)
-      {
-         throw ExceptionUtil.handleJMXInvocation(t, this + " getMessageCount");
-      }
-   }
-
-   // JMX managed operations ----------------------------------------
-   
    public synchronized void startService() throws Exception
    {
       super.startService();
@@ -81,22 +68,28 @@
       {                           
          postOffice = serverPeer.getPostOfficeInstance();
          
-         destination.setPostOffice(postOffice);
+         destination.setServerPeer(serverPeer);
 
          //Binding must be added before destination is registered in JNDI
          //otherwise the user could get a reference to the destination and use it
          //while it is still being loaded
-         
+             
          //Binding might already exist
             
          Binding binding = postOffice.getBindingForQueueName(destination.getName());
          
+         PagingFilteredQueue queue;
+         
          if (binding != null)
          {     
-            PagingFilteredQueue queue = (PagingFilteredQueue)binding.getQueue();
-            
+            queue = (PagingFilteredQueue)binding.getQueue();
+                
             queue.setPagingParams(destination.getFullSize(), destination.getPageSize(), destination.getDownCacheSize());
             queue.load();
+            
+            //Must be done after load
+            queue.setMaxSize(destination.getMaxSize());
+            
             queue.activate();
          }
          else
@@ -105,14 +98,12 @@
             
             //Create a new queue       
             
-            PagingFilteredQueue queue;
-            
             JMSCondition queueCond = new JMSCondition(true, destination.getName());
             
             if (postOffice.isLocal())
             {
                queue = new PagingFilteredQueue(destination.getName(), idm.getID(), ms, pm, true, true,
-                                               executor, null,
+                                               executor, destination.getMaxSize(), null,
                                                destination.getFullSize(), destination.getPageSize(), destination.getDownCacheSize());
                
                
@@ -122,7 +113,7 @@
             else
             {               
                queue = new LocalClusteredQueue(postOffice, nodeId, destination.getName(), idm.getID(), ms, pm, true, true,
-                                               executor, null, tr, 
+                                               executor, destination.getMaxSize(), null, tr, 
                                                destination.getFullSize(), destination.getPageSize(), destination.getDownCacheSize());
                
                ClusteredPostOffice cpo = (ClusteredPostOffice)postOffice;
@@ -138,6 +129,25 @@
             }                        
          }
          
+         ((ManagedQueue)destination).setQueue(queue);
+         
+         String counterName = QUEUE_MESSAGECOUNTER_PREFIX + destination.getName();
+         
+         int dayLimitToUse = destination.getMessageCounterHistoryDayLimit();
+         if (dayLimitToUse == -1)
+         {
+            //Use override on server peer
+            dayLimitToUse = serverPeer.getDefaultMessageCounterHistoryDayLimit();
+         }
+         
+         MessageCounter counter =
+            new MessageCounter(counterName, null, queue, false, false,
+                               dayLimitToUse);
+         
+         ((ManagedQueue)destination).setMessageCounter(counter);
+                  
+         serverPeer.getMessageCounterManager().registerMessageCounter(counterName, counter);
+                       
          dm.registerDestination(destination);
         
          log.debug(this + " security configuration: " + (destination.getSecurityConfig() == null ?
@@ -160,11 +170,17 @@
       {
          dm.unregisterDestination(destination);
          
-         //We undeploy the queue from memory - this also deactivates the binding
-         Binding binding = postOffice.getBindingForQueueName(destination.getName());
+         Queue queue = ((ManagedQueue)destination).getQueue();
          
-         PagingFilteredQueue queue = (PagingFilteredQueue)binding.getQueue();
+         String counterName = QUEUE_MESSAGECOUNTER_PREFIX + destination.getName();
+                  
+         MessageCounter counter = serverPeer.getMessageCounterManager().unregisterMessageCounter(counterName);
          
+         if (counter == null)
+         {
+            throw new IllegalStateException("Cannot find counter to unregister " + counterName);
+         }
+         
          queue.deactivate();
          queue.unload();
          
@@ -178,6 +194,72 @@
       }
    }
    
+   
+   // JMX managed attributes ----------------------------------------
+   
+   public int getMessageCount() throws Exception
+   {
+      try
+      {
+         if (!started)
+         {
+            log.warn("Queue is stopped");
+            return 0;
+         }
+         
+         return ((ManagedQueue)destination).getMessageCount();
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " getMessageCount");
+      }
+   }
+   
+   public int getScheduledMessageCount() throws Exception
+   {
+      try
+      {
+         if (!started)
+         {
+            log.warn("Queue is stopped");
+            return 0;
+         }
+         
+         return ((ManagedQueue)destination).getScheduledMessageCount();
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " getMessageCount");
+      }
+   }
+   
+   public MessageCounter getMessageCounter()
+   {
+      return ((ManagedQueue)destination).getMessageCounter();
+   }
+   
+   public MessageStatistics getMessageStatistics() throws Exception
+   {
+      List counters = new ArrayList();
+      counters.add(getMessageCounter());
+      
+      List stats = MessageCounter.getMessageStatistics(counters);
+      
+      return (MessageStatistics)stats.get(0);
+   }
+   
+   public String getMessageCounterAsHTML()
+   {
+      return super.listMessageCounterAsHTML(new MessageCounter[] { getMessageCounter() });
+   }
+   
+   public int getConsumerCount() throws Exception
+   {
+      return ((ManagedQueue)destination).getConsumersCount();
+   }
+     
+   // JMX managed operations ----------------------------------------
+      
    public void removeAllMessages() throws Exception
    {
       try
@@ -196,24 +278,129 @@
       } 
    }
    
-   public List listMessages(String selector) throws Exception
+   public List listAllMessages() throws Exception
    {
       try
       {
          if (!started)
          {
             log.warn("Queue is stopped.");
-            return new ArrayList();
+            return null;
          }
          
-         return ((ManagedQueue)destination).listMessages(selector);
+         return ((ManagedQueue)destination).listAllMessages(null);
       }
       catch (Throwable t)
       {
-         throw ExceptionUtil.handleJMXInvocation(t, this + " listMessages");
+         throw ExceptionUtil.handleJMXInvocation(t, this + " listAllMessages");
       } 
    }
-    
+   
+   public List listAllMessages(String selector) throws Exception
+   {
+      try
+      {
+         if (!started)
+         {
+            log.warn("Queue is stopped.");
+            return null;
+         }
+         
+         return ((ManagedQueue)destination).listAllMessages(selector);
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " listAllMessages");
+      } 
+   }
+   
+   public List listDurableMessages() throws Exception
+   {
+      try
+      {
+         if (!started)
+         {
+            log.warn("Queue is stopped.");
+            return null;
+         }
+         
+         return ((ManagedQueue)destination).listDurableMessages(null);
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " listDurableMessages");
+      } 
+   }
+   
+   public List listDurableMessages(String selector) throws Exception
+   {
+      try
+      {
+         if (!started)
+         {
+            log.warn("Queue is stopped.");
+            return null;
+         }
+         
+         return ((ManagedQueue)destination).listDurableMessages(selector);
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " listDurableMessages");
+      } 
+   }
+   
+   public List listNonDurableMessages() throws Exception
+   {
+      try
+      {
+         if (!started)
+         {
+            log.warn("Queue is stopped.");
+            return null;
+         }
+         
+         return ((ManagedQueue)destination).listNonDurableMessages(null);
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " listNonDurableMessages");
+      } 
+   }
+   
+   public List listNonDurableMessages(String selector) throws Exception
+   {
+      try
+      {
+         if (!started)
+         {
+            log.warn("Queue is stopped.");
+            return null;
+         }
+         
+         return ((ManagedQueue)destination).listNonDurableMessages(selector);
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " listNonDurableMessages");
+      } 
+   }
+            
+   public void resetMessageCounter()
+   {
+      ((ManagedQueue)destination).getMessageCounter().resetCounter();
+   }
+   
+   public String getMessageCounterHistoryAsHTML()
+   {
+      return super.listMessageCounterHistoryAsHTML(new MessageCounter[] { getMessageCounter() });
+   }
+ 
+   public void resetMessageCounterHistory()
+   {
+      ((ManagedQueue)destination).getMessageCounter().resetHistory();
+   }
+       
    // Public --------------------------------------------------------
 
    // Package protected ---------------------------------------------

Added: trunk/src/main/org/jboss/jms/server/destination/SubscriptionInfo.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/SubscriptionInfo.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/server/destination/SubscriptionInfo.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -0,0 +1,99 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jms.server.destination;
+
+import java.io.Serializable;
+
+/**
+ * A SubscriptionInfo
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class SubscriptionInfo implements Serializable
+{
+   private static final long serialVersionUID = -38689006079435295L;
+
+   private String id;
+   
+   private boolean durable;
+   
+   private String name;
+   
+   private String clientID;
+   
+   private String selector;
+   
+   private int messageCount;
+   
+   private int maxSize;
+   
+   public SubscriptionInfo(String id, boolean durable, String name, String clientID, String selector, int messageCount, int maxSize)
+   {
+      this.id = id;
+      this.durable = durable;
+      this.name = name;
+      this.clientID = clientID;
+      this.selector = selector;
+      this.messageCount = messageCount;
+      this.maxSize = maxSize;
+   }
+   
+   public String getId()
+   {
+      return id;
+   }
+
+   public String getClientID()
+   {
+      return clientID;
+   }
+
+   public boolean isDurable()
+   {
+      return durable;
+   }
+
+   public int getMaxSize()
+   {
+      return maxSize;
+   }
+
+   public int getMessageCount()
+   {
+      return messageCount;
+   }
+
+   public String getName()
+   {
+      return name;
+   }
+
+   public String getSelector()
+   {
+      return selector;
+   }
+
+}

Added: trunk/src/main/org/jboss/jms/server/destination/TopicMBean.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/TopicMBean.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/server/destination/TopicMBean.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -0,0 +1,80 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jms.server.destination;
+
+import java.util.List;
+
+/**
+ * A TopicMBean
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public interface TopicMBean
+{
+   //JMX attributes
+    
+   int getAllMessageCount() throws Exception;
+      
+   int getDurableMessageCount() throws Exception;
+      
+   int getNonDurableMessageCount() throws Exception;
+   
+   int getAllSubscriptionsCount() throws Exception;
+
+   int getDurableSubscriptionsCount() throws Exception;
+   
+   int getNonDurableSubscriptionsCount() throws Exception;
+   
+   // JMX operations
+   
+   void removeAllMessages() throws Exception;
+      
+   List listAllSubscriptions() throws Exception;
+   
+   List listDurableSubscriptions() throws Exception;
+   
+   List listNonDurableSubscriptions() throws Exception;
+   
+   String listAllSubscriptionsAsHTML() throws Exception;
+   
+   String listDurableSubscriptionsAsHTML() throws Exception;
+   
+   String listNonDurableSubscriptionsAsHTML() throws Exception;
+   
+   List listAllMessages(String subscriptionId) throws Exception;
+   
+   List listAllMessages(String subscriptionId, String selector) throws Exception;
+   
+   List listDurableMessages(String subscriptionId) throws Exception;
+   
+   List listDurableMessages(String subscriptionId, String selector) throws Exception;
+   
+   List listNonDurableMessages(String subscriptionId) throws Exception;
+   
+   List listNonDurableMessages(String subscriptionId, String selector) throws Exception;
+   
+   List getMessageCounters() throws Exception;      
+}

Modified: trunk/src/main/org/jboss/jms/server/destination/TopicService.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/destination/TopicService.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/server/destination/TopicService.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -6,7 +6,6 @@
  */
 package org.jboss.jms.server.destination;
 
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
@@ -14,7 +13,9 @@
 import javax.jms.JMSException;
 
 import org.jboss.jms.server.JMSCondition;
+import org.jboss.jms.server.messagecounter.MessageCounter;
 import org.jboss.jms.util.ExceptionUtil;
+import org.jboss.jms.util.MessageQueueNameHelper;
 import org.jboss.jms.util.XMLUtil;
 import org.jboss.messaging.core.local.PagingFilteredQueue;
 import org.jboss.messaging.core.plugin.postoffice.Binding;
@@ -31,9 +32,11 @@
  *
  * $Id$
  */
-public class TopicService extends DestinationServiceSupport
+public class TopicService extends DestinationServiceSupport implements TopicMBean
 {
    // Constants -----------------------------------------------------
+   
+   public static final String SUBSCRIPTION_MESSAGECOUNTER_PREFIX = "Subscription.";
 
    // Static --------------------------------------------------------
 
@@ -52,11 +55,9 @@
       
       destination = new ManagedTopic();      
    }
-
-   // JMX managed attributes ----------------------------------------
-
-   // JMX managed operations ----------------------------------------
    
+   // ServiceMBeanSupport overrides ---------------------------------
+   
    public synchronized void startService() throws Exception
    {
       super.startService();
@@ -67,23 +68,46 @@
 
          if (postOffice == null)
           throw new IllegalArgumentException("Post Office instance not found. Check your destination configuration.");
-
-         destination.setPostOffice(postOffice);
+         destination.setServerPeer(serverPeer);
          
          JMSCondition topicCond = new JMSCondition(false, destination.getName());
                     
          // We deploy any queues corresponding to pre-existing durable subscriptions
-         Collection bindings = postOffice.getBindingForCondition(topicCond);
+         Collection bindings = postOffice.getBindingsForCondition(topicCond);
          Iterator iter = bindings.iterator();
          while (iter.hasNext())
          {
             Binding binding = (Binding)iter.next();
             
             PagingFilteredQueue queue = (PagingFilteredQueue)binding.getQueue();
-                        
+                     
+            //TODO We need to set the paging params this way since the post office doesn't store them
+            //instead we should never create queues inside the postoffice - only do it at deploy time
             queue.setPagingParams(destination.getFullSize(), destination.getPageSize(), destination.getDownCacheSize());
+            
             queue.load();
-            queue.activate();            
+            queue.activate();  
+            
+            //Must be done after load
+            queue.setMaxSize(destination.getMaxSize());  
+            
+            //Create a counter
+            String counterName = SUBSCRIPTION_MESSAGECOUNTER_PREFIX + queue.getName();
+            
+            String subName = MessageQueueNameHelper.createHelper(queue.getName()).getSubName();
+            
+            int dayLimitToUse = destination.getMessageCounterHistoryDayLimit();
+            if (dayLimitToUse == -1)
+            {
+               //Use override on server peer
+               dayLimitToUse = serverPeer.getDefaultMessageCounterHistoryDayLimit();
+            }
+            
+            MessageCounter counter =
+               new MessageCounter(counterName, subName, queue, true, true,
+                                  dayLimitToUse);
+            
+            serverPeer.getMessageCounterManager().registerMessageCounter(counterName, counter);
          }
 
          dm.registerDestination(destination);
@@ -116,7 +140,7 @@
          
          JMSCondition topicCond = new JMSCondition(false, destination.getName());         
          
-         Collection bindings = postOffice.getBindingForCondition(topicCond);
+         Collection bindings = postOffice.getBindingsForCondition(topicCond);
          
          Iterator iter = bindings.iterator();
          while (iter.hasNext())            
@@ -132,6 +156,11 @@
                         
             queue.deactivate();
             queue.unload();
+            
+            //unregister counter
+            String counterName = SUBSCRIPTION_MESSAGECOUNTER_PREFIX + queue.getName();
+            
+            serverPeer.getMessageCounterManager().unregisterMessageCounter(counterName);
          }
           
          started = false;
@@ -143,33 +172,69 @@
       }
    }
 
-   /**
-    * Remove all messages from subscription's storage.
-    */
-   public void removeAllMessages() throws Exception
+   // JMX managed attributes ----------------------------------------
+   
+   public int getAllMessageCount() throws Exception
    {
       try
       {
          if (!started)
          {
             log.warn("Topic is stopped.");
-            return;
+            return -1;
          }
          
-         ((ManagedTopic)destination).removeAllMessages();
+         return ((ManagedTopic)destination).getAllMessageCount();
       }
       catch (Throwable t)
       {
-         throw ExceptionUtil.handleJMXInvocation(t, this + " removeAllMessages");
+         throw ExceptionUtil.handleJMXInvocation(t, this + " getAllMessageCount");
       } 
    }
    
+   
+   public int getDurableMessageCount() throws Exception
+   {
+      try
+      {
+         if (!started)
+         {
+            log.warn("Topic is stopped.");
+            return -1;
+         }
+         
+         return ((ManagedTopic)destination).getDurableMessageCount();
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " getDurableMessageCount");
+      }
+   }
+   
+   public int getNonDurableMessageCount() throws Exception
+   {
+      try
+      {
+         if (!started)
+         {
+            log.warn("Topic is stopped.");
+            return -1;
+         }
+         
+         return ((ManagedTopic)destination).getNonDurableMessageCount();
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " getNonDurableMessageCount");
+      }
+   }
+   
    /**
     * All subscription count
     * @return all subscription count
     * @throws JMSException
     */
-   public int subscriptionCount() throws Exception
+   public int getAllSubscriptionsCount() throws Exception
    {
       try
       {
@@ -179,22 +244,15 @@
             return 0;
          }
    
-         return ((ManagedTopic)destination).subscriptionCount();        
+         return ((ManagedTopic)destination).getAllSubscriptionsCount();        
       }
       catch (Throwable t)
       {
-         throw ExceptionUtil.handleJMXInvocation(t, this + " subscriptionCount");
+         throw ExceptionUtil.handleJMXInvocation(t, this + " getAllSubscriptionsCount");
       } 
    }
 
-   /**
-    * Durable/nondurable subscription count
-    * @param durable If true return durable subscription count.
-    *                If false return nondurable subscription count.
-    * @return either durable or nondurable subscription count depending on param.
-    * @throws JMSException
-    */
-   public int subscriptionCount(boolean durable) throws Exception
+   public int getDurableSubscriptionsCount() throws Exception
    {
       try
       {
@@ -204,286 +262,297 @@
             return 0;
          }
          
-         return ((ManagedTopic)destination).subscriptionCount(durable);
+         return ((ManagedTopic)destination).getDurableSubscriptionsCount();
       }
       catch (Throwable t)
       {
-         throw ExceptionUtil.handleJMXInvocation(t, this + " subscriptionCount");
+         throw ExceptionUtil.handleJMXInvocation(t, this + " getDurableSubscriptionsCount");
       } 
    }
-
-   /**
-    * XXX Placeholder
-    * Get all subscription list.
-    * @return List of CoreSubscription. Never null. 
-    * @throws JMSException
-    * @see ManageableTopic#getSubscriptions()
-    */
-   /*
-   public List listSubscriptions() throws JMSException
+   
+   public int getNonDurableSubscriptionsCount() throws Exception
    {
+      try
+      {
+         if (!started)
+         {
+            log.warn("Topic is stopped.");
+            return 0;
+         }
+         
+         return ((ManagedTopic)destination).getNonDurableSubscriptionsCount();
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " getNonDurableSubscriptionsCount");
+      } 
    }
-   */
 
+   // JMX managed operations ----------------------------------------
+      
+
    /**
-    * Returns a human readable list containing the names of current subscriptions.
-    * @return String of subscription list. Never null.
+    * Remove all messages from subscription's storage.
     */
-   public String listSubscriptionsAsText() throws Exception
+   public void removeAllMessages() throws Exception
    {
       try
       {
          if (!started)
          {
             log.warn("Topic is stopped.");
-            return "";
+            return;
          }
+         
+         ((ManagedTopic)destination).removeAllMessages();
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " removeAllMessages");
+      } 
+   }         
    
-         return ((ManagedTopic)destination).listSubscriptionsAsText();
-
+   public List listAllSubscriptions() throws Exception
+   {
+      try
+      {
+         if (!started)
+         {
+            log.warn("Topic is stopped.");
+            return null;
+         }
+         
+         return ((ManagedTopic)destination).listAllSubscriptions();
       }
       catch (Throwable t)
       {
-         throw ExceptionUtil.handleJMXInvocation(t, this + " listSubscriptionsAsText");
+         throw ExceptionUtil.handleJMXInvocation(t, this + " listAllSubscriptions");
       } 
    }
    
+   public List listDurableSubscriptions() throws Exception
+   {
+      try
+      {
+         if (!started)
+         {
+            log.warn("Topic is stopped.");
+            return null;
+         }
+         
+         return ((ManagedTopic)destination).listDurableSubscriptions();
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " listDurableSubscriptions");
+      } 
+   }
    
-
-   /**
-    * Returns a human readable list containing the names of current subscriptions.
-    * @param durable If true, return durable subscription list.
-    *                If false, return non-durable subscription list.
-    * @return String of subscription list. Never null.
-    */
-   public String listSubscriptionsAsText(boolean durable) throws Exception
+   public List listNonDurableSubscriptions() throws Exception
    {
       try
       {
          if (!started)
          {
             log.warn("Topic is stopped.");
+            return null;
+         }
+         
+         return ((ManagedTopic)destination).listNonDurableSubscriptions();
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " listNonDurableSubscriptions");
+      } 
+   }
+   
+   public String listAllSubscriptionsAsHTML() throws Exception
+   {
+      try
+      {
+         if (!started)
+         {
+            log.warn("Topic is stopped.");
             return "";
          }
    
-         return ((ManagedTopic)destination).listSubscriptionsAsText(durable);
+         return ((ManagedTopic)destination).listAllSubscriptionsAsHTML();
       }
       catch (Throwable t)
       {
-         throw ExceptionUtil.handleJMXInvocation(t, this + " listSubscriptionsAsText");
+         throw ExceptionUtil.handleJMXInvocation(t, this + " listAllSubscriptionsAsHTML");
       } 
    }
-
-   /**
-    * XXX Placeholder
-    * Get durable/non-durable subscription list.
-    * @param durable If true, return durable subscription list.
-    *                If false, return non-durable subscription list.
-    * @return List of CoreDurableSubscription/CoreSubscription. Never null.
-    * @throws JMSException
-    * @see ManageableTopic#getSubscriptions(boolean)
-    */
-   /*
-   public List listSubscriptions(boolean durable) throws JMSException
+   
+   public String listDurableSubscriptionsAsHTML() throws Exception
    {
-      JBossTopic jbt = new JBossTopic(name);
-      ManageableTopic t = (ManageableTopic)cm.getCoreDestination(jbt);
-      return t.getSubscriptions(durable);
+      try
+      {
+         if (!started)
+         {
+            log.warn("Topic is stopped.");
+            return "";
+         }
+   
+         return ((ManagedTopic)destination).listDurableSubscriptionsAsHTML();
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " listDurableSubscriptionsAsHTML");
+      } 
    }
-   */
    
-   /**
-    * XXX Placeholder
-    * Get messages from certain subscription.
-    * @param channelID @see #listSubscriptions()
-    * @param clientID @see #listSubscriptions()
-    * @param subName @see #listSubscriptions()
-    * @param selector Filter expression
-    * @return list of javax.jms.Message
-    * @throws JMSException
-    * @see ManageableTopic#getMessages(long, String, String, String)
-    */
-   /*
-   public List listMessages(long channelID, String clientID, String subName, String selector)
-      throws JMSException
+   public String listNonDurableSubscriptionsAsHTML() throws Exception
    {
-      JBossTopic jbt = new JBossTopic(name);
-      ManageableTopic t = (ManageableTopic)cm.getCoreDestination(jbt);
-      return t.getMessages(channelID, clientID, subName, trimSelector(selector));
+      try
+      {
+         if (!started)
+         {
+            log.warn("Topic is stopped.");
+            return "";
+         }
+   
+         return ((ManagedTopic)destination).listNonDurableSubscriptionsAsHTML();
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " listNonDurableSubscriptionsAsHTML");
+      } 
    }
-   */
    
-   /**
-    * Get messages from a durable subscription.
-    * @param subName Subscription name.
-    * @param clientID Client ID.
-    * @param selector Filter expression.
-    * @return list of javax.jms.Message
-    * @throws JMSException
-    * @see ManageableTopic#getMessagesFromDurableSub(String, String, String)
-    */
-   public List listMessagesDurableSub(String subName, String clientID, String selector)
-      throws Exception
+   public List listAllMessages(String subscriptionId) throws Exception
    {
       try
       {
          if (!started)
          {
             log.warn("Topic is stopped.");
-            return new ArrayList();
+            return null;
          }
    
-         return ((ManagedTopic)destination).listMessagesDurableSub(subName, clientID, selector);
+         return ((ManagedTopic)destination).listAllMessages(subscriptionId, null);
       }
       catch (Throwable t)
       {
-         throw ExceptionUtil.handleJMXInvocation(t, this + " listMessagesDurableSub");
-      } 
+         throw ExceptionUtil.handleJMXInvocation(t, this + " listMessages");
+      }
    }
    
-   /**
-    * Get messages from a non-durable subscription.
-    * @param channelID
-    * @param selector Filter expression.
-    * @return list of javax.jms.Message
-    * @throws JMSException
-    * @see ManageableTopic#getMessagesFromNonDurableSub(Long, String)
-    */
-   public List listMessagesNonDurableSub(long channelID, String selector)
-      throws Exception
+   public List listAllMessages(String subscriptionId, String selector) throws Exception
    {
       try
       {
          if (!started)
          {
             log.warn("Topic is stopped.");
-            return new ArrayList();
+            return null;
          }
-         
-         return ((ManagedTopic)destination).listMessagesNonDurableSub(channelID, selector);
+   
+         return ((ManagedTopic)destination).listAllMessages(subscriptionId, selector);
       }
       catch (Throwable t)
       {
-         throw ExceptionUtil.handleJMXInvocation(t, this + " listMessagesNonDurableSub");
-      } 
+         throw ExceptionUtil.handleJMXInvocation(t, this + " listMessages");
+      }
    }
-
    
-   // TODO implement these:
-
-//   int getAllMessageCount();
-//
-//   int getDurableMessageCount();
-//
-//   int getNonDurableMessageCount();
-//
-//   int getAllSubscriptionsCount();
-//
-//   int getDurableSubscriptionsCount();
-//
-//   int getNonDurableSubscriptionsCount();
-//
-//   java.util.List listAllSubscriptions();
-//
-//   java.util.List listDurableSubscriptions();
-//
-//   java.util.List listNonDurableSubscriptions();
-//
-//   java.util.List listMessages(java.lang.String id) throws java.lang.Exception;
-//
-//   java.util.List listMessages(java.lang.String id, java.lang.String selector) throws java.lang.Exception;
-//
-//   List listNonDurableMessages(String id, String sub) throws Exception;
-//
-//   List listNonDurableMessages(String id, String sub, String selector) throws Exception;
-//
-//   List listDurableMessages(String id, String name) throws Exception;
-//
-//   List listDurableMessages(String id, String name, String selector) throws Exception;
-
-   // Public --------------------------------------------------------
-
-   // Package protected ---------------------------------------------
-
-   // Protected -----------------------------------------------------
-
-   protected boolean isQueue()
+   
+   public List listDurableMessages(String subscriptionId) throws Exception
    {
-      return false;
+      try
+      {
+         if (!started)
+         {
+            log.warn("Topic is stopped.");
+            return null;
+         }
+   
+         return ((ManagedTopic)destination).listDurableMessages(subscriptionId, null);
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " listDurableMessages");
+      }
    }
    
- 
-   /**
-    * XXX Placeholder
-    * @see ManageableTopic#getSubscriptions()
-    */
-   /*
-   public List getSubscriptions()
+   public List listDurableMessages(String subscriptionId, String selector) throws Exception
    {
-      ArrayList list = new ArrayList();
-      Iterator iter = iterator();
-      while (iter.hasNext())
+      try
       {
-         CoreSubscription sub = (CoreSubscription)iter.next();
-         if (sub instanceof CoreDurableSubscription)
-            list.add(new String[]{ 
-                        Long.toString(sub.getChannelID()), 
-                        ((CoreDurableSubscription)sub).getClientID(),
-                        ((CoreDurableSubscription)sub).getName()});
-         else
-            list.add(new String[]{ 
-                  Long.toString(sub.getChannelID()), "", ""});
+         if (!started)
+         {
+            log.warn("Topic is stopped.");
+            return null;
+         }
+   
+         return ((ManagedTopic)destination).listDurableMessages(subscriptionId, selector);
       }
-      return list;
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " listDurableMessages");
+      }
    }
-   */
    
+   public List listNonDurableMessages(String subscriptionId) throws Exception
+   {
+      try
+      {
+         if (!started)
+         {
+            log.warn("Topic is stopped.");
+            return null;
+         }
    
-   /**
-    * XXX Placeholder
-    * @see ManageableTopic#getSubscriptions(boolean)
-    */
-   /*
-   public List getSubscriptions(boolean durable)
+         return ((ManagedTopic)destination).listNonDurableMessages(subscriptionId, null);
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " listNonDurableMessages");
+      }
+   }
+   
+   public List listNonDurableMessages(String subscriptionId, String selector) throws Exception
    {
-      ArrayList list = new ArrayList();
-      Iterator iter = iterator();
-      while (iter.hasNext())
+      try
       {
-         CoreSubscription sub = (CoreSubscription)iter.next();
-         if (sub instanceof CoreDurableSubscription && durable)
-            list.add(new String[]{ 
-                        Long.toString(sub.getChannelID()), 
-                        ((CoreDurableSubscription)sub).getClientID(),
-                        ((CoreDurableSubscription)sub).getName()});
-         else if (!(sub instanceof CoreDurableSubscription) && !durable)
-            list.add(new String[]{ 
-                  Long.toString(sub.getChannelID()), "", ""});
+         if (!started)
+         {
+            log.warn("Topic is stopped.");
+            return null;
+         }
+   
+         return ((ManagedTopic)destination).listNonDurableMessages(subscriptionId, selector);
       }
-      return list;
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " listNonDurableMessages");
+      }
    }
-   */   
    
-   /**
-    * XXX Placeholder
-    * @see ManageableTopic#getMessages(long, String, String, String)
-    */
-   /*
-   public List getMessages(long channelID, String clientID, String subName, String selector) throws InvalidSelectorException
+   public List getMessageCounters()
+      throws Exception
    {
-      Iterator iter = iterator();
-      while (iter.hasNext())
+      try
       {
-         CoreSubscription sub = (CoreSubscription)iter.next();
-         // If subID matches, then get message list from the subscription
-         if (matchSubscription(channelID, clientID, subName, sub))
-            return sub.browse(null == selector ? null : new Selector(selector));
-      }   
-      // No match, return an empty list
-      return new ArrayList();
+         return ((ManagedTopic)destination).getMessageCounters();       
+      }
+      catch (Throwable t)
+      {
+         throw ExceptionUtil.handleJMXInvocation(t, this + " listMessagesNonDurableSub");
+      } 
    }
-   */
+   
+   // Public --------------------------------------------------------
 
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   protected boolean isQueue()
+   {
+      return false;
+   }   
+
    // Private -------------------------------------------------------
 
    // Inner classes -------------------------------------------------

Modified: trunk/src/main/org/jboss/jms/server/endpoint/ServerConnectionEndpoint.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/endpoint/ServerConnectionEndpoint.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/server/endpoint/ServerConnectionEndpoint.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -43,10 +43,11 @@
 import org.jboss.jms.server.SecurityManager;
 import org.jboss.jms.server.ServerPeer;
 import org.jboss.jms.server.endpoint.advised.SessionAdvised;
+import org.jboss.jms.server.messagecounter.MessageCounter;
 import org.jboss.jms.server.remoting.JMSDispatcher;
 import org.jboss.jms.server.remoting.JMSWireFormat;
+import org.jboss.jms.tx.ClientTransaction;
 import org.jboss.jms.tx.TransactionRequest;
-import org.jboss.jms.tx.ClientTransaction;
 import org.jboss.jms.tx.ClientTransaction.SessionTxState;
 import org.jboss.jms.util.ExceptionUtil;
 import org.jboss.jms.util.ToString;
@@ -316,7 +317,16 @@
    
                if (dest.isQueue())
                {     
-                  postOffice.unbindQueue(dest.getName());               
+                  postOffice.unbindQueue(dest.getName()); 
+                  
+                  String counterName = ServerSessionEndpoint.TEMP_QUEUE_MESSAGECOUNTER_PREFIX + dest.getName();
+                  
+                  MessageCounter counter = serverPeer.getMessageCounterManager().unregisterMessageCounter(counterName);
+                  
+                  if (counter == null)
+                  {
+                     throw new IllegalStateException("Cannot find counter to unregister " + counterName);
+                  }
                }
                else
                {

Modified: trunk/src/main/org/jboss/jms/server/endpoint/ServerConsumerEndpoint.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/endpoint/ServerConsumerEndpoint.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/server/endpoint/ServerConsumerEndpoint.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -29,6 +29,8 @@
 import org.jboss.jms.message.JBossMessage;
 import org.jboss.jms.message.MessageProxy;
 import org.jboss.jms.selector.Selector;
+import org.jboss.jms.server.destination.TopicService;
+import org.jboss.jms.server.messagecounter.MessageCounter;
 import org.jboss.jms.server.remoting.JMSDispatcher;
 import org.jboss.jms.server.remoting.MessagingMarshallable;
 import org.jboss.jms.util.ExceptionUtil;
@@ -97,6 +99,8 @@
    
    private Queue expiryQueue;
    
+   private long redeliveryDelay;
+   
    private boolean started;
    
    //This lock protects starting and stopping
@@ -110,7 +114,7 @@
    ServerConsumerEndpoint(int id, Channel messageQueue, String queueName,
                           ServerSessionEndpoint sessionEndpoint,
                           String selector, boolean noLocal, JBossDestination dest,
-                          Queue dlq, Queue expiryQueue)
+                          Queue dlq, Queue expiryQueue, long redeliveryDelay)
                           throws InvalidSelectorException
    {
       if (trace) { log.trace("constructing consumer endpoint " + id); }
@@ -133,6 +137,8 @@
       
       this.dlq = dlq;
       
+      this.redeliveryDelay = redeliveryDelay;
+      
       this.expiryQueue = expiryQueue;
       
       //Always start as false - wait for consumer to initiate
@@ -212,7 +218,7 @@
             return delivery;
          }
                  
-         long deliveryId = sessionEndpoint.addDelivery(delivery, id);
+         long deliveryId = sessionEndpoint.addDelivery(delivery, id, dlq, expiryQueue, redeliveryDelay);
    
          // We don't send the message as-is, instead we create a MessageProxy instance. This allows
          // local fields such as deliveryCount to be handled by the proxy but global data to be
@@ -415,6 +421,11 @@
    {
       return expiryQueue;
    }
+   
+   long getRedliveryDelay()
+   {
+      return redeliveryDelay;
+   }
      
    void localClose() throws Throwable
    {      
@@ -441,6 +452,16 @@
          if (binding != null && !binding.getQueue().isRecoverable())
          {
             postOffice.unbindQueue(queueName);
+            
+            String counterName = TopicService.SUBSCRIPTION_MESSAGECOUNTER_PREFIX + queueName;
+            
+            MessageCounter counter = 
+               sessionEndpoint.getConnectionEndpoint().getServerPeer().getMessageCounterManager().unregisterMessageCounter(counterName);
+            
+            if (counter == null)
+            {
+               throw new IllegalStateException("Cannot find counter to remove " + counterName);
+            }
          }
       }
      

Modified: trunk/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -37,9 +37,10 @@
 import javax.jms.IllegalStateException;
 import javax.jms.InvalidDestinationException;
 import javax.jms.JMSException;
+import javax.jms.Message;
 
+import org.jboss.jms.client.delegate.ClientBrowserDelegate;
 import org.jboss.jms.client.delegate.ClientConsumerDelegate;
-import org.jboss.jms.client.delegate.ClientBrowserDelegate;
 import org.jboss.jms.delegate.BrowserDelegate;
 import org.jboss.jms.delegate.ConsumerDelegate;
 import org.jboss.jms.destination.JBossDestination;
@@ -54,8 +55,10 @@
 import org.jboss.jms.server.destination.ManagedDestination;
 import org.jboss.jms.server.destination.ManagedQueue;
 import org.jboss.jms.server.destination.ManagedTopic;
+import org.jboss.jms.server.destination.TopicService;
+import org.jboss.jms.server.endpoint.advised.BrowserAdvised;
 import org.jboss.jms.server.endpoint.advised.ConsumerAdvised;
-import org.jboss.jms.server.endpoint.advised.BrowserAdvised;
+import org.jboss.jms.server.messagecounter.MessageCounter;
 import org.jboss.jms.server.remoting.JMSDispatcher;
 import org.jboss.jms.util.ExceptionUtil;
 import org.jboss.jms.util.MessageQueueNameHelper;
@@ -63,6 +66,7 @@
 import org.jboss.messaging.core.Channel;
 import org.jboss.messaging.core.Delivery;
 import org.jboss.messaging.core.DeliveryObserver;
+import org.jboss.messaging.core.MessageReference;
 import org.jboss.messaging.core.Queue;
 import org.jboss.messaging.core.local.PagingFilteredQueue;
 import org.jboss.messaging.core.plugin.IDManager;
@@ -108,7 +112,15 @@
    // Constants ------------------------------------------------------------------------------------
 
    private static final Logger log = Logger.getLogger(ServerSessionEndpoint.class);
+   
+   static final String TEMP_QUEUE_MESSAGECOUNTER_PREFIX = "TempQueue.";
+   
+   public static final String JBOSS_MESSAGING_ORIG_DESTINATION = "JBM_ORIG_DESTINATION";
 
+   public static final String JBOSS_MESSAGING_ORIG_MESSAGEID = "JBM_ORIG_MESSAGEID";
+   
+   public static final String JBOSS_MESSAGING_ACTUAL_EXPIRY_TIME = "JBM_ACTUAL_EXPIRY";
+   
    // Static ---------------------------------------------------------------------------------------
 
    // Attributes -----------------------------------------------------------------------------------
@@ -318,7 +330,7 @@
       }
       catch (Throwable t)
       {
-         throw ExceptionUtil.handleJMSInvocation(t, this + " acknowledge");
+         throw ExceptionUtil.handleJMSInvocation(t, this + " acknowledgeDelivery");
       }
    }     
          
@@ -339,7 +351,7 @@
       }
       catch (Throwable t)
       {
-         throw ExceptionUtil.handleJMSInvocation(t, this + " acknowledgeBatch");
+         throw ExceptionUtil.handleJMSInvocation(t, this + " acknowledgeDeliveries");
       }
    }
              
@@ -454,6 +466,21 @@
             
             Queue queue = binding.getQueue();
             
+            JMSCondition cond = (JMSCondition)binding.getCondition();                        
+            
+            ManagedDestination dest = sp.getDestinationManager().getDestination(cond.getName(), cond.isQueue());
+            
+            if (dest == null)
+            {
+               throw new IllegalStateException("Cannot find managed destination with name " + cond.getName() + " isQueue" + cond.isQueue());
+            }
+            
+            Queue dlqToUse =
+               dest.getDLQ() == null ? defaultDLQ : dest.getDLQ();
+            
+            Queue expiryQueueToUse =
+               dest.getExpiryQueue() == null ? defaultExpiryQueue : dest.getExpiryQueue();
+            
             List dels = queue.recoverDeliveries(ids);
             
             Iterator iter2 = dels.iterator();
@@ -472,7 +499,7 @@
                
                if (trace) { log.trace(this + " Recovered delivery " + deliveryId + ", " + del); }
                
-               deliveries.put(new Long(deliveryId), new DeliveryRecord(del, -1));
+               deliveries.put(new Long(deliveryId), new DeliveryRecord(del, -1, dlqToUse, expiryQueueToUse, dest.getRedeliveryDelay()));
             }
          }
          
@@ -523,8 +550,14 @@
             
             PagingFilteredQueue q = 
                new PagingFilteredQueue(dest.getName(), idm.getID(), ms, pm, true, false,
-                                       executor, null, fullSize, pageSize, downCacheSize);                        
+                                       executor, -1, null, fullSize, pageSize, downCacheSize);     
+                        
+            String counterName = TEMP_QUEUE_MESSAGECOUNTER_PREFIX + dest.getName();
             
+            MessageCounter counter = new MessageCounter(counterName, null, q, false, false, sp.getDefaultMessageCounterHistoryDayLimit());
+            
+            sp.getMessageCounterManager().registerMessageCounter(counterName, counter);
+                                 
             //Make a binding for this queue
             postOffice.bindQueue(new JMSCondition(true, dest.getName()), q);
          }         
@@ -560,11 +593,22 @@
          {
             //Unbind
             postOffice.unbindQueue(dest.getName());
+            
+            String counterName = TEMP_QUEUE_MESSAGECOUNTER_PREFIX + dest.getName();
+            
+            connectionEndpoint.removeTemporaryDestination(dest);
+            
+            MessageCounter counter = sp.getMessageCounterManager().unregisterMessageCounter(counterName);  
+            
+            if (counter == null)
+            {
+               throw new IllegalStateException("Cannot find counter to unregister " + counterName);
+            }
          }
          else
          {
             //Topic            
-            Collection bindings = postOffice.getBindingForCondition(new JMSCondition(false, dest.getName()));
+            Collection bindings = postOffice.getBindingsForCondition(new JMSCondition(false, dest.getName()));
             
             if (!bindings.isEmpty())
             {
@@ -572,9 +616,7 @@
             }
          }
          
-         dm.unregisterDestination(mDest);         
-            
-         connectionEndpoint.removeTemporaryDestination(dest);
+         dm.unregisterDestination(mDest);                             
       }
       catch (Throwable t)
       {
@@ -621,7 +663,7 @@
          
          Queue sub = binding.getQueue();
          
-         if (sub.numberOfReceivers() != 0)
+         if (sub.getNumberOfReceivers() != 0)
          {
             throw new IllegalStateException("Cannot unsubscribe durable subscription " +
                                             subscriptionName + " since it has active subscribers");
@@ -647,6 +689,15 @@
          {         
             postOffice.unbindQueue(queueName);
          }
+         
+         String counterName = TopicService.SUBSCRIPTION_MESSAGECOUNTER_PREFIX + sub.getName();
+         
+         MessageCounter counter = sp.getMessageCounterManager().unregisterMessageCounter(counterName);
+         
+         if (counter == null)
+         {
+            throw new IllegalStateException("Cannot find counter to remove " + counterName);
+         }
       }
       catch (Throwable t)
       {
@@ -681,7 +732,9 @@
       {
          if (trace) { log.trace("Sending to expiry queue"); }
          
-         moveInTransaction(del, expiryQueue);
+         JBossMessage copy = makeCopyForDLQOrExpiry(true, del);
+         
+         moveInTransaction(copy, del, expiryQueue);
       }
       else
       {
@@ -836,11 +889,11 @@
       rec.del.cancel();
    }
    
-   long addDelivery(Delivery del, int consumerId)
+   long addDelivery(Delivery del, int consumerId, Queue dlq, Queue expiryQueue, long redeliveryDelay)
    {
       long deliveryId = deliveryIdSequence.increment();
       
-      deliveries.put(new Long(deliveryId), new DeliveryRecord(del, consumerId));
+      deliveries.put(new Long(deliveryId), new DeliveryRecord(del, consumerId, dlq, expiryQueue, redeliveryDelay));
       
       if (trace) { log.trace(this + " added delivery " + deliveryId + ": " + del); }
       
@@ -920,61 +973,98 @@
       //back to the original queue
       boolean reachedMaxDeliveryAttempts =
          cancel.isReachedMaxDeliveryAttempts() || cancel.getDeliveryCount() >= maxDeliveryAttempts;
+                    
+      Delivery del = rec.del;   
          
       if (!expired && !reachedMaxDeliveryAttempts)
       {
          //Normal cancel back to the queue
          
-         rec.del.getReference().setDeliveryCount(cancel.getDeliveryCount());
+         del.getReference().setDeliveryCount(cancel.getDeliveryCount());
          
-         rec.del.cancel();
-      }
-      else
-      {
-         ServerConsumerEndpoint consumer = null;
+         //Do we need to set a redelivery delay?
          
-         synchronized (consumers)
+         if (rec.redeliveryDelay != 0)
          {
-            consumer = (ServerConsumerEndpoint)consumers.get(new Integer(rec.consumerId));
+            del.getReference().setScheduledDeliveryTime(System.currentTimeMillis() + rec.redeliveryDelay);
          }
          
-         if (consumer == null)
-         {
-            throw new IllegalStateException("Cannot find consumer with id " + rec.consumerId);
-         }
-         
+         del.cancel();
+      }
+      else
+      {                  
          if (expired)
          {
             //Sent to expiry queue
             
-            this.moveInTransaction(rec.del, consumer.getExpiryQueue());
+            JBossMessage copy = makeCopyForDLQOrExpiry(true, del);
+            
+            moveInTransaction(copy, del, rec.expiryQueue);
          }
          else
          {
             //Send to DLQ
             
-            this.moveInTransaction(rec.del, consumer.getDLQ());
+            JBossMessage copy = makeCopyForDLQOrExpiry(false, del);
+            
+            moveInTransaction(copy, del, rec.dlq);
          }
       }      
       
       return rec.del;
    }      
    
-   private void moveInTransaction(Delivery del, Queue queue) throws Throwable
+   private JBossMessage makeCopyForDLQOrExpiry(boolean expiry, Delivery del) throws Exception
    {
+      //We copy the message and send that to the dlq/expiry queue - this is because
+      //otherwise we may end up with a ref with the same message id in the queue more than once
+      //which would barf - this might happen if the same message had been expire from multiple
+      //subscriptions of a topic for example
+      //We set headers that hold the original message destination, expiry time and original message id
+      
+      JBossMessage msg = ((JBossMessage)del.getReference().getMessage());
+      
+      JBossMessage copy = msg.doShallowCopy();
+      
+      long newMessageId = sp.getMessageIDManager().getID();
+      
+      copy.setMessageId(newMessageId);
+      
+      //reset delivery count and expiry
+      copy.setDeliveryCount(0);
+      
+      copy.setExpiration(0);
+      
+      String origMessageId = msg.getJMSMessageID();
+      
+      String origDest = msg.getJMSDestination().toString();
+            
+      copy.setStringProperty(JBOSS_MESSAGING_ORIG_MESSAGEID, origMessageId);
+      
+      copy.setStringProperty(JBOSS_MESSAGING_ORIG_DESTINATION, origDest);
+      
+      if (expiry)
+      {
+         long actualExpiryTime = System.currentTimeMillis();
+         
+         copy.setLongProperty(JBOSS_MESSAGING_ACTUAL_EXPIRY_TIME, actualExpiryTime);
+      }
+      
+      return copy;
+   }
+   
+   private void moveInTransaction(JBossMessage msg, Delivery del, Queue queue) throws Throwable
+   {
       Transaction tx = tr.createTransaction();
       
+      MessageReference ref = ms.reference(msg);
+                       
       try
       {               
          if (queue != null)
-         {                               
-            //Need to reset expiration and delivery account
-            del.getReference().setExpiration(0);
-            del.getReference().getMessage().setExpiration(0);
-            del.getReference().setDeliveryCount(0);
+         {                                                       
+            queue.handle(null, ref, tx);
             
-            queue.handle(null, del.getReference(), tx);
-            
             del.acknowledge(tx);           
          }
          else
@@ -984,12 +1074,7 @@
             del.acknowledge(tx);
          }             
          
-         tx.commit();
-         
-         if (queue != null)
-         {
-            queue.deliver(false);
-         }
+         tx.commit();         
       }
       catch (Throwable t)
       {
@@ -997,6 +1082,19 @@
          
          throw t;
       } 
+      finally
+      {
+         if (ref != null)
+         {
+            ref.releaseMemoryReference();
+         }
+      }
+      
+      //Need to prompt delivery on the dlq/expiry queue
+      if (queue != null)
+      {
+         queue.deliver(false);
+      }
    }
    
    private void acknowledgeDeliveryInternal(Ack ack) throws Throwable
@@ -1048,7 +1146,7 @@
       {
          // locate the binding based on destination name and the failed node ID
          Collection c = postOffice.
-            getBindingForCondition(new JMSCondition(true, jmsDestination.getName()));
+            getBindingsForCondition(new JMSCondition(true, jmsDestination.getName()));
 
          for(Iterator i = c.iterator(); i.hasNext(); )
          {
@@ -1087,11 +1185,20 @@
       
       Queue expiryQueueToUse =
          dest.getExpiryQueue() == null ? defaultExpiryQueue : dest.getExpiryQueue();
+      
+      long redeliveryDelay = dest.getRedeliveryDelay();
+      
+      if (redeliveryDelay == 0)
+      {
+         redeliveryDelay = sp.getDefaultRedeliveryDelay();
+      }
             
       ServerConsumerEndpoint ep =
-         new ServerConsumerEndpoint(consumerID, newQueue, newQueue.getName(), this, selectorString,
-                                    noLocal, jmsDestination, dlqToUse, expiryQueueToUse);
-      
+
+         new ServerConsumerEndpoint(consumerID, binding.getQueue(),
+                                    binding.getQueue().getName(), this, selectorString, noLocal,
+                                    jmsDestination, dlqToUse, expiryQueueToUse, redeliveryDelay);
+
       JMSDispatcher.instance.registerTarget(new Integer(consumerID), new ConsumerAdvised(ep));
 
       ClientConsumerDelegate stub =
@@ -1121,10 +1228,13 @@
          selectorString = null;
       }
       
-      log.debug(this + " creating consumer for " + jmsDestination +
-         (selectorString == null ? "" : ", selector '" + selectorString + "'") +
-         (subscriptionName == null ? "" : ", subscription '" + subscriptionName + "'") +
-         (noLocal ? ", noLocal" : ""));
+      if (trace)
+      {
+         log.trace(this + " creating consumer for " + jmsDestination +
+            (selectorString == null ? "" : ", selector '" + selectorString + "'") +
+            (subscriptionName == null ? "" : ", subscription '" + subscriptionName + "'") +
+            (noLocal ? ", noLocal" : ""));
+      }
 
       ManagedDestination mDest = dm.
          getDestination(jmsDestination.getName(), jmsDestination.isQueue());
@@ -1141,7 +1251,7 @@
          if (!connectionEndpoint.hasTemporaryDestination(jmsDestination))
          {
             String msg = "Cannot create a message consumer on a different connection " +
-            "to that which created the temporary destination";
+                         "to that which created the temporary destination";
             throw new IllegalStateException(msg);
          }
       }
@@ -1174,7 +1284,7 @@
             if (postOffice.isLocal())
             {
                q = new PagingFilteredQueue(new GUID().toString(), idm.getID(), ms, pm, true, false,
-                        executor, selector,
+                        executor, mDest.getMaxSize(), selector,
                         mDest.getFullSize(),
                         mDest.getPageSize(),
                         mDest.getDownCacheSize());
@@ -1184,7 +1294,7 @@
             else
             {
                q = new LocalClusteredQueue(postOffice, nodeId, new GUID().toString(), idm.getID(), ms, pm, true, false,
-                        executor, selector, tr,
+                        executor, mDest.getMaxSize(), selector, tr,
                         mDest.getFullSize(),
                         mDest.getPageSize(),
                         mDest.getDownCacheSize());
@@ -1200,6 +1310,20 @@
                   binding = cpo.bindQueue(topicCond, q);
                }
             }
+            String counterName = TopicService.SUBSCRIPTION_MESSAGECOUNTER_PREFIX + q.getName();
+  
+            int dayLimitToUse = mDest.getMessageCounterHistoryDayLimit();
+            if (dayLimitToUse == -1)
+            {
+               //Use override on server peer
+               dayLimitToUse = sp.getDefaultMessageCounterHistoryDayLimit();
+            }
+            
+            MessageCounter counter =
+               new MessageCounter(counterName, null, q, true, false,
+                                  dayLimitToUse);
+            
+            sp.getMessageCounterManager().registerMessageCounter(counterName, counter);
          }
          else
          {
@@ -1233,7 +1357,7 @@
                if (postOffice.isLocal())
                {
                   q = new PagingFilteredQueue(name, idm.getID(), ms, pm, true, true,
-                                              executor, selector,
+                                              executor, mDest.getMaxSize(), selector,
                                               mDest.getFullSize(),
                                               mDest.getPageSize(),
                                               mDest.getDownCacheSize());
@@ -1244,7 +1368,7 @@
                {
                   q = new LocalClusteredQueue(postOffice, nodeId, name, idm.getID(),
                                               ms, pm, true, true,
-                                              executor, selector, tr,
+                                              executor, mDest.getMaxSize(), selector, tr,
                                               mDest.getFullSize(),
                                               mDest.getPageSize(),
                                               mDest.getDownCacheSize());
@@ -1260,6 +1384,13 @@
                      binding = cpo.bindQueue(topicCond, q);
                   }
                }
+               String counterName = TopicService.SUBSCRIPTION_MESSAGECOUNTER_PREFIX + q.getName();
+                       
+               MessageCounter counter =
+                  new MessageCounter(counterName, subscriptionName, q, true, true,
+                                     mDest.getMessageCounterHistoryDayLimit());
+               
+               sp.getMessageCounterManager().registerMessageCounter(counterName, counter);
             }
             else
             {
@@ -1316,7 +1447,7 @@
                   if (postOffice.isLocal())
                   {
                      q = new PagingFilteredQueue(name, idm.getID(), ms, pm, true, true,
-                              executor, selector,
+                              executor, mDest.getMaxSize(), selector,
                               mDest.getFullSize(),
                               mDest.getPageSize(),
                               mDest.getDownCacheSize());
@@ -1325,7 +1456,7 @@
                   else
                   {
                      q = new LocalClusteredQueue(postOffice, nodeId, name, idm.getID(), ms, pm, true, true,
-                              executor, selector, tr,
+                              executor, mDest.getMaxSize(), selector, tr,
                               mDest.getFullSize(),
                               mDest.getPageSize(),
                               mDest.getDownCacheSize());
@@ -1341,6 +1472,13 @@
                         binding = cpo.bindQueue(topicCond, (LocalClusteredQueue)q);
                      }
                   }
+                  String counterName = TopicService.SUBSCRIPTION_MESSAGECOUNTER_PREFIX + q.getName();
+                  
+                  MessageCounter counter =
+                     new MessageCounter(counterName, subscriptionName, q, true, true,
+                                        mDest.getMessageCounterHistoryDayLimit());
+                  
+                  sp.getMessageCounterManager().registerMessageCounter(counterName, counter);
                }
             }
          }
@@ -1364,10 +1502,17 @@
       
       Queue expiryQueueToUse = mDest.getExpiryQueue() == null ? defaultExpiryQueue : mDest.getExpiryQueue();
       
+      long redeliveryDelay = mDest.getRedeliveryDelay();
+      
+      if (redeliveryDelay == 0)
+      {
+         redeliveryDelay = sp.getDefaultRedeliveryDelay();
+      }
+      
       ServerConsumerEndpoint ep =
          new ServerConsumerEndpoint(consumerID, (PagingFilteredQueue)binding.getQueue(),
                   binding.getQueue().getName(), this, selectorString, noLocal,
-                  jmsDestination, dlqToUse, expiryQueueToUse);
+                  jmsDestination, dlqToUse, expiryQueueToUse, redeliveryDelay);
       
       JMSDispatcher.instance.registerTarget(new Integer(consumerID), new ConsumerAdvised(ep));
       
@@ -1383,7 +1528,7 @@
       log.debug(this + " created and registered " + ep);
       
       return stub;
-   }
+   }   
 
    private BrowserDelegate createFailoverBrowserDelegateInternal(JBossDestination jmsDestination,
                                                                  String selector,
@@ -1407,7 +1552,7 @@
       {
          // locate the binding based on destination name and the failed node ID
          Collection c = postOffice.
-            getBindingForCondition(new JMSCondition(true, jmsDestination.getName()));
+            getBindingsForCondition(new JMSCondition(true, jmsDestination.getName()));
 
          for(Iterator i = c.iterator(); i.hasNext(); )
          {
@@ -1510,13 +1655,14 @@
    /*
     * Holds a record of a delivery - we need to store the consumer id as well
     * hence this class
-    * The only reason we need to store the consumer id is that on consumer close, we need to 
-    * cancel any deliveries corresponding to that consumer.
     * We can't rely on the cancel being driven from the MessageCallbackHandler since
     * the deliveries may have got lost in transit (ignored) since the consumer might have closed
     * when they were in transit.
     * In such a case we might otherwise end up with the consumer closing but not all it's deliveries being
     * cancelled, which would mean they wouldn't be cancelled until the session is closed which is too late
+    * 
+    * We need to store various pieces of information, such as consumer id, dlq, expiry queue
+    * since we need this at cancel time, but by then the actual consumer might have closed
     */
    private static class DeliveryRecord
    {
@@ -1524,11 +1670,23 @@
       
       int consumerId;
       
-      DeliveryRecord(Delivery del, int consumerId)
+      Queue dlq;
+      
+      Queue expiryQueue;
+      
+      long redeliveryDelay;
+      
+      DeliveryRecord(Delivery del, int consumerId, Queue dlq, Queue expiryQueue, long redeliveryDelay)
       {
          this.del = del;
          
          this.consumerId = consumerId;
+         
+         this.dlq = dlq;
+         
+         this.expiryQueue = expiryQueue;
+         
+         this.redeliveryDelay = redeliveryDelay;
       }            
    }
    

Added: trunk/src/main/org/jboss/jms/server/messagecounter/MessageCounter.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/messagecounter/MessageCounter.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/server/messagecounter/MessageCounter.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -0,0 +1,669 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.jms.server.messagecounter;
+
+import java.text.DateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Iterator;
+import java.util.List;
+
+import org.jboss.logging.Logger;
+import org.jboss.messaging.core.Queue;
+
+/**
+ * This class stores message count informations for a given queue
+ * 
+ * At intervals this class samples the queue for message count data
+ * 
+ * Note that the underlying queue *does not* update statistics every time a message
+ * is added since that would reall slow things down, instead we *sample* the queues at
+ * regular intervals - this means we are less intrusive on the queue
+ *
+ * @author <a href="mailto:u.schroeter at mobilcom.de">Ulf Schroeter</a>
+ * @author <a href="mailto:s.steinbacher at mobilcom.de">Stephan Steinbacher</a>
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version $Revision: 1.8 $
+ */
+public class MessageCounter
+{
+   protected static final Logger log = Logger.getLogger(MessageCounter.class);
+
+   // destination related information
+   private String destName;
+   private String destSubscription;
+   private boolean destTopic;
+   private boolean destDurable;
+
+   // destination queue
+   private Queue destQueue;
+
+   // counter
+   private int countTotal;
+   private int countTotalLast;
+   private int depthLast;
+   private long timeLastUpdate;
+
+   // per hour day counter history
+   private int dayCounterMax;
+   private ArrayList dayCounter;
+   
+   /**
+    * Get a list of message statistics from a list of message counters
+    * 
+    * @param counter the message counters
+    * @return the message statistics
+    * @throws Exception for any error
+    */
+   public static List getMessageStatistics(List counters) throws Exception
+   {
+      List list = new ArrayList(counters.size());
+      
+      Iterator iter = counters.iterator();
+      
+      while (iter.hasNext())
+      {
+         MessageCounter counter = (MessageCounter)iter.next();
+         
+         MessageStatistics stats = new MessageStatistics();
+         stats.setName(counter.getDestinationName());
+         stats.setSubscriptionID(counter.getDestinationSubscription());
+         stats.setTopic(counter.getDestinationTopic());
+         stats.setDurable(counter.getDestinationDurable());
+         stats.setCount(counter.getCount());
+         stats.setCountDelta(counter.getCountDelta());
+         stats.setDepth(counter.getMessageCount());
+         stats.setDepthDelta(counter.getMessageCountDelta());
+         stats.setTimeLastUpdate(counter.getLastUpdate());
+         
+         list.add(stats);
+      }
+      return list;
+   }
+
+   /**
+    *    Constructor
+    *
+    * @param name             destination name
+    * @param subscription     subscription name
+    * @param queue            internal queue object
+    * @param topic            topic destination flag
+    * @param durable          durable subsciption flag
+    * @param daycountmax      max message history day count
+    */
+   public MessageCounter(String name,
+                         String subscription,
+                         Queue queue,
+                         boolean topic,
+                         boolean durable,
+                         int daycountmax)
+   {
+      // store destination related information
+      destName = name;
+      destSubscription = subscription;
+      destTopic = topic;
+      destDurable = durable;
+      destQueue = queue;      
+
+      // initialize counter
+      resetCounter();
+
+      // initialize message history
+      dayCounter = new ArrayList();
+
+      setHistoryLimit(daycountmax);
+   }
+
+   /**
+   * Get string representation
+   */
+   public String toString()
+   {
+      return getCounterAsString();
+   }
+
+   private int lastMessagesAdded;
+   
+   /*
+    * This method is called periodically to update statistics from the queue
+    */
+   public synchronized void onTimer()
+   {
+      int latestMessagesAdded = destQueue.getMessagesAdded();
+      
+      int newMessagesAdded = latestMessagesAdded - lastMessagesAdded;
+      
+      countTotal += newMessagesAdded;
+      
+      lastMessagesAdded = latestMessagesAdded;
+      
+      //update timestamp
+      timeLastUpdate = System.currentTimeMillis();
+      
+      // update message history
+      updateHistory(true);
+   }
+
+   /**
+    * Gets the related destination name
+    *
+    * @return String    destination name
+    */
+   public String getDestinationName()
+   {
+      return destName;
+   }
+
+   /**
+    * Gets the related destination subscription
+    *
+    * @return String    destination name
+    */
+   public String getDestinationSubscription()
+   {
+      return destSubscription;
+   }
+
+   /**
+    * Gets the related destination topic flag
+    *
+    * @return boolean    true: topic destination, false: queue destination
+    */
+   public boolean getDestinationTopic()
+   {
+      return destTopic;
+   }
+
+   /**
+    * Gets the related destination durable subscription flag
+    *
+    * @return boolean   true : durable subscription,
+    *                   false: non-durable subscription
+    */
+   public boolean getDestinationDurable()
+   {
+      return destDurable;
+   }
+
+   /**
+    * Gets the total message count since startup or
+    * last counter reset
+    *
+    * @return int    message count
+    */
+   public int getCount()
+   {
+      return countTotal;
+   }
+
+   /**
+    * Gets the message count delta since last method call
+    *
+    * @return int    message count delta
+    */
+   public int getCountDelta()
+   {
+      int delta = countTotal - countTotalLast;
+
+      countTotalLast = countTotal;
+
+      return delta;
+   }
+
+   /**
+    * Gets the current message count of pending messages
+    * within the destination waiting for dispatch
+    *
+    * @return int message queue depth
+    */
+   public int getMessageCount()
+   {
+      return destQueue.getMessageCount();
+   }
+
+   /**
+    * Gets the message count delta of pending messages
+    * since last method call. Therefore
+    *
+    * @return int message queue depth delta
+    */
+   public int getMessageCountDelta()
+   {
+      int current = destQueue.getMessageCount();
+      int delta = current - depthLast;
+
+      depthLast = current;
+
+      return delta;
+   }
+
+   /**
+    * Gets the timestamp of the last message add
+    *
+    * @return long      system time
+    */
+   public long getLastUpdate()
+   {
+      return timeLastUpdate;
+   }
+
+   /**
+    * Reset message counter values
+    */
+   public void resetCounter()
+   {
+      countTotal = 0;
+      countTotalLast = 0;
+      depthLast = 0;
+      timeLastUpdate = 0;
+   }
+
+   /**
+    * Get message counter data as string in format
+    *
+    *  "Topic/Queue, Name, Subscription, Durable, Count, CountDelta,
+    *  Depth, DepthDelta, Timestamp Last Increment"  
+    *
+    * @return  String   message counter data string
+    */
+   public String getCounterAsString()
+   {
+      StringBuffer ret = new StringBuffer();
+
+      // Topic/Queue
+      if (destTopic)
+         ret.append("Topic,");
+      else
+         ret.append("Queue,");
+
+      // name 
+      ret.append(destName).append(",");
+
+      // subscription
+      if (destSubscription != null)
+         ret.append(destSubscription).append(",");
+      else
+         ret.append("-,");
+
+      // Durable subscription
+      if (destTopic)
+      {
+         // Topic
+         if (destDurable)
+            ret.append("true,");
+         else
+            ret.append("false,");
+      }
+      else
+      {
+         // Queue
+         ret.append("-,");
+      }
+
+      // counter values
+      ret.append(getCount()).append(",").append(getCountDelta()).append(",").append(getMessageCount()).append(",").append(getMessageCountDelta()).append(",");
+
+      // timestamp last counter update
+      if (timeLastUpdate > 0)
+      {
+         DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM);
+
+         ret.append(dateFormat.format(new Date(timeLastUpdate)));
+      }
+      else
+      {
+         ret.append("-");
+      }
+
+      return ret.toString();
+   }
+
+   /**
+    * Get message counter history day count limit
+    *
+    * <0: unlimited, 0: history disabled, >0: day count
+    */
+   public int getHistoryLimit()
+   {
+      return dayCounterMax;
+   }
+
+   /**
+    * Set message counter history day count limit
+    *
+    * <0: unlimited, 0: history disabled, >0: day count
+    */
+   public void setHistoryLimit(int daycountmax)
+   {
+      boolean bInitialize = false;
+
+      // store new maximum day count
+      dayCounterMax = daycountmax;
+
+      // update day counter array
+      synchronized (dayCounter)
+      {
+         if (dayCounterMax > 0)
+         {
+            // limit day history to specified day count
+            int delta = dayCounter.size() - dayCounterMax;
+
+            for (int i = 0; i < delta; i++)
+            {
+               // reduce array size to requested size by dropping
+               // oldest day counters
+               dayCounter.remove(0);
+            }
+
+            // create initial day counter when empty
+            bInitialize = dayCounter.isEmpty();
+         }
+         else if (dayCounterMax == 0)
+         {
+            // disable history
+            dayCounter.clear();
+         }
+         else
+         {
+            // unlimited day history
+
+            // create initial day counter when empty
+            bInitialize = dayCounter.isEmpty();
+         }
+
+         // optionally initialize first day counter entry
+         if (bInitialize)
+         {
+            dayCounter.add(new DayCounter(new GregorianCalendar(), true));
+         }
+      }
+   }
+
+   /**
+    * Update message counter history
+    */
+   private void updateHistory(boolean incrementCounter)
+   {
+      // check history activation
+      if (dayCounter.isEmpty())
+      {
+         return;
+      }
+
+      // calculate day difference between current date and date of last day counter entry
+      synchronized (dayCounter)
+      {
+         DayCounter counterLast = (DayCounter) dayCounter.get(dayCounter.size() - 1);
+
+         GregorianCalendar calNow = new GregorianCalendar();
+         GregorianCalendar calLast = counterLast.getDate();
+
+         // clip day time part for day delta calulation
+         calNow.clear(Calendar.AM_PM);
+         calNow.clear(Calendar.HOUR);
+         calNow.clear(Calendar.HOUR_OF_DAY);
+         calNow.clear(Calendar.MINUTE);
+         calNow.clear(Calendar.SECOND);
+         calNow.clear(Calendar.MILLISECOND);
+
+         calLast.clear(Calendar.AM_PM);
+         calLast.clear(Calendar.HOUR);
+         calLast.clear(Calendar.HOUR_OF_DAY);
+         calLast.clear(Calendar.MINUTE);
+         calLast.clear(Calendar.SECOND);
+         calLast.clear(Calendar.MILLISECOND);
+
+         long millisPerDay = 86400000; // 24 * 60 * 60 * 1000
+         long millisDelta = calNow.getTime().getTime() - calLast.getTime().getTime();
+
+         int dayDelta = (int) (millisDelta / millisPerDay);
+
+         if (dayDelta > 0)
+         {
+            // finalize last day counter
+            counterLast.finalizeDayCounter();
+
+            // add new intermediate empty day counter entries
+            DayCounter counterNew;
+
+            for (int i = 1; i < dayDelta; i++)
+            {
+               // increment date
+               calLast.add(Calendar.DAY_OF_YEAR, 1);
+
+               counterNew = new DayCounter(calLast, false);
+               counterNew.finalizeDayCounter();
+
+               dayCounter.add(counterNew);
+            }
+
+            // add new day counter entry for current day
+            counterNew = new DayCounter(calNow, false);
+
+            dayCounter.add(counterNew);
+
+            // ensure history day count limit
+            setHistoryLimit(dayCounterMax);
+         }
+
+         // update last day counter entry
+         counterLast = (DayCounter) dayCounter.get(dayCounter.size() - 1);
+         counterLast.updateDayCounter(incrementCounter);
+      }
+   }
+
+   /**
+    * Reset message counter history
+    */
+   public void resetHistory()
+   {
+      int max = dayCounterMax;
+
+      setHistoryLimit(0);
+      setHistoryLimit(max);
+   }
+
+   /**
+    * Get message counter history data as string in format
+    * 
+    * "day count\n  
+    *  Date 1, hour counter 0, hour counter 1, ..., hour counter 23\n
+    *  Date 2, hour counter 0, hour counter 1, ..., hour counter 23\n
+    *  .....
+    *  .....
+    *  Date n, hour counter 0, hour counter 1, ..., hour counter 23\n"
+    *
+    * @return  String   message history data string
+    */
+   public String getHistoryAsString()
+   {
+      String ret = "";
+
+      // ensure history counters are up to date
+      updateHistory(false);
+
+      // compile string       
+      synchronized (dayCounter)
+      {
+         // first line: history day count  
+         ret += dayCounter.size() + "\n";
+
+         // following lines: day counter data
+         for (int i = 0; i < dayCounter.size(); i++)
+         {
+            DayCounter counter = (DayCounter) dayCounter.get(i);
+
+            ret += counter.getDayCounterAsString() + "\n";
+         }
+      }
+
+      return ret;
+   }
+
+   /**
+    * Internal day counter class for one day hour based counter history
+    */
+   private static class DayCounter
+   {
+      static final int HOURS = 24;
+
+      GregorianCalendar date = null;
+      int[] counters = new int[HOURS];
+
+      /**
+       *    Constructor
+       *
+       * @param date          day counter date
+       * @param isStartDay    true  first day counter
+       *                      false follow up day counter
+       */
+      DayCounter(GregorianCalendar date, boolean isStartDay)
+      {
+         // store internal copy of creation date
+         this.date = (GregorianCalendar) date.clone();
+
+         // initialize the array with '0'- values to current hour (if it is not the
+         // first monitored day) and the rest with default values ('-1')
+         int hour = date.get(Calendar.HOUR_OF_DAY);
+
+         for (int i = 0; i < HOURS; i++)
+         {
+            if (i < hour)
+            {
+               if (isStartDay)
+                  counters[i] = -1;
+               else
+                  counters[i] = 0;
+            }
+            else
+            {
+               counters[i] = -1;
+            }
+         }
+
+         // set the array element of the current hour to '0'
+         counters[hour] = 0;
+      }
+
+      /**
+       * Gets copy of day counter date
+       *
+       * @return GregorianCalendar        day counter date
+       */
+      GregorianCalendar getDate()
+      {
+         return (GregorianCalendar) date.clone();
+      }
+
+      /**
+       * Update day counter hour array elements  
+       *
+       * @param incrementCounter      update current hour counter
+       */
+      void updateDayCounter(boolean incrementCounter)
+      {
+         // get the current hour of the day
+         GregorianCalendar cal = new GregorianCalendar();
+
+         int currentIndex = cal.get(Calendar.HOUR_OF_DAY);
+
+         // check if the last array update is more than 1 hour ago, if so fill all
+         // array elements between the last index and the current index with '0' values
+         boolean bUpdate = false;
+
+         for (int i = 0; i <= currentIndex; i++)
+         {
+            if (counters[i] > -1)
+            {
+               // found first initialized hour counter
+               // -> set all following uninitialized
+               //    counter values to 0
+               bUpdate = true;
+            }
+
+            if (bUpdate == true)
+            {
+               if (counters[i] == -1)
+                  counters[i] = 0;
+            }
+         }
+
+         // optionally increment current counter
+         if (incrementCounter)
+         {
+            counters[currentIndex]++;
+         }
+      }
+
+      /**
+       * Finalize day counter hour array elements  
+       */
+      void finalizeDayCounter()
+      {
+         // a new day has began, so fill all array elements from index to end with
+         // '0' values
+         boolean bFinalize = false;
+
+         for (int i = 0; i < HOURS; i++)
+         {
+            if (counters[i] > -1)
+            {
+               // found first initialized hour counter
+               // -> finalize all following uninitialized
+               //    counter values
+               bFinalize = true;
+            }
+
+            if (bFinalize)
+            {
+               if (counters[i] == -1)
+                  counters[i] = 0;
+            }
+         }
+      }
+
+      /**
+       * Return day counter data as string with format
+       * "Date, hour counter 0, hour counter 1, ..., hour counter 23"
+       * 
+       * @return  String   day counter data
+       */
+      String getDayCounterAsString()
+      {
+         // first element day counter date
+         DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT);
+
+         String strData = dateFormat.format(date.getTime());
+
+         // append 24 comma separated hour counter values           
+         for (int i = 0; i < HOURS; i++)
+         {
+            strData += "," + counters[i];
+         }
+
+         return strData;
+      }
+   }
+}
+

Added: trunk/src/main/org/jboss/jms/server/messagecounter/MessageCounterManager.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/messagecounter/MessageCounterManager.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/server/messagecounter/MessageCounterManager.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -0,0 +1,196 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.jms.server.messagecounter;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.jboss.logging.Logger;
+import org.jboss.messaging.core.plugin.contract.MessagingComponent;
+
+/**
+ * 
+ * A MessageCounterManager
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class MessageCounterManager implements MessagingComponent
+{
+   private static final Logger log = Logger.getLogger(MessageCounterManager.class);
+   
+   private Map messageCounters;
+   
+   private boolean started;
+   
+   private Timer timer;
+   
+   private long period;
+   
+   private PingMessageCountersTask task;
+          
+   public MessageCounterManager(long period)
+   {
+      messageCounters = new HashMap();
+      
+      this.period = period;
+   }
+
+   public synchronized void start()
+   {
+      if (started)
+      {
+         log.warn(this + " already started");
+         
+         return;
+      }
+      
+      // Needs to be daemon
+      timer = new Timer(true);
+      
+      task = new PingMessageCountersTask();
+            
+      timer.schedule(task, 0, period);      
+      
+      started = true;      
+   }
+
+   public synchronized void stop()
+   {
+      if (!started)
+      {
+         log.warn(this + " isn't started");
+      }
+      
+      //Wait for timer task to stop
+      
+      task.stop();
+      
+      timer.cancel();
+      
+      timer = null;
+      
+      started = false;
+   }
+   
+   public synchronized void reschedule(long newPeriod)
+   {
+      stop();
+      
+      period = newPeriod;
+      
+      start();
+   }
+   
+   public void registerMessageCounter(String name, MessageCounter counter)
+   {
+      synchronized (messageCounters)
+      {
+         messageCounters.put(name, counter);
+      }
+   }
+   
+   public MessageCounter unregisterMessageCounter(String name)
+   {
+      synchronized (messageCounters)
+      {
+         return (MessageCounter)messageCounters.remove(name);
+      }
+   }
+   
+   public Collection getMessageCounters()
+   {
+      synchronized (messageCounters)
+      {
+         return Collections.unmodifiableCollection(messageCounters.values());
+      }
+   }
+   
+   public MessageCounter getMessageCounter(String name)
+   {
+      synchronized (messageCounters)
+      {
+         return (MessageCounter)messageCounters.get(name);
+      }
+   }
+   
+   public void resetAllCounters()
+   {
+      synchronized (messageCounters)
+      {
+         Iterator iter = messageCounters.values().iterator();
+         
+         while (iter.hasNext())
+         {
+            MessageCounter counter = (MessageCounter)iter.next();
+            
+            counter.resetCounter();
+         }
+      }
+   }
+   
+   public void resetAllCounterHistories()
+   {
+      synchronized (messageCounters)
+      {
+         Iterator iter = messageCounters.values().iterator();
+         
+         while (iter.hasNext())
+         {
+            MessageCounter counter = (MessageCounter)iter.next();
+            
+            counter.resetHistory();
+         }
+      }
+   }
+   
+   class PingMessageCountersTask extends TimerTask
+   {
+      public void run()
+      {
+         synchronized (messageCounters)
+         {
+            Iterator iter = messageCounters.values().iterator();
+            
+            while (iter.hasNext())
+            {
+               MessageCounter counter = (MessageCounter)iter.next();
+               
+               counter.onTimer();
+            }
+         }
+      }  
+                        
+      synchronized void stop()
+      {
+         cancel();
+      }
+   }
+}

Added: trunk/src/main/org/jboss/jms/server/messagecounter/MessageStatistics.java
===================================================================
--- trunk/src/main/org/jboss/jms/server/messagecounter/MessageStatistics.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/jms/server/messagecounter/MessageStatistics.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -0,0 +1,338 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.jms.server.messagecounter;
+
+import java.io.Serializable;
+import java.text.DateFormat;
+import java.util.Date;
+
+/**
+ * Message statistics
+ * 
+ * @author <a href="mailto:adrian at jboss.org">Adrian Brock</a>
+ * @version <tt>$Revision: 1.3 $</tt>
+ */
+public class MessageStatistics implements Serializable
+{
+   // Constants -----------------------------------------------------
+
+   /** The serialVersionUID */
+   static final long serialVersionUID = 8056884098781414022L;
+
+   // Attributes ----------------------------------------------------
+
+   /** Whether we are topic */
+   private boolean topic;
+
+   /** Whether we are durable */
+   private boolean durable;
+
+   /** The name */
+   private String name;
+
+   /** The subscription id */
+   private String subscriptionID;
+
+   /** The message count */
+   private int count;
+
+   /** The message count delta */
+   private int countDelta;
+
+   /** The message depth */
+   private int depth;
+
+   /** The message depth delta */
+   private int depthDelta;
+
+   /** The last update */
+   private long timeLastUpdate;
+
+   // Static --------------------------------------------------------
+
+   // Constructors --------------------------------------------------
+
+   /**
+    * Construct a new Message Statistics
+    */
+   public MessageStatistics()
+   {
+   }
+
+   // Public --------------------------------------------------------
+
+   /**
+    * Get the count.
+    * 
+    * @return Returns the count.
+    */
+   public int getCount()
+   {
+      return count;
+   }
+
+   /**
+    * Set the count.
+    * 
+    * @param count The count to set.
+    */
+   public void setCount(int count)
+   {
+      this.count = count;
+   }
+
+   /**
+    * Get the countDelta.
+    * 
+    * @return Returns the countDelta.
+    */
+   public int getCountDelta()
+   {
+      return countDelta;
+   }
+
+   /**
+    * Set the countDelta.
+    * 
+    * @param countDelta The countDelta to set.
+    */
+   public void setCountDelta(int countDelta)
+   {
+      this.countDelta = countDelta;
+   }
+
+   /**
+    * Get the depth.
+    * 
+    * @return Returns the depth.
+    */
+   public int getDepth()
+   {
+      return depth;
+   }
+
+   /**
+    * Set the depth.
+    * 
+    * @param depth The depth to set.
+    */
+   public void setDepth(int depth)
+   {
+      this.depth = depth;
+   }
+
+   /**
+    * Get the depthDelta.
+    * 
+    * @return Returns the depthDelta.
+    */
+   public int getDepthDelta()
+   {
+      return depthDelta;
+   }
+
+   /**
+    * Set the depthDelta.
+    * 
+    * @param depthDelta The depthDelta to set.
+    */
+   public void setDepthDelta(int depthDelta)
+   {
+      this.depthDelta = depthDelta;
+   }
+
+   /**
+    * Get the durable.
+    * 
+    * @return Returns the durable.
+    */
+   public boolean isDurable()
+   {
+      return durable;
+   }
+
+   /**
+    * Set the durable.
+    * 
+    * @param durable The durable to set.
+    */
+   public void setDurable(boolean durable)
+   {
+      this.durable = durable;
+   }
+
+   /**
+    * Get the name.
+    * 
+    * @return Returns the name.
+    */
+   public String getName()
+   {
+      return name;
+   }
+
+   /**
+    * Set the name.
+    * 
+    * @param name The name to set.
+    */
+   public void setName(String name)
+   {
+      this.name = name;
+   }
+
+   /**
+    * Get the subscriptionID.
+    * 
+    * @return Returns the subscriptionID.
+    */
+   public String getSubscriptionID()
+   {
+      return subscriptionID;
+   }
+
+   /**
+    * Set the subscriptionID.
+    * 
+    * @param subscriptionID The subscriptionID to set.
+    */
+   public void setSubscriptionID(String subscriptionID)
+   {
+      this.subscriptionID = subscriptionID;
+   }
+
+   /**
+    * Get the timeLastUpdate.
+    * 
+    * @return Returns the timeLastUpdate.
+    */
+   public long getTimeLastUpdate()
+   {
+      return timeLastUpdate;
+   }
+
+   /**
+    * Set the timeLastUpdate.
+    * 
+    * @param timeLastUpdate The timeLastUpdate to set.
+    */
+   public void setTimeLastUpdate(long timeLastUpdate)
+   {
+      this.timeLastUpdate = timeLastUpdate;
+   }
+
+   /**
+    * Get the topic.
+    * 
+    * @return Returns the topic.
+    */
+   public boolean isTopic()
+   {
+      return topic;
+   }
+
+   /**
+    * Set the topic.
+    * 
+    * @param topic The topic to set.
+    */
+   public void setTopic(boolean topic)
+   {
+      this.topic = topic;
+   }
+
+   /**
+    * Get message data as string in format
+    *
+    *  "Topic/Queue, Name, Subscription, Durable, Count, CountDelta,
+    *  Depth, DepthDelta, Timestamp Last Increment"  
+    *
+    * @return  String data as a string
+    */
+   public String getAsString()
+   {
+      StringBuffer buffer = new StringBuffer(50);
+
+      // Topic/Queue
+      if (topic)
+         buffer.append("Topic,");
+      else
+         buffer.append("Queue,");
+
+      // name 
+      buffer.append(name).append(',');
+
+      // subscription
+      if (subscriptionID != null)
+         buffer.append(subscriptionID).append(',');
+      else
+         buffer.append("-,");
+
+      // Durable subscription
+      if (topic)
+      {
+         // Topic
+         if (durable)
+            buffer.append("DURABLE,");
+         else
+            buffer.append("NONDURABLE,");
+      }
+      else
+      {
+         buffer.append("-,");
+      }
+
+      // counter values
+      buffer.append(count).append(',').append(countDelta).append(',').append(depth).append(',').append(depthDelta)
+            .append(',');
+
+      // timestamp last counter update
+      if (timeLastUpdate > 0)
+      {
+         DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM);
+
+         buffer.append(dateFormat.format(new Date(timeLastUpdate)));
+      }
+      else
+      {
+         buffer.append('-');
+      }
+
+      return buffer.toString();
+   }
+
+   // Object overrides ----------------------------------------------
+
+   public String toString()
+   {
+      return getAsString();
+   }
+
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+
+}
\ No newline at end of file

Modified: trunk/src/main/org/jboss/messaging/core/Channel.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/Channel.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/messaging/core/Channel.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -109,14 +109,24 @@
    void clear();
    
    /**
-    * Message amount. 
-    * @return message amount.
+    * 
+    * @return Total message count = undelivered + delivering + scheduled
     */
    int getMessageCount();
    
+   /**
+    * 
+    * @return Count being delivered
+    */
    int getDeliveringCount();
    
    /**
+    * Count scheduled for delivery
+    * @return
+    */
+   int getScheduledCount();
+   
+   /**
     * Remove all the references in the channel
     * @throws Throwable
     */
@@ -134,6 +144,12 @@
    
    List recoverDeliveries(List messageIds);
   
+   int getMaxSize();
+   
+   void setMaxSize(int newSize);
+   
+   //Count of messages added since server was started (needed for stats)
+   int getMessagesAdded();
 }
 
 

Modified: trunk/src/main/org/jboss/messaging/core/ChannelSupport.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/ChannelSupport.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/messaging/core/ChannelSupport.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -22,10 +22,13 @@
 package org.jboss.messaging.core;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
+import java.util.Set;
 
+import org.jboss.jms.server.MyTimeoutFactory;
 import org.jboss.logging.Logger;
 import org.jboss.messaging.core.plugin.contract.MessageStore;
 import org.jboss.messaging.core.plugin.contract.PersistenceManager;
@@ -35,6 +38,8 @@
 import org.jboss.messaging.core.tx.TransactionException;
 import org.jboss.messaging.core.tx.TxCallback;
 import org.jboss.messaging.util.Future;
+import org.jboss.util.timeout.Timeout;
+import org.jboss.util.timeout.TimeoutTarget;
 
 import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
 import EDU.oswego.cs.dl.util.concurrent.SynchronizedInt;
@@ -94,15 +99,23 @@
    //refs being delivered is because many tests require this
    //Having to keep this count requires synchronization between delivery thread and acknowledgement
    //thread which will hamper concurrency
-   //Suggest that we have a glag that disables this for production systems
+   //Suggest that we have a flag that disables this for production systems
    protected SynchronizedInt deliveringCount;
+    
+   protected Set scheduledDeliveries;
    
+   //The maximum number of refs this queue can hold, or -1 if no limit
+   //If any more refs are added after this point they are dropped
+   protected int maxSize;
+  
+   protected SynchronizedInt messagesAdded;
+    
    // Constructors ---------------------------------------------------------------------------------
 
    protected ChannelSupport(long channelID, MessageStore ms,
                             PersistenceManager pm,
                             boolean acceptReliableMessages, boolean recoverable,
-                            QueuedExecutor executor)
+                            QueuedExecutor executor, int maxSize)
    {
       if (trace) { log.trace("creating " + (pm != null ? "recoverable " : "non-recoverable ") + "channel[" + channelID + "]"); }
 
@@ -133,6 +146,12 @@
       refLock = new Object();
       
       deliveringCount = new SynchronizedInt(0);
+      
+      scheduledDeliveries = new HashSet();
+      
+      this.maxSize = maxSize;
+      
+      this.messagesAdded = new SynchronizedInt(0);
    }
 
    // Receiver implementation ----------------------------------------------------------------------
@@ -180,13 +199,26 @@
       acknowledgeInternal(d, tx, true, false);
    }
 
-
-   public void cancel(Delivery d) throws Throwable
+   public void cancel(Delivery del) throws Throwable
    {
-      // We put the cancellation on the event queue
-      this.executor.execute(new CancelRunnable(d));      
-   }
-
+      //We may need to update the delivery count in the database
+      
+      MessageReference ref = del.getReference();
+      
+      if (ref.isReliable())
+      {
+         pm.updateDeliveryCount(this.channelID, ref);
+      }
+      
+      deliveringCount.decrement();
+      
+      if (!checkAndSchedule(ref))
+      {
+         // We put the cancellation on the event queue if it's not a scheduled delivery
+         this.executor.execute(new CancelRunnable(ref));     
+      }
+   }      
+        
    // Distributor implementation -------------------------------------------------------------------
 
    public boolean add(Receiver r)
@@ -231,9 +263,9 @@
       return router.iterator();
    }
 
-   public int numberOfReceivers()
+   public int getNumberOfReceivers()
    {
-      return router.numberOfReceivers();
+      return router.getNumberOfReceivers();
    }
 
    // Channel implementation -----------------------------------------------------------------------
@@ -313,15 +345,18 @@
       {
          log.warn("Thread interrupted", e);
       }
-   }
+   }      
 
    public void close()
    {
       if (router != null)
       {
          router.clear();
+         
          router = null;
       }
+      
+      clearAllScheduledDeliveries();
    }
 
    /*
@@ -358,6 +393,8 @@
          
          deliveringCount.set(0);
       }
+      
+      clearAllScheduledDeliveries();
    }
 
    public List undelivered(Filter filter)
@@ -391,13 +428,13 @@
    }
 
    /**
-    * Returns the count of messages stored AND being delivered.
+    * Returns the count of messages stored AND being delivered AND scheduled
     */
    public int getMessageCount()
    {
       synchronized (refLock)
       {
-         return messageRefs.size() + getDeliveringCount();
+         return messageRefs.size() + getDeliveringCount() + getScheduledCount();
       }
    }
    
@@ -405,6 +442,14 @@
    {
       return deliveringCount.get();
    }
+   
+   public int getScheduledCount()
+   {
+      synchronized (scheduledDeliveries)
+      {
+         return scheduledDeliveries.size();
+      }
+   }
 
    public void activate()
    {
@@ -473,6 +518,36 @@
             
       return dels;
    }
+   
+   public int getMaxSize()
+   {
+      synchronized (refLock)
+      {
+         return maxSize;
+      }
+   }
+   
+   public void setMaxSize(int newSize)
+   {
+      synchronized (refLock)
+      {
+         int count = getMessageCount();
+         
+         if (newSize != -1 && count > newSize)
+         {
+            log.warn("Cannot set maxSize to " + newSize + " since there are already " + count + " refs");
+         }
+         else
+         {
+            maxSize = newSize;
+         }
+      }
+   }
+   
+   public int getMessagesAdded()
+   {
+      return messagesAdded.get();
+   }
 
    // Public ---------------------------------------------------------------------------------------
 
@@ -493,9 +568,40 @@
    }
 
    // Package protected ----------------------------------------------------------------------------
-
+   
    // Protected ------------------------------------------------------------------------------------
    
+   protected void clearAllScheduledDeliveries()
+   {
+      synchronized (scheduledDeliveries)
+      {
+         Set clone = new HashSet(scheduledDeliveries);
+         
+         Iterator iter = clone.iterator();
+         
+         while (iter.hasNext())
+         {
+            Timeout timeout = (Timeout)iter.next();
+            
+            timeout.cancel();
+         }
+         
+         scheduledDeliveries.clear();
+      }
+   }
+
+   protected void cancelInternal(MessageReference ref) throws Exception
+   {
+      if (trace) { log.trace(this + " cancelling " + ref + " in memory"); }
+
+      synchronized (refLock)
+      {
+         messageRefs.addFirst(ref, ref.getPriority());
+      }
+                  
+      if (trace) { log.trace(this + " added " + ref + " back into state"); }
+   }
+   
    /*
     * This methods delivers as many messages as possible to the router until no
     * more deliveries are returned. This method should never be called at the
@@ -503,7 +609,7 @@
     *
     * @see org.jboss.messaging.core.Channel#deliver()
     */
-   protected void deliverInternal() throws Throwable
+   protected void deliverInternal()
    {
       try
       {
@@ -572,7 +678,50 @@
          log.error(this + " Failed to deliver", t);
       }
    }
-
+   
+   protected boolean deliverScheduled(MessageReference ref)
+   {
+      try
+      {      
+         // We synchonize on the ref lock to prevent scheduled deivery kicking in before
+         // load has finished
+         synchronized (refLock)
+         {
+            // Attempt to push the ref to a receiver
+            
+            if (trace) { log.trace(this + " pushing " + ref); }                                  
+   
+            Delivery del = router.handle(this, ref, null);
+   
+            receiversReady = del != null;
+            
+            if (del == null)
+            {
+               // No receiver, broken receiver or full receiver so we stop delivering
+               if (trace) { log.trace(this + ": no delivery returned for message" + ref + " so no receiver got the message. Delivery is now complete"); }
+   
+               return false;
+            }
+            else if (del.isSelectorAccepted())
+            {
+               if (trace) { log.trace(this + ": " + del + " returned for message:" + ref); }
+               
+               // Receiver accepted the reference
+               
+               deliveringCount.increment();                   
+               
+               return true;
+            }                
+         }
+      }
+      catch (Throwable t)
+      {
+         log.error(this + " Failed to deliver", t);
+      }
+      
+      return false;
+   }
+      
    protected Delivery handleInternal(DeliveryObserver sender, MessageReference ref,
                                      Transaction tx, boolean persist, boolean synchronous)
    {
@@ -582,6 +731,15 @@
       }
 
       if (trace) { log.trace(this + " handles " + ref + (tx == null ? " non-transactionally" : " in transaction: " + tx)); }
+      
+      if (maxSize != -1 && getMessageCount() >= maxSize)
+      {
+         //Have reached maximum size - will drop message
+         
+         log.warn("Queue " + this + " has reached maximum size, ref " + ref + " will be dropped");
+         
+         return null;
+      }
    
       //Each channel has its own copy of the reference
       ref = ref.copy();
@@ -618,20 +776,27 @@
                // Reliable message in a recoverable state - also add to db
                if (trace) { log.trace(this + " adding " + ref + " to database non-transactionally"); }
 
+               //TODO - this db access could safely be done outside the event loop
                pm.addReference(channelID, ref, null);        
             }
             
-            synchronized (refLock)
-            {
-               addReferenceInMemory(ref);
-            }
+            //If the ref has a scheduled delivery time then we don't add to the in memory queue
+            //instead we create a timeout, so when that time comes delivery will attempted directly
             
-            // We only do delivery if there are receivers that haven't said they don't want
-            // any more references.
-            if (receiversReady)
-            {
-               // Prompt delivery
-               deliverInternal();
+            if (!checkAndSchedule(ref))
+            {               
+               synchronized (refLock)
+               {
+                  addReferenceInMemory(ref);
+               }
+               
+               // We only do delivery if there are receivers that haven't said they don't want
+               // any more references.
+               if (receiversReady)
+               {
+                  // Prompt delivery
+                  deliverInternal();
+               }
             }
          }
          else
@@ -664,6 +829,8 @@
                pm.addReference(channelID, ref, tx);
             }
          }
+         
+         messagesAdded.increment();
       }
       catch (Throwable t)
       {
@@ -679,6 +846,33 @@
       return new SimpleDelivery(this, ref, true);
    }
 
+   
+   protected boolean checkAndSchedule(MessageReference ref)
+   {
+      if (ref.getScheduledDeliveryTime() > System.currentTimeMillis())
+      {      
+         if (trace) { log.trace("Scheduling delivery for " + ref + " to occur at " + ref.getScheduledDeliveryTime()); }
+         
+         //Schedule the cancel to actually occur at the specified time
+         
+         //Need to synchronize to prevent timeout being removed before it is added
+         synchronized (scheduledDeliveries)
+         {            
+            Timeout timeout =
+               MyTimeoutFactory.instance.getFactory().schedule(ref.getScheduledDeliveryTime(),
+                        new DeliverRefTimeoutTarget(ref));
+            
+            scheduledDeliveries.add(timeout);
+         }      
+         
+         return true;
+      }
+      else
+      {
+         return false;
+      }
+   }
+   
    protected void acknowledgeInternal(Delivery d, Transaction tx, boolean persist,
                                       boolean synchronous) throws Exception
    {   
@@ -727,30 +921,7 @@
 
       return callback;
    }
-
-      
-   protected void cancelInternal(Delivery del) throws Exception
-   {
-      if (trace) { log.trace(this + " cancelling " + del + " in memory"); }
-
-      MessageReference ref = del.getReference();
-      
-      synchronized (refLock)
-      {
-         messageRefs.addFirst(ref, ref.getPriority());
-      }
-      
-      //We may need to update the delivery count in the database
-      if (ref.isReliable())
-      {
-         pm.updateDeliveryCount(this.channelID, ref);
-      }
-      
-      deliveringCount.decrement();
-      
-      if (trace) { log.trace(this + " added " + ref + " back into state"); }
-   }
-   
+ 
    protected MessageReference removeFirstInMemory() throws Exception
    {
       MessageReference result = (MessageReference) messageRefs.removeFirst();
@@ -1067,7 +1238,7 @@
   
    // Inner classes --------------------------------------------------------------------------------
 
-   protected class DeliveryRunnable implements Runnable
+   private class DeliveryRunnable implements Runnable
    {
       Future result;
       
@@ -1080,7 +1251,7 @@
       {
          try
          {
-            if (router.numberOfReceivers() > 0)
+            if (router.getNumberOfReceivers() > 0)
             {               
                deliverInternal();                     
             }
@@ -1100,20 +1271,55 @@
       }
    } 
    
+   private class DeliverScheduledRunnable implements Runnable
+   {
+      private MessageReference ref;
+      
+      private Future result;
+      
+      public DeliverScheduledRunnable(Future result, MessageReference ref)
+      {
+         this.ref = ref;
+         
+         this.result = result;
+      }
+      
+      public void run()
+      {
+         try         
+         {
+            if (router.getNumberOfReceivers() > 0)
+            {               
+               boolean delivered = deliverScheduled(ref);     
+               
+               result.setResult(Boolean.valueOf(delivered));
+            }
+            else
+            {
+               result.setResult(Boolean.valueOf(false));
+            }
+         }
+         catch (Throwable t)
+         {
+            log.error("Failed to deliver scheduled", t);            
+         }
+      }
+   } 
+   
    private class CancelRunnable implements Runnable
    {
-      Delivery del;
+      MessageReference ref;
       
-      CancelRunnable(Delivery del)
+      CancelRunnable(MessageReference ref)
       {
-         this.del = del;
+         this.ref = ref;
       }
       
       public void run()
       {
          try
          {
-            cancelInternal(del);
+            cancelInternal(ref);
          }
          catch (Exception e)
          {
@@ -1121,7 +1327,7 @@
          }
       }
    }
-
+   
    protected class HandleRunnable implements Runnable
    {
       Future result;
@@ -1146,4 +1352,64 @@
          result.setResult(d);
       }
    }   
+   
+   private class DeliverRefTimeoutTarget implements TimeoutTarget
+   {
+      private MessageReference ref;
+
+      public DeliverRefTimeoutTarget(MessageReference ref)
+      {
+         this.ref = ref;
+      }
+
+      public void timedOut(Timeout timeout)
+      {
+         if (trace) { log.trace("Scheduled delivery timeout " + ref); }
+         
+         synchronized (scheduledDeliveries)
+         {
+            boolean removed = scheduledDeliveries.remove(timeout);
+            
+            if (!removed)
+            {
+               throw new IllegalStateException("Failed to remove timeout " + timeout);
+            }
+         }
+              
+         ref.setScheduledDeliveryTime(0);
+           
+         Future result = new Future();
+         
+         DeliverScheduledRunnable runnable = new DeliverScheduledRunnable(result, ref);
+         
+         try
+         {
+            executor.execute(runnable);
+         }
+         catch (InterruptedException e)
+         {
+            log.error("Thread interrupted", e);
+         }
+         
+         Boolean b = (Boolean)result.getResult();
+         boolean delivered = b.booleanValue();
+         
+         if (!delivered)
+         {
+            //add to front of queue
+            try
+            {
+               executor.execute(new CancelRunnable(ref));
+            }
+            catch (InterruptedException e)
+            {
+               log.error("Thread interrupted", e);
+            }
+         }
+         else
+         {
+            if (trace) { log.trace("Delivered scheduled delivery at " + System.currentTimeMillis() + " for " + ref); }
+         }
+      }
+   }
 }

Modified: trunk/src/main/org/jboss/messaging/core/Distributor.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/Distributor.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/messaging/core/Distributor.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -67,6 +67,6 @@
     * 
     * @return The number of receivers in the distributor
     */
-   int numberOfReceivers();
+   int getNumberOfReceivers();
 
 }

Modified: trunk/src/main/org/jboss/messaging/core/PagingChannelSupport.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/PagingChannelSupport.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/messaging/core/PagingChannelSupport.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -102,9 +102,9 @@
     */
    public PagingChannelSupport(long channelID, MessageStore ms, PersistenceManager pm,
                                boolean acceptReliableMessages, boolean recoverable,                        
-                               QueuedExecutor executor)
+                               QueuedExecutor executor, int maxSize)
    {
-      super(channelID, ms, pm, acceptReliableMessages, recoverable, executor);
+      super(channelID, ms, pm, acceptReliableMessages, recoverable, executor, maxSize);
       
       downCache = new ArrayList(downCacheSize);    
       
@@ -125,10 +125,10 @@
     */
    public PagingChannelSupport(long channelID, MessageStore ms, PersistenceManager pm,
                                boolean acceptReliableMessages, boolean recoverable,                        
-                               QueuedExecutor executor,
+                               QueuedExecutor executor, int maxSize,
                                int fullSize, int pageSize, int downCacheSize)
    {
-      super(channelID, ms, pm, acceptReliableMessages, recoverable, executor);
+      super(channelID, ms, pm, acceptReliableMessages, recoverable, executor, maxSize);
       
       if (pageSize >= fullSize)
       {
@@ -274,7 +274,9 @@
          
          paging = false;
          
-         firstPagingOrder = nextPagingOrder = 0;         
+         firstPagingOrder = nextPagingOrder = 0;  
+         
+         clearAllScheduledDeliveries();
       }
    }
    
@@ -355,13 +357,11 @@
       }    
    }
       
-   protected void cancelInternal(Delivery del) throws Exception
+   protected void cancelInternal(MessageReference ref) throws Exception
    {
-      if (trace) { log.trace(this + " cancelling " + del + " in memory"); }
-
       synchronized (refLock)
       {         
-         super.cancelInternal(del);
+         super.cancelInternal(ref);
          
          if (paging)
          {
@@ -369,13 +369,13 @@
             // preserve the number of refs in the queue
             if (messageRefs.size() == fullSize + 1)
             {
-               MessageReference ref = (MessageReference)messageRefs.removeLast();
+               MessageReference refCancel = (MessageReference)messageRefs.removeLast();
     
-               addToDownCache(ref, true);
+               addToDownCache(refCancel, true);
             }
          }
                
-         if (trace) { log.trace(this + " added " + del.getReference() + " back into state"); }      
+         if (trace) { log.trace(this + " added " + ref + " back into state"); }      
       }
    }
       
@@ -547,6 +547,8 @@
 
       ref.setPagingOrder(-1);
       
+      ref.setScheduledDeliveryTime(info.getScheduledDelivery());
+      
       //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
       
@@ -554,9 +556,13 @@
       //Reliability is an attribute of the message reference, not the message
       
       ref.setReliable(info.isReliable());
+            
+      //Schedule the delivery if necessary, or just add to the in memory queue
+      if (!checkAndSchedule(ref))
+      {
+         messageRefs.addLast(ref, ref.getPriority());
+      }
       
-      messageRefs.addLast(ref, ref.getPriority());
-      
       return ref;
    }
    

Modified: trunk/src/main/org/jboss/messaging/core/Routable.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/Routable.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/messaging/core/Routable.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -76,6 +76,17 @@
    boolean isExpired();
    
    void setExpiration(long expiration);
+   
+   
+   /**
+    * 
+    * @return The time in the future that delivery will be delayed until, or zero if
+    * no scheduled delivery will occur
+    */
+   long getScheduledDeliveryTime();
+   
+   void setScheduledDeliveryTime(long scheduledDeliveryTime);
+   
 
    /**
     * @return the time (in GMT milliseconds) when this routable was delivered to the provider.

Modified: trunk/src/main/org/jboss/messaging/core/local/FirstReceiverPointToPointRouter.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/local/FirstReceiverPointToPointRouter.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/messaging/core/local/FirstReceiverPointToPointRouter.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -176,7 +176,7 @@
       }
    }
    
-   public int numberOfReceivers()
+   public int getNumberOfReceivers()
    {
       synchronized(receivers)
       {

Modified: trunk/src/main/org/jboss/messaging/core/local/PagingFilteredQueue.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/local/PagingFilteredQueue.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/messaging/core/local/PagingFilteredQueue.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -21,13 +21,20 @@
   */
 package org.jboss.messaging.core.local;
 
-import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
 import org.jboss.logging.Logger;
-import org.jboss.messaging.core.*;
+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.SimpleDelivery;
 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
@@ -66,10 +73,11 @@
    // Constructors --------------------------------------------------
 
    public PagingFilteredQueue(String name, long id, MessageStore ms, PersistenceManager pm,             
-                             boolean acceptReliableMessages, boolean recoverable, QueuedExecutor executor,
-                             Filter filter)
+                              boolean acceptReliableMessages, boolean recoverable,
+                              QueuedExecutor executor, int maxSize,
+                              Filter filter)
    {
-      super(id, ms, pm, acceptReliableMessages, recoverable, executor);
+      super(id, ms, pm, acceptReliableMessages, recoverable, executor, maxSize);
       
       router = new RoundRobinPointToPointRouter();
       
@@ -79,11 +87,12 @@
    }
    
    public PagingFilteredQueue(String name, long id, MessageStore ms, PersistenceManager pm,             
-                              boolean acceptReliableMessages, boolean recoverable, QueuedExecutor executor,
+                              boolean acceptReliableMessages, boolean recoverable,
+                              QueuedExecutor executor, int maxSize,
                               Filter filter,
                               int fullSize, int pageSize, int downCacheSize)
    {
-      super(id, ms, pm, acceptReliableMessages, recoverable, executor, fullSize, pageSize, downCacheSize);
+      super(id, ms, pm, acceptReliableMessages, recoverable, executor, maxSize, fullSize, pageSize, downCacheSize);
       
       router = new RoundRobinPointToPointRouter();
       

Modified: trunk/src/main/org/jboss/messaging/core/local/RoundRobinPointToPointRouter.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/local/RoundRobinPointToPointRouter.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/messaging/core/local/RoundRobinPointToPointRouter.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -202,7 +202,7 @@
       }
    }
    
-   public int numberOfReceivers()
+   public int getNumberOfReceivers()
    {
       synchronized(receivers)
       {

Modified: trunk/src/main/org/jboss/messaging/core/message/CoreMessage.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/message/CoreMessage.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/messaging/core/message/CoreMessage.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -55,7 +55,7 @@
                       Map headers,
                       byte[] payload)
    {
-      super(messageID, reliable, expiration, timestamp, priority, 0, headers, payload);
+      super(messageID, reliable, expiration, timestamp, priority, 0, 0, headers, payload);
    }
 
    // Public --------------------------------------------------------

Modified: trunk/src/main/org/jboss/messaging/core/message/MessageFactory.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/message/MessageFactory.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/messaging/core/message/MessageFactory.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -97,7 +97,8 @@
                                        String correlationID,
                                        byte[] correlationIDBytes,
                                        JBossDestination destination,
-                                       JBossDestination replyTo,                                                                              
+                                       JBossDestination replyTo, 
+                                       long scheduledDeliveryTime,
                                        HashMap jmsProperties)
 
    {

Modified: trunk/src/main/org/jboss/messaging/core/message/MessageSupport.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/message/MessageSupport.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/messaging/core/message/MessageSupport.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -110,11 +110,12 @@
                          long expiration,
                          long timestamp,
                          byte priority,
-                         int deliveryCount,                        
+                         int deliveryCount,  
+                         long scheduledDeliveryTime,
                          Map headers,
-                         byte[] payloadAsByteArray)
+                         byte[] payloadAsByteArray)                         
    {
-      super(messageID, reliable, expiration, timestamp, priority, deliveryCount, headers);
+      super(messageID, reliable, expiration, timestamp, priority, deliveryCount, scheduledDeliveryTime, headers);
       this.payloadAsByteArray = payloadAsByteArray;
    }
 
@@ -339,6 +340,7 @@
       payload = payloadAsByteArray;
    }
 
+
    // Private -------------------------------------------------------
 
    // Inner classes -------------------------------------------------

Modified: trunk/src/main/org/jboss/messaging/core/message/RoutableSupport.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/message/RoutableSupport.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/messaging/core/message/RoutableSupport.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -59,6 +59,7 @@
    protected Map headers;
    protected byte priority;
    protected int deliveryCount;   
+   protected long scheduledDeliveryTime;
 
    // Constructors --------------------------------------------------
 
@@ -93,6 +94,7 @@
            System.currentTimeMillis(),
            (byte)4,        
            0,
+           0,
            null);
    }
 
@@ -101,7 +103,8 @@
                           long expiration, 
                           long timestamp,
                           byte priority,
-                          int deliveryCount,                          
+                          int deliveryCount, 
+                          long scheduledDeliveryTime,
                           Map headers)
    {
       this.messageID = messageID;
@@ -110,6 +113,7 @@
       this.timestamp = timestamp;
       this.priority = priority;
       this.deliveryCount = deliveryCount;
+      this.scheduledDeliveryTime = scheduledDeliveryTime;
       if (headers == null)
       {
          this.headers = new HashMap();
@@ -129,6 +133,7 @@
       this.headers = new HashMap(other.headers);
       this.deliveryCount = other.deliveryCount;
       this.priority = other.priority;  
+      this.scheduledDeliveryTime = other.scheduledDeliveryTime;
    }
 
    // Routable implementation ---------------------------------------
@@ -223,6 +228,16 @@
       this.priority = priority;
    }
    
+   public long getScheduledDeliveryTime()
+   {
+      return scheduledDeliveryTime;
+   }
+
+   public void setScheduledDeliveryTime(long scheduledDeliveryTime)
+   {
+      this.scheduledDeliveryTime = scheduledDeliveryTime;
+   }
+   
    // Streamable implementation ---------------------------------
    
    public void write(DataOutputStream out) throws Exception
@@ -232,9 +247,9 @@
       out.writeLong(expiration);
       out.writeLong(timestamp);
       StreamUtils.writeMap(out, headers, true);
-    //  out.writeBoolean(redelivered);
       out.writeByte(priority);
       out.writeInt(deliveryCount);
+      out.writeLong(scheduledDeliveryTime);
    }
 
    public void read(DataInputStream in) throws Exception
@@ -252,9 +267,9 @@
       {
          headers = (HashMap)m;
       }
-     // redelivered = in.readBoolean();
       priority = in.readByte();
       deliveryCount = in.readInt();
+      scheduledDeliveryTime = in.readLong();
    }
    
    // Public --------------------------------------------------------

Modified: trunk/src/main/org/jboss/messaging/core/plugin/JDBCPersistenceManager.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/JDBCPersistenceManager.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/messaging/core/plugin/JDBCPersistenceManager.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -367,9 +367,6 @@
       }     
    }
          
-   // Related to paging functionality
-   // ===============================         
-        
    /*
     * Retrieve a List of messages corresponding to the specified List of message ids.
     * The implementation here for HSQLDB does this by using a PreparedStatment with an IN clause
@@ -446,11 +443,18 @@
                
                while (rs.next())
                {
+                  
+//                  "SELECT MESSAGEID, RELIABLE, EXPIRATION, TIMESTAMP, " +
+//                  "PRIORITY, COREHEADERS, PAYLOAD, CHANNELCOUNT, TYPE, JMSTYPE, CORRELATIONID, " +
+//                  "CORRELATIONID_BYTES, DESTINATION, REPLYTO, JMSPROPERTIES " +
+//                  "FROM JMS_MESSAGE"
+                  
+                  
                   long messageId = rs.getLong(1);
                   boolean reliable = rs.getString(2).equals("Y");
                   long expiration = rs.getLong(3);
                   long timestamp = rs.getLong(4);
-                  byte priority = rs.getByte(5);
+                  byte priority = rs.getByte(5);                  
                   byte[] bytes = getBytes(rs, 6);
                   HashMap coreHeaders = bytesToMap(bytes);
                   byte[] payload = getBytes(rs, 7);
@@ -461,20 +465,20 @@
                   //JBossMessages - we should subclass JBDCPersistenceManager and the JBossMessage
                   //specific code in a subclass
                   
-                  byte type = rs.getByte(9);
+                  byte type = rs.getByte(8);
                   
                   Message m;
                   
                   if (type != CoreMessage.TYPE)
                   {
                      //JBossMessage
-                     String jmsType = rs.getString(10);
-                     String correlationID = rs.getString(11);
-                     byte[] correlationIDBytes = rs.getBytes(12);
-                     String destination = rs.getString(13);
-                     String replyTo = rs.getString(14);
+                     String jmsType = rs.getString(9);
+                     String correlationID = rs.getString(10);
+                     byte[] correlationIDBytes = rs.getBytes(11);
+                     String destination = rs.getString(12);
+                     String replyTo = rs.getString(13);
                      boolean replyToExists = !rs.wasNull();
-                     bytes = getBytes(rs, 15);
+                     bytes = getBytes(rs, 14);
                      HashMap jmsProperties = bytesToMap(bytes);
                      
                      JBossDestination dest;
@@ -504,14 +508,14 @@
                      m = MessageFactory.createMessage(messageId, reliable, expiration, timestamp, priority,
                                                       coreHeaders, payload,
                                                       type, jmsType, correlationID, correlationIDBytes,
-                                                      dest, replyToDest,
+                                                      dest, replyToDest, 0,
                                                       jmsProperties);
                   }
                   else
                   {
                      m = MessageFactory.createMessage(messageId, reliable, expiration, timestamp, priority,
                                                           coreHeaders, payload, type,
-                                                          null, null, null, null, null, null);
+                                                          null, null, null, null, null, 0, null);
                   }
                   
                   
@@ -572,6 +576,9 @@
    }  
    
        
+   // Related to paging functionality
+   // ===============================                 
+   
    public void pageReferences(long channelID, List references, boolean paged) throws Exception
    {  
       Connection conn = null;
@@ -1211,6 +1218,7 @@
             int deliveryCount = rs.getInt(2);
             int pageOrd = rs.getInt(3);
             boolean reliable = rs.getString(4).equals("Y");
+            long sched = rs.getLong(5);
             
             //Sanity check
             if (pageOrd != ord)
@@ -1218,7 +1226,7 @@
                throw new IllegalStateException("Unexpected pageOrd: " + pageOrd + " expected: " + ord);
             }
             
-            ReferenceInfo ri = new ReferenceInfo(msgId, deliveryCount, reliable);
+            ReferenceInfo ri = new ReferenceInfo(msgId, deliveryCount, reliable, sched);
             
             refs.add(ri);
             ord++;
@@ -1333,8 +1341,9 @@
             long msgId = rs.getLong(1);            
             int deliveryCount = rs.getInt(2);
             boolean reliable = rs.getString(3).equals("Y");
+            long sched = rs.getLong(4);
             
-            ReferenceInfo ri = new ReferenceInfo(msgId, deliveryCount, reliable);
+            ReferenceInfo ri = new ReferenceInfo(msgId, deliveryCount, reliable, sched);
             
             if (count < fullSize)
             {
@@ -2808,6 +2817,7 @@
       }
       ps.setInt(7, ref.getDeliveryCount());
       ps.setString(8, ref.isReliable() ? "Y" : "N");
+      ps.setLong(9, ref.getScheduledDeliveryTime());
    }
    
    protected void removeReference(long channelID, MessageReference ref, PreparedStatement ps)
@@ -2832,6 +2842,7 @@
       ps.setNull(6, Types.BIGINT);      
       ps.setInt(7, ref.getDeliveryCount());
       ps.setString(8, ref.isReliable() ? "Y" : "N");
+      ps.setLong(9, ref.getScheduledDeliveryTime());
    }
    
    protected void prepareToRemoveReference(long channelID, MessageReference ref, Transaction tx, PreparedStatement ps)
@@ -2997,9 +3008,7 @@
    {
       ps.setLong(1, m.getMessageID());
    }
-   
-   
-   
+         
    protected void decrementChannelCount(Message m, PreparedStatement ps) throws Exception
    {
       ps.setLong(1, m.getMessageID());
@@ -3018,6 +3027,7 @@
       ps.setLong(4, m.getTimestamp());
       ps.setByte(5, m.getPriority());
       
+      //Core headers
       byte[] bytes = mapToBytes(((MessageSupport) m).getHeaders());
       if (bytes != null)
       {
@@ -3093,6 +3103,7 @@
             ps.setString(14, (replyTo.isQueue() ? "Q" : "T") + replyTo);
          }
          
+         //jms properties
          bytes = mapToBytes(jbm.getJMSProperties());
          if (bytes != null)
          {
@@ -3255,12 +3266,13 @@
       map.put("CREATE_MESSAGE_REFERENCE",
               "CREATE TABLE JMS_MESSAGE_REFERENCE (CHANNELID BIGINT, " +
               "MESSAGEID BIGINT, TRANSACTIONID BIGINT, STATE CHAR(1), ORD BIGINT, PAGE_ORD BIGINT, " +
-              "DELIVERYCOUNT INTEGER, RELIABLE CHAR(1), LOADED CHAR(1), PRIMARY KEY(CHANNELID, MESSAGEID))");
+              "DELIVERYCOUNT INTEGER, RELIABLE CHAR(1), LOADED CHAR(1), SCHED_DELIVERY BIGINT, PRIMARY KEY(CHANNELID, MESSAGEID))"); //CHANGED
       map.put("CREATE_IDX_MESSAGE_REF_TX", "CREATE INDEX JMS_MESSAGE_REF_TX ON JMS_MESSAGE_REFERENCE (TRANSACTIONID)");
       map.put("CREATE_IDX_MESSAGE_REF_ORD", "CREATE INDEX JMS_MESSAGE_REF_ORD ON JMS_MESSAGE_REFERENCE (ORD)");
       map.put("CREATE_IDX_MESSAGE_REF_PAGE_ORD", "CREATE INDEX JMS_MESSAGE_REF__PAGE_ORD ON JMS_MESSAGE_REFERENCE (PAGE_ORD)");
       map.put("CREATE_IDX_MESSAGE_REF_MESSAGEID", "CREATE INDEX JMS_MESSAGE_REF_MESSAGEID ON JMS_MESSAGE_REFERENCE (MESSAGEID)");
       map.put("CREATE_IDX_MESSAGE_REF_RELIABLE", "CREATE INDEX JMS_MESSAGE_REF_RELIABLE ON JMS_MESSAGE_REFERENCE (RELIABLE)");
+      map.put("CREATE_IDX_MESSAGE_REF_SCHED_DELIVERY", "CREATE INDEX JMS_MESSAGE_REF_SCHED_DELIVERY ON JMS_MESSAGE_REFERENCE (SCHED_DELIVERY)");
       //Message
       map.put("CREATE_MESSAGE",
               "CREATE TABLE JMS_MESSAGE (MESSAGEID BIGINT, RELIABLE CHAR(1), " +
@@ -3285,8 +3297,8 @@
       Map map = new LinkedHashMap();
       //Message reference
       map.put("INSERT_MESSAGE_REF",
-              "INSERT INTO JMS_MESSAGE_REFERENCE (CHANNELID, MESSAGEID, TRANSACTIONID, STATE, ORD, PAGE_ORD, DELIVERYCOUNT, RELIABLE) " +
-              "VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
+              "INSERT INTO JMS_MESSAGE_REFERENCE (CHANNELID, MESSAGEID, TRANSACTIONID, STATE, ORD, PAGE_ORD, DELIVERYCOUNT, RELIABLE, SCHED_DELIVERY) " +
+              "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"); //CHANGED
       map.put("DELETE_MESSAGE_REF", "DELETE FROM JMS_MESSAGE_REFERENCE WHERE MESSAGEID=? AND CHANNELID=? AND STATE='C'");
       map.put("UPDATE_MESSAGE_REF",
               "UPDATE JMS_MESSAGE_REFERENCE SET TRANSACTIONID=?, STATE='-' " +
@@ -3297,11 +3309,11 @@
       map.put("ROLLBACK_MESSAGE_REF1", "DELETE FROM JMS_MESSAGE_REFERENCE WHERE TRANSACTIONID=? AND STATE='+'");
       map.put("ROLLBACK_MESSAGE_REF2", "UPDATE JMS_MESSAGE_REFERENCE SET STATE='C', TRANSACTIONID = NULL WHERE TRANSACTIONID=? AND STATE='-'");
       map.put("LOAD_PAGED_REFS",
-              "SELECT MESSAGEID, DELIVERYCOUNT, PAGE_ORD, RELIABLE FROM JMS_MESSAGE_REFERENCE " +
-              "WHERE CHANNELID = ? AND PAGE_ORD BETWEEN ? AND ? ORDER BY PAGE_ORD");
+              "SELECT MESSAGEID, DELIVERYCOUNT, PAGE_ORD, RELIABLE, SCHED_DELIVERY FROM JMS_MESSAGE_REFERENCE " +
+              "WHERE CHANNELID = ? AND PAGE_ORD BETWEEN ? AND ? ORDER BY PAGE_ORD"); //CHANGED
       map.put("LOAD_UNPAGED_REFS",
-              "SELECT MESSAGEID, DELIVERYCOUNT, RELIABLE FROM JMS_MESSAGE_REFERENCE WHERE STATE = 'C' " +
-              "AND CHANNELID = ? AND PAGE_ORD IS NULL ORDER BY ORD");
+              "SELECT MESSAGEID, DELIVERYCOUNT, RELIABLE, SCHED_DELIVERY FROM JMS_MESSAGE_REFERENCE WHERE STATE = 'C' " +
+              "AND CHANNELID = ? AND PAGE_ORD IS NULL ORDER BY ORD"); //CHANGED
       map.put("UPDATE_RELIABLE_REFS_NOT_PAGED", "UPDATE JMS_MESSAGE_REFERENCE SET PAGE_ORD = NULL WHERE PAGE_ORD BETWEEN ? AND ? AND CHANNELID=?");       
       map.put("SELECT_MIN_MAX_PAGE_ORD", "SELECT MIN(PAGE_ORD), MAX(PAGE_ORD) FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID = ?");
       map.put("SELECT_EXISTS_REF", "SELECT MESSAGEID FROM JMS_MESSAGE_REFERENCE WHERE CHANNELID = ? AND MESSAGEID = ?");
@@ -3309,7 +3321,7 @@
       //Message
       map.put("LOAD_MESSAGES",
               "SELECT MESSAGEID, RELIABLE, EXPIRATION, TIMESTAMP, " +
-              "PRIORITY, COREHEADERS, PAYLOAD, CHANNELCOUNT, TYPE, JMSTYPE, CORRELATIONID, " +
+              "PRIORITY, COREHEADERS, PAYLOAD, TYPE, JMSTYPE, CORRELATIONID, " +
               "CORRELATIONID_BYTES, DESTINATION, REPLYTO, JMSPROPERTIES " +
               "FROM JMS_MESSAGE");
       map.put("INSERT_MESSAGE",

Modified: trunk/src/main/org/jboss/messaging/core/plugin/SimpleMessageReference.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/SimpleMessageReference.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/messaging/core/plugin/SimpleMessageReference.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -75,7 +75,7 @@
       this(holder.getMessage().getMessageID(), holder.getMessage().isReliable(),
            holder.getMessage().getExpiration(), holder.getMessage().getTimestamp(),
            holder.getMessage().getHeaders(), holder.getMessage().getDeliveryCount(),
-           holder.getMessage().getPriority(), ms);
+           holder.getMessage().getPriority(), holder.getMessage().getScheduledDeliveryTime(), ms);
 
       this.holder = holder;
    }
@@ -89,7 +89,7 @@
    {
       this(other.getMessageID(), other.isReliable(), other.getExpiration(),
            other.getTimestamp(), other.getHeaders(), other.getDeliveryCount(),
-           other.getPriority(), other.ms);
+           other.getPriority(), other.getScheduledDeliveryTime(), other.ms);
       
       this.headers = other.headers;
       this.holder = other.holder;
@@ -97,9 +97,9 @@
    
    protected SimpleMessageReference(long messageID, boolean reliable, long expiration,
                                     long timestamp, Map headers, int deliveryCount,
-                                    byte priority, MessageStore ms)
+                                    byte priority, long scheduledDeliveryTime, MessageStore ms)
    {
-      super(messageID, reliable, expiration, timestamp, priority, 0, headers);
+      super(messageID, reliable, expiration, timestamp, priority, 0, scheduledDeliveryTime, headers);
       this.deliveryCount = deliveryCount;
       this.ms = ms;
    }

Modified: trunk/src/main/org/jboss/messaging/core/plugin/contract/PersistenceManager.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/contract/PersistenceManager.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/messaging/core/plugin/contract/PersistenceManager.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -116,13 +116,17 @@
       
       private boolean reliable;
       
-      public ReferenceInfo(long msgId, int deliveryCount, boolean reliable)
+      private long scheduledDelivery;
+      
+      public ReferenceInfo(long msgId, int deliveryCount, boolean reliable, long scheduledDelivery)
       {
          this.messageId = msgId;
          
          this.deliveryCount = deliveryCount;
          
          this.reliable = reliable;
+         
+         this.scheduledDelivery = scheduledDelivery;
       }    
       
       public long getMessageId()
@@ -139,6 +143,11 @@
       {
          return reliable;
       }
+      
+      public long getScheduledDelivery()
+      {
+         return scheduledDelivery;
+      }
    }
    class InitialLoadInfo
    {

Modified: trunk/src/main/org/jboss/messaging/core/plugin/contract/PostOffice.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/contract/PostOffice.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/messaging/core/plugin/contract/PostOffice.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -58,7 +58,7 @@
    /**
     * List the bindings that match the specified condition
     */
-   Collection getBindingForCondition(Condition condition) throws Exception;
+   Collection getBindingsForCondition(Condition condition) throws Exception;
 
    
    /**

Modified: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/DefaultPostOffice.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/DefaultPostOffice.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/DefaultPostOffice.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -257,7 +257,7 @@
       }
    }   
    
-   public Collection getBindingForCondition(Condition condition) throws Exception
+   public Collection getBindingsForCondition(Condition condition) throws Exception
    {
       return listBindingsForConditionInternal(condition, true);
    }  
@@ -469,6 +469,12 @@
       }
    }
     
+   //FIXME - this is not quite right
+   //We should not load any bindings at startup - since then we do not have to create any queues internally
+   //Creating queues is problematic since there are params we do not know until destination deploy time
+   //e.g. paging params, maxsize etc.
+   //This means we have to load the queues disabled and then set the params and re-activate them
+   //which is not clean
    protected void loadBindings() throws Exception
    {
       lock.writeLock().acquire();
@@ -567,7 +573,7 @@
       {
          QueuedExecutor executor = (QueuedExecutor)pool.get();
          queue =
-            new PagingFilteredQueue(queueName, channelID, ms, pm, true, true, executor, filter);
+            new PagingFilteredQueue(queueName, channelID, ms, pm, true, true, executor, -1, filter);
       }
       else
       {

Modified: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/DefaultClusteredPostOffice.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/DefaultClusteredPostOffice.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/DefaultClusteredPostOffice.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -1137,7 +1137,7 @@
 
                   if (trace) { log.trace(this + " successfully routed message to " + (queue.isLocal() ? "LOCAL"  : "REMOTE") + " destination '" + queue.getName() + "' on node " + queue.getNodeId()); }
 
-                  if (router.numberOfReceivers() > 1)
+                  if (router.getNumberOfReceivers() > 1)
                   {
                      // We have now chosen which one will receive the message so we need to add this
                      // information to a map which will get sent when casting - so the the queue on
@@ -1592,6 +1592,9 @@
                            filter, durable, failed, failedNodeID);
    }
 
+   //FIXME - we should not create queues here
+   //Queues should only be created at destination deployment time since it is only then
+   //we know all the params
    protected Binding createBinding(int nodeID, Condition condition, String queueName,
                                    long channelId, Filter filter, boolean durable,
                                    boolean failed, Integer failedNodeID)
@@ -1605,7 +1608,7 @@
          if (failedNodeID == null)
          {
             queue = new LocalClusteredQueue(this, nodeID, queueName, channelId, ms, pm, true,
-                                            durable, executor, filter, tr);
+                                            durable, executor, -1, filter, tr);
          }
          else
          {

Modified: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/DefaultRouter.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/DefaultRouter.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/DefaultRouter.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -225,7 +225,7 @@
       target = 0;
    }
 
-   public int numberOfReceivers()
+   public int getNumberOfReceivers()
    {
       return nonLocalQueues.size() + (localQueue != null ? 1 : 0);
    }

Modified: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/FailedOverQueue.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/FailedOverQueue.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/FailedOverQueue.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -42,7 +42,7 @@
                           int failedNodeID)
    {
       super(office, nodeID, name, id, ms, pm, acceptReliableMessages, recoverable,
-            executor, filter, tr, fullSize, pageSize, downCacheSize);
+            executor, -1, filter, tr, fullSize, pageSize, downCacheSize);
 
       this.failedNodeID = failedNodeID;
    }
@@ -53,7 +53,7 @@
                           TransactionRepository tr, int failedNodeID)
    {
       super(office, nodeID, name, id, ms, pm, acceptReliableMessages, recoverable,
-            executor, filter, tr);
+            executor, -1, filter, tr);
 
       this.failedNodeID = failedNodeID;
    }

Modified: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/LocalClusteredQueue.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/LocalClusteredQueue.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/LocalClusteredQueue.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -62,11 +62,12 @@
    public LocalClusteredQueue(PostOffice office, int nodeId, String name, long id,
                               MessageStore ms, PersistenceManager pm,
                               boolean acceptReliableMessages, boolean recoverable,
-                              QueuedExecutor executor, Filter filter, TransactionRepository tr,
+                              QueuedExecutor executor, int maxSize,
+                              Filter filter, TransactionRepository tr,
                               int fullSize, int pageSize, int downCacheSize)
    {
       super(name, id, ms, pm, acceptReliableMessages, recoverable, 
-            executor, filter, fullSize, pageSize, downCacheSize);
+            executor, maxSize, filter, fullSize, pageSize, downCacheSize);
      
       this.nodeId = nodeId;
       this.tr = tr;
@@ -76,9 +77,10 @@
    public LocalClusteredQueue(PostOffice office, int nodeId, String name, long id,
                               MessageStore ms, PersistenceManager pm,
                               boolean acceptReliableMessages, boolean recoverable,
-                              QueuedExecutor executor, Filter filter, TransactionRepository tr)
+                              QueuedExecutor executor, int maxSize,
+                              Filter filter, TransactionRepository tr)
    {
-      super(name, id, ms, pm, acceptReliableMessages, recoverable, executor, filter);
+      super(name, id, ms, pm, acceptReliableMessages, recoverable, executor, maxSize, filter);
       
       this.nodeId = nodeId;
       this.tr = tr;
@@ -217,7 +219,7 @@
       return ((Integer)result.getResult()).intValue();
    }
    
-   protected void deliverInternal() throws Throwable
+   protected void deliverInternal()
    {      
       super.deliverInternal();
         
@@ -230,7 +232,14 @@
          //We don't do this synchronously with a message dispatcher since that can lead to distributed
          //deadlock
           
-         sendPullMessage();
+         try
+         {
+            sendPullMessage();
+         }
+         catch (Exception e)
+         {
+            log.error("Failed to send pull message", e);
+         }
       }
    }
    

Modified: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/RemoteQueueStub.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/RemoteQueueStub.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/RemoteQueueStub.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -135,7 +135,7 @@
       throw new UnsupportedOperationException();
    }
 
-   public int numberOfReceivers()
+   public int getNumberOfReceivers()
    {
       throw new UnsupportedOperationException();
    }
@@ -241,7 +241,33 @@
    {
       throw new UnsupportedOperationException();
    }
+   
+   public int getDeliveringCount()
+   {
+      throw new UnsupportedOperationException();
+   }
 
+   public int getMaxSize()
+   {
+      throw new UnsupportedOperationException();
+   }
+
+   public int getMessagesAdded()
+   {
+      throw new UnsupportedOperationException();
+   }
+   
+   public void setMaxSize(int newSize)
+   {
+      throw new UnsupportedOperationException();
+   }
+   
+   public int getScheduledCount()
+   {
+      throw new UnsupportedOperationException();
+   }
+
+
    // Queue implementation ------------------------------------------
 
    public String getName()
@@ -288,11 +314,6 @@
       return "RemoteQueueStub[" + channelID + "/" + name + " -> " + nodeID + "]";
    }
 
-   public int getDeliveringCount()
-   {
-      throw new UnsupportedOperationException();
-   }
-
    // Package protected ---------------------------------------------
 
    // Protected -----------------------------------------------------

Modified: trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/StatsSender.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/StatsSender.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/messaging/core/plugin/postoffice/cluster/StatsSender.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -57,7 +57,7 @@
       this.period = period;
    }
 
-   public synchronized void start() throws Exception
+   public synchronized void start()
    {
       if (started)
       {
@@ -77,7 +77,7 @@
       started = true;
    }
 
-   public synchronized void stop() throws Exception
+   public synchronized void stop() 
    {
       if (!started)
       {
@@ -97,7 +97,7 @@
    
    class SendStatsTimerTask extends TimerTask
    {
-      public synchronized void run()
+      public void run()
       {
          try
          {

Modified: trunk/src/main/org/jboss/messaging/core/tx/TransactionRepository.java
===================================================================
--- trunk/src/main/org/jboss/messaging/core/tx/TransactionRepository.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/src/main/org/jboss/messaging/core/tx/TransactionRepository.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -197,6 +197,11 @@
          }
       }
    }
+   
+   public List getPreparedTransactions()
+   {
+      return new ArrayList(globalToLocalMap.keySet());
+   }
 
 
    public Transaction getPreparedTx(Xid xid) throws Exception

Modified: trunk/tests/src/org/jboss/test/messaging/core/SimpleChannel.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/SimpleChannel.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/SimpleChannel.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -191,7 +191,7 @@
       throw new NotYetImplementedException();
    }
 
-   public int numberOfReceivers()
+   public int getNumberOfReceivers()
    {
       throw new NotYetImplementedException();
    }
@@ -231,6 +231,26 @@
       throw new UnsupportedOperationException();
    }
 
+   public int getMaxSize()
+   {
+      throw new UnsupportedOperationException();
+   }
+
+   public int getMessagesAdded()
+   {
+      throw new UnsupportedOperationException();
+   }
+
+   public void setMaxSize(int newSize)
+   {
+      throw new UnsupportedOperationException();
+   }
+
+   public int getScheduledCount()
+   {
+      throw new UnsupportedOperationException();
+   }
+
    // Package protected ---------------------------------------------
    
    // Protected -----------------------------------------------------

Modified: trunk/tests/src/org/jboss/test/messaging/core/local/NonRecoverablePagingFilteredQueueTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/local/NonRecoverablePagingFilteredQueueTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/local/NonRecoverablePagingFilteredQueueTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -55,7 +55,7 @@
    {
       super.setUp();
       
-      queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, false, new QueuedExecutor(), null);
+      queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, false, new QueuedExecutor(), -1, null);
    }
    
    public void tearDown() throws Exception
@@ -71,7 +71,7 @@
 
    public void recoverChannel() throws Exception
    {
-      queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, false, new QueuedExecutor(), null);
+      queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, false, new QueuedExecutor(), -1, null);
    }
 
    // Public --------------------------------------------------------

Modified: trunk/tests/src/org/jboss/test/messaging/core/local/RecoverablePagingFilteredQueueTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/local/RecoverablePagingFilteredQueueTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/local/RecoverablePagingFilteredQueueTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -55,7 +55,7 @@
    {
       super.setUp();
       
-      queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null);
+      queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), -1, null);
    }
 
    public void tearDown() throws Exception
@@ -71,7 +71,7 @@
 
    public void recoverChannel() throws Exception
    {
-      queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null);
+      queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), -1, null);
    }
 
    // Public --------------------------------------------------------

Modified: trunk/tests/src/org/jboss/test/messaging/core/local/base/PagingFilteredQueueTestBase.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/local/base/PagingFilteredQueueTestBase.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/local/base/PagingFilteredQueueTestBase.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -209,7 +209,7 @@
    {
       Filter f = new SimpleFilter(3);
             
-      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, false, new QueuedExecutor(), f);
+      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, false, new QueuedExecutor(), -1, f);
       
       Message m1 = new CoreMessage(1, false, 0, 0, (byte)0, null, null);
       Message m2 = new CoreMessage(2, false, 0, 0, (byte)0, null, null);
@@ -5299,7 +5299,7 @@
       catch(IllegalStateException e)
       {
          // OK
-         log.info(e);
+         log.trace(e);
 
       }
 

Modified: trunk/tests/src/org/jboss/test/messaging/core/message/JBossMessageTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/message/JBossMessageTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/message/JBossMessageTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -58,7 +58,7 @@
    {
       rs = (MessageSupport)MessageFactory.createMessage(0, false, 0, 0, (byte)4, null,
                                                              null, JBossMessage.TYPE,
-                                                             null, null, null, null, null, null);
+                                                             null, null, null, null, null, 0, null);
       super.setUp();
       log.debug("setup done");
    }

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	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_2PCTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -65,9 +65,9 @@
    
    public void testChannelShareNP_2PC() throws Throwable
    {
-      PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), -1, null, 100, 20, 10);
       
-      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", 2, ms, pm, true, true, new QueuedExecutor(), null, 50, 10, 5);
+      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", 2, ms, pm, true, true, new QueuedExecutor(), -1, null, 50, 10, 5);
                   
       Message[] msgs = new Message[150];
       

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_NTTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_NTTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_NTTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -64,9 +64,9 @@
    
    public void test1() throws Throwable
    {
-      PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), -1, null, 100, 20, 10);
      
-      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", 2, ms, pm, true, true, new QueuedExecutor(), null, 50, 10, 5);
+      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", 2, ms, pm, true, true, new QueuedExecutor(), -1, null, 50, 10, 5);
            
       Message[] msgs = new Message[150];
       

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_TTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_TTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_NP_TTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -65,9 +65,9 @@
    
    public void testChannelShareNP_Transactional() throws Throwable
    {
-      PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), -1, null, 100, 20, 10);
       
-      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", 2, ms, pm, true, true, new QueuedExecutor(), null, 50, 10, 5);
+      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", 2, ms, pm, true, true, new QueuedExecutor(), -1, 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	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_2PCTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -60,9 +60,9 @@
    
    public void test1() throws Throwable
    {
-      PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), -1, null, 100, 20, 10);
       
-      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", 2, ms, pm, true, true, new QueuedExecutor(), null, 50, 10, 5);
+      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", 2, ms, pm, true, true, new QueuedExecutor(), -1, 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	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_NTTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -64,9 +64,9 @@
    
    public void test1() throws Throwable
    {
-      PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), -1, null, 100, 20, 10);
       
-      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", 2, ms, pm, true, true, new QueuedExecutor(), null, 50, 10, 5);
+      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", 2, ms, pm, true, true, new QueuedExecutor(), -1, 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	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/ChannelShare_P_TTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -64,9 +64,9 @@
    
    public void test1() throws Throwable
    {
-      PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), -1, null, 100, 20, 10);
       
-      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", 2, ms, pm, true, true, new QueuedExecutor(), null, 50, 10, 5);
+      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", 2, ms, pm, true, true, new QueuedExecutor(), -1, null, 50, 10, 5);
                                 
       Message[] msgs = new Message[150];
       

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/PagingTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/PagingTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/PagingTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -63,7 +63,7 @@
 
    public void testPaging() throws Exception
    {
-      PagingFilteredQueue p = new PagingFilteredQueue("queue0", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      PagingFilteredQueue p = new PagingFilteredQueue("queue0", 1, ms, pm, true, true, new QueuedExecutor(), -1, null, 100, 20, 10);
            
       CoreMessage m = null;
 

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	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_2PCTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -67,7 +67,7 @@
    
    public void test1() throws Throwable
    {
-      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), -1, null, 100, 20, 10);
             
       Message[] msgs = new Message[241];
       

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_NTTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_NTTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_NTTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -66,7 +66,7 @@
    
    public void test1() throws Throwable
    {
-      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), -1, null, 100, 20, 10);
       
       Message[] msgs = new Message[241];
       

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_TTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_TTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_NP_TTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -67,7 +67,7 @@
  
    public void test1() throws Throwable
    {
-      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), -1, null, 100, 20, 10);
       
       Message[] msgs = new Message[241];
       

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_2PCTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_2PCTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_2PCTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -67,7 +67,7 @@
    
    public void test1() throws Throwable
    {
-      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), -1, null, 100, 20, 10);
       
       Message[] msgs = new Message[241];
       

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_NTTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_NTTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_NTTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -66,7 +66,7 @@
    
    public void test1() throws Throwable
    {
-      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), -1, null, 100, 20, 10);
       
       Message[] msgs = new Message[241];
       

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_TTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_TTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_P_TTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -67,7 +67,7 @@
    
    public void test1() throws Throwable
    {
-      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), -1, null, 100, 20, 10);
       
       Message[] msgs = new Message[241];
       

Modified: trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_ReloadTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_ReloadTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/paging/SingleChannel_ReloadTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -68,7 +68,7 @@
    
    public void testRecoverableQueueCrash() throws Throwable
    {
-      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), -1, null, 100, 20, 10);
 
       Message[] msgs = new Message[200];
       
@@ -129,7 +129,7 @@
 
       tr.start();
          
-      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), -1, null, 100, 20, 10);
       queue2.deactivate();
       queue2.load();
       
@@ -164,7 +164,7 @@
    {
       //Non recoverable queue - eg temporary queue
       
-      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), -1, null, 100, 20, 10);
       
       Message[] msgs = new Message[200];
       
@@ -225,7 +225,7 @@
       tr = new TransactionRepository(pm, ms, idm);
       tr.start();
 
-      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      PagingFilteredQueue queue2 = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), -1, null, 100, 20, 10);
       queue2.deactivate();
       queue2.load();
       
@@ -254,7 +254,7 @@
    {
       //Non recoverable queue - eg temporary queue
       
-      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), null, 100, 20, 10);
+      PagingFilteredQueue queue = new PagingFilteredQueue("queue1", 1, ms, pm, true, true, new QueuedExecutor(), -1, null, 100, 20, 10);
   
       Message[] msgs = new Message[200];
       

Modified: trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/DefaultPostOfficeTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/DefaultPostOfficeTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/DefaultPostOfficeTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -96,7 +96,7 @@
          
          PagingFilteredQueue queue1 =
             new PagingFilteredQueue("durableQueue", channelIDManager.getID(), ms, pm, true, true,
-                                    (QueuedExecutor)pool.get(), null);
+                                    (QueuedExecutor)pool.get(), -1, null);
          
          
          Binding binding1 =
@@ -116,7 +116,7 @@
          //Bind one non durable
          PagingFilteredQueue queue2 =
             new PagingFilteredQueue("nonDurableQueue", channelIDManager.getID(), ms, pm, true,
-                                    false, (QueuedExecutor)pool.get(), null);
+                                    false, (QueuedExecutor)pool.get(), -1, null);
          
          Binding binding2 =
             office1.bindQueue(new SimpleCondition("condition2"), queue2);
@@ -206,63 +206,63 @@
       {      
          office = createPostOffice();
          
-         PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);
+         PagingFilteredQueue queue1 = new PagingFilteredQueue("queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null);
          
          Binding binding1 =
             office.bindQueue(new SimpleCondition("condition1"), queue1);
          
-         PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);
+         PagingFilteredQueue queue2 = new PagingFilteredQueue("queue2", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null);
          
          Binding binding2 =
             office.bindQueue(new SimpleCondition("condition1"), queue2);
          
-         PagingFilteredQueue queue3 = new PagingFilteredQueue("queue3", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);
+         PagingFilteredQueue queue3 = new PagingFilteredQueue("queue3", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null);
          
          Binding binding3 =
             office.bindQueue(new SimpleCondition("condition1"), queue3);
          
-         PagingFilteredQueue queue4 = new PagingFilteredQueue("queue4", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);
+         PagingFilteredQueue queue4 = new PagingFilteredQueue("queue4", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null);
          
          Binding binding4 =
             office.bindQueue(new SimpleCondition("condition1"), queue4);
          
-         PagingFilteredQueue queue5 = new PagingFilteredQueue("queue5", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);
+         PagingFilteredQueue queue5 = new PagingFilteredQueue("queue5", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null);
          
          Binding binding5 =
             office.bindQueue(new SimpleCondition("condition2"), queue5);
          
-         PagingFilteredQueue queue6 = new PagingFilteredQueue("queue6", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);
+         PagingFilteredQueue queue6 = new PagingFilteredQueue("queue6", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null);
          
          Binding binding6 =
             office.bindQueue(new SimpleCondition("condition2"), queue6);
          
-         PagingFilteredQueue queue7 = new PagingFilteredQueue("queue7", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);
+         PagingFilteredQueue queue7 = new PagingFilteredQueue("queue7", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null);
          
          Binding binding7 =
             office.bindQueue(new SimpleCondition("condition2"), queue7);
          
-         PagingFilteredQueue queue8 = new PagingFilteredQueue("queue8", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);
+         PagingFilteredQueue queue8 = new PagingFilteredQueue("queue8", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null);
          
          Binding binding8 =
             office.bindQueue(new SimpleCondition("condition2"), queue8);
          
          
-         Collection bindings = office.getBindingForCondition(new SimpleCondition("dummy"));
+         Collection bindings = office.getBindingsForCondition(new SimpleCondition("dummy"));
          assertNotNull(bindings);
          assertTrue(bindings.isEmpty());
          
          //We don't match on substrings
-         bindings = office.getBindingForCondition(new SimpleCondition("condition123"));
+         bindings = office.getBindingsForCondition(new SimpleCondition("condition123"));
          assertNotNull(bindings);
          assertTrue(bindings.isEmpty());
          
          //We don't currently support hierarchies
-         bindings = office.getBindingForCondition(new SimpleCondition("condition1.subcondition"));
+         bindings = office.getBindingsForCondition(new SimpleCondition("condition1.subcondition"));
          assertNotNull(bindings);
          assertTrue(bindings.isEmpty());
          
          //We currently just do an exact match
-         bindings = office.getBindingForCondition(new SimpleCondition("condition1"));
+         bindings = office.getBindingsForCondition(new SimpleCondition("condition1"));
          assertNotNull(bindings);
          assertEquals(4, bindings.size());
          
@@ -272,7 +272,7 @@
          assertEquivalent((Binding)iter.next(), binding3);
          assertEquivalent((Binding)iter.next(), binding4);
          
-         bindings = office.getBindingForCondition(new SimpleCondition("condition2"));
+         bindings = office.getBindingsForCondition(new SimpleCondition("condition2"));
          assertNotNull(bindings);
          assertEquals(4, bindings.size());
          
@@ -334,37 +334,37 @@
          
          PagingFilteredQueue queue1 =
             new PagingFilteredQueue("queue1", channelIDManager.getID(), ms, pm, true, false,
-                                    (QueuedExecutor)pool.get(), null);
+                                    (QueuedExecutor)pool.get(), -1, null);
          
          postOffice.bindQueue(new SimpleCondition("topic1"), queue1);
          
          PagingFilteredQueue queue2 =
             new PagingFilteredQueue("queue2", channelIDManager.getID(), ms, pm, true, false,
-                                    (QueuedExecutor)pool.get(), null);
+                                    (QueuedExecutor)pool.get(), -1, null);
          
          postOffice.bindQueue(new SimpleCondition("topic1"), queue2);
          
          PagingFilteredQueue queue3 =
             new PagingFilteredQueue("queue3", channelIDManager.getID(), ms, pm, true, false,
-                                    (QueuedExecutor)pool.get(), null);
+                                    (QueuedExecutor)pool.get(), -1, null);
          
          postOffice.bindQueue(new SimpleCondition("topic1"), queue3);
          
          PagingFilteredQueue queue4 =
             new PagingFilteredQueue("queue4", channelIDManager.getID(), ms, pm, true, false,
-                                    (QueuedExecutor)pool.get(), null);
+                                    (QueuedExecutor)pool.get(), -1, null);
          
          postOffice.bindQueue(new SimpleCondition("topic2"), queue4);
          
          PagingFilteredQueue queue5 =
             new PagingFilteredQueue("queue5", channelIDManager.getID(), ms, pm, true, false,
-                                    (QueuedExecutor)pool.get(), null);
+                                    (QueuedExecutor)pool.get(), -1, null);
          
          postOffice.bindQueue(new SimpleCondition("topic2"), queue5);
          
          PagingFilteredQueue queue6 =
             new PagingFilteredQueue("queue6", channelIDManager.getID(), ms, pm, true, false,
-                                    (QueuedExecutor)pool.get(), null);
+                                    (QueuedExecutor)pool.get(), -1, null);
          
          postOffice.bindQueue(new SimpleCondition("topic2"), queue6);
       
@@ -493,7 +493,7 @@
          
          PagingFilteredQueue queue1 =
             new PagingFilteredQueue("queue1", channelIDManager.getID(), ms, pm, true, false,
-                                    (QueuedExecutor)pool.get(), null);
+                                    (QueuedExecutor)pool.get(), -1, null);
          
          postOffice.bindQueue(new SimpleCondition("condition1"), queue1);
               
@@ -548,19 +548,19 @@
       
          PagingFilteredQueue queue1 =
             new PagingFilteredQueue("queue1", channelIDManager.getID(), ms, pm, true, false,
-                                    (QueuedExecutor)pool.get(), filter);
+                                    (QueuedExecutor)pool.get(), -1, filter);
          
          postOffice.bindQueue(new SimpleCondition("topic1"), queue1);
          
          PagingFilteredQueue queue2 =
             new PagingFilteredQueue("queue2", channelIDManager.getID(), ms, pm, true, false,
-                                    (QueuedExecutor)pool.get(), null);
+                                    (QueuedExecutor)pool.get(), -1, null);
          
          postOffice.bindQueue(new SimpleCondition("topic1"), queue2);
          
          PagingFilteredQueue queue3 =
             new PagingFilteredQueue("queue3", channelIDManager.getID(), ms, pm, true, false,
-                                    (QueuedExecutor)pool.get(), null);
+                                    (QueuedExecutor)pool.get(), -1, null);
          
          postOffice.bindQueue(new SimpleCondition("topic1"), queue3);
          
@@ -654,37 +654,37 @@
       
          PagingFilteredQueue queue1 =
             new PagingFilteredQueue("queue1", channelIDManager.getID(), ms, pm, true, false,
-                                    (QueuedExecutor)pool.get(), null);
+                                    (QueuedExecutor)pool.get(), -1, null);
          
          postOffice.bindQueue(new SimpleCondition("topic1"), queue1);
          
          PagingFilteredQueue queue2 =
             new PagingFilteredQueue("queue2", channelIDManager.getID(), ms, pm, true, false,
-                                    (QueuedExecutor)pool.get(), null);
+                                    (QueuedExecutor)pool.get(), -1, null);
          
          postOffice.bindQueue(new SimpleCondition("topic1"), queue2);
          
          PagingFilteredQueue queue3 =
             new PagingFilteredQueue("queue3", channelIDManager.getID(), ms, pm, true, false,
-                                    (QueuedExecutor)pool.get(), null);
+                                    (QueuedExecutor)pool.get(), -1, null);
          
          postOffice.bindQueue(new SimpleCondition("topic1"), queue3);
          
          PagingFilteredQueue queue4 =
             new PagingFilteredQueue("queue4", channelIDManager.getID(), ms, pm, true, true,
-                                    (QueuedExecutor)pool.get(), null);
+                                    (QueuedExecutor)pool.get(), -1, null);
          
          postOffice.bindQueue(new SimpleCondition("topic2"), queue4);
          
          PagingFilteredQueue queue5 =
             new PagingFilteredQueue("queue5", channelIDManager.getID(), ms, pm, true, true,
-                                    (QueuedExecutor)pool.get(), null);
+                                    (QueuedExecutor)pool.get(), -1, null);
          
          postOffice.bindQueue(new SimpleCondition("topic2"), queue5);
          
          PagingFilteredQueue queue6 =
             new PagingFilteredQueue("queue6", channelIDManager.getID(), ms, pm, true, true,
-                                    (QueuedExecutor)pool.get(), null);
+                                    (QueuedExecutor)pool.get(), -1, null);
          
          postOffice.bindQueue(new SimpleCondition("topic2"), queue6);
       
@@ -834,13 +834,13 @@
       
          PagingFilteredQueue queue1 =
             new PagingFilteredQueue("queue1", channelIDManager.getID(), ms, pm, true, false,
-                                    (QueuedExecutor)pool.get(), null);
+                                    (QueuedExecutor)pool.get(), -1, null);
          
          postOffice.bindQueue(new SimpleCondition("topic1"), queue1);
          
          PagingFilteredQueue queue2 =
             new PagingFilteredQueue("queue2", channelIDManager.getID(), ms, pm, true, true,
-                                    (QueuedExecutor)pool.get(), null);
+                                    (QueuedExecutor)pool.get(), -1, null);
          
          postOffice.bindQueue(new SimpleCondition("topic1"), queue2);
           

Modified: trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/DefaultClusteredPostOfficeTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/DefaultClusteredPostOfficeTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/DefaultClusteredPostOfficeTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -98,10 +98,10 @@
       
       try
       {         
-         log.info("Starting office 1");
+         log.trace("Starting office 1");
          office1 = createClusteredPostOffice(1, "testgroup");
          
-         log.info("starting office 2");
+         log.trace("starting office 2");
          office2 = createClusteredPostOffice(2, "testgroup");
                   
          office3 = createClusteredPostOffice(3, "testgroup");
@@ -158,11 +158,11 @@
          
          //Add a couple of bindings
          
-         LocalClusteredQueue queue1 = new LocalClusteredQueue(office1, 1, "sub1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue1 = new LocalClusteredQueue(office1, 1, "sub1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding1 =
             office1.bindClusteredQueue(new SimpleCondition("topic1"), queue1);
          
-         LocalClusteredQueue queue2 = new LocalClusteredQueue(office1, 1, "sub2", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue2 = new LocalClusteredQueue(office1, 1, "sub2", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding2 =
             office1.bindClusteredQueue(new SimpleCondition("topic1"), queue2);
          
@@ -180,7 +180,7 @@
          
          //Add another binding on node 2
          
-         LocalClusteredQueue queue3 = new LocalClusteredQueue(office2, 2, "sub3", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue3 = new LocalClusteredQueue(office2, 2, "sub3", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
 
          Binding binding3 =
             office2.bindClusteredQueue(new SimpleCondition("topic1"), queue3);
@@ -207,7 +207,7 @@
 
          //Add another binding on node 1
          
-         LocalClusteredQueue queue4 = new LocalClusteredQueue(office2, 2, "sub4", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue4 = new LocalClusteredQueue(office2, 2, "sub4", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding4 =
             office2.bindClusteredQueue(new SimpleCondition("topic1"), queue4);
          
@@ -271,7 +271,7 @@
          
          //Add another binding on node 3
                   
-         LocalClusteredQueue queue5 = new LocalClusteredQueue(office3, 3, "sub5", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue5 = new LocalClusteredQueue(office3, 3, "sub5", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          
          Binding binding5 =
             office3.bindClusteredQueue(new SimpleCondition("topic1"), queue5);
@@ -307,12 +307,12 @@
          
          //Add a durable and a non durable binding on node 1
          
-         LocalClusteredQueue queue6 = new LocalClusteredQueue(office1, 1, "sub6", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue6 = new LocalClusteredQueue(office1, 1, "sub6", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), -1, null, tr);
          
          Binding binding6 =
             office1.bindClusteredQueue(new SimpleCondition("topic1"), queue6);
          
-         LocalClusteredQueue queue7 = new LocalClusteredQueue(office1, 1, "sub7", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue7 = new LocalClusteredQueue(office1, 1, "sub7", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          
          Binding binding7 =
             office1.bindClusteredQueue(new SimpleCondition("topic1"), queue7);
@@ -598,15 +598,15 @@
          
          office2 = createClusteredPostOffice(2, "testgroup");
          
-         LocalClusteredQueue queue1 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue1 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          
          Binding binding1 = office1.bindClusteredQueue(new SimpleCondition("queue1"), queue1);
 
-         LocalClusteredQueue queue2 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue2 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
 
          Binding binding2 = office2.bindClusteredQueue(new SimpleCondition("queue1"), queue2);
 
-         LocalClusteredQueue queue3 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue3 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          
          try
          {
@@ -617,7 +617,7 @@
          {
             //Ok
          }
-         LocalClusteredQueue queue4 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue4 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          
          try
          {
@@ -633,11 +633,11 @@
 
          office1.unbindClusteredQueue("queue1");
 
-         LocalClusteredQueue queue5 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue5 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          
          Binding binding5 = office1.bindClusteredQueue(new SimpleCondition("queue1"), queue5);
          
-         PagingFilteredQueue queue6 = new PagingFilteredQueue("queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null);
+         PagingFilteredQueue queue6 = new PagingFilteredQueue("queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null);
          try
          {
             Binding binding6 = office1.bindQueue(new SimpleCondition("queue1"), queue6);
@@ -651,13 +651,13 @@
          office1.unbindClusteredQueue("queue1");
          
          //It should be possible to bind queues locally into a clustered post office
-         LocalClusteredQueue queue7 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue7 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding7 = office1.bindQueue(new SimpleCondition("queue1"), queue7);
          
-         LocalClusteredQueue queue8 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue8 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding8 = office2.bindQueue(new SimpleCondition("queue1"), queue8);
          
-         LocalClusteredQueue queue9 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue9 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          try
          {
             Binding binding9 = office1.bindQueue(new SimpleCondition("queue1"), queue9);
@@ -701,15 +701,15 @@
          SimpleFilter filter1 = new SimpleFilter(2);
          SimpleFilter filter2 = new SimpleFilter(3);
       
-         LocalClusteredQueue queue1 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor)pool.get(), filter1, tr);
+         LocalClusteredQueue queue1 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor)pool.get(), -1, filter1, tr);
          Binding binding1 =
             office1.bindClusteredQueue(new SimpleCondition("topic1"), queue1);
          
-         LocalClusteredQueue queue2 = new LocalClusteredQueue(office2, 2, "queue2", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor)pool.get(), filter2, tr);
+         LocalClusteredQueue queue2 = new LocalClusteredQueue(office2, 2, "queue2", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor)pool.get(), -1, filter2, tr);
          Binding binding2 =
             office2.bindClusteredQueue(new SimpleCondition("topic1"), queue2);
          
-         LocalClusteredQueue queue3 = new LocalClusteredQueue(office2, 2, "queue3", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue3 = new LocalClusteredQueue(office2, 2, "queue3", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding3 =
             office2.bindClusteredQueue(new SimpleCondition("topic1"), queue3);   
          
@@ -810,52 +810,52 @@
          LocalClusteredQueue[] queues = new LocalClusteredQueue[16];
          Binding[] bindings = new Binding[16];
          
-         queues[0] = new LocalClusteredQueue(office1, 1, "sub1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         queues[0] = new LocalClusteredQueue(office1, 1, "sub1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[0] = office1.bindClusteredQueue(new SimpleCondition("topic1"), queues[0]);
          
-         queues[1] = new LocalClusteredQueue(office1, 1, "sub2", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         queues[1] = new LocalClusteredQueue(office1, 1, "sub2", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[1] = office1.bindClusteredQueue(new SimpleCondition("topic1"), queues[1]);
          
-         queues[2] = new LocalClusteredQueue(office2, 2, "sub3", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         queues[2] = new LocalClusteredQueue(office2, 2, "sub3", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[2] = office2.bindClusteredQueue(new SimpleCondition("topic1"), queues[2]);
          
-         queues[3] = new LocalClusteredQueue(office2, 2, "sub4", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         queues[3] = new LocalClusteredQueue(office2, 2, "sub4", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[3] = office2.bindClusteredQueue(new SimpleCondition("topic1"), queues[3]);
          
-         queues[4] = new LocalClusteredQueue(office2, 2, "sub5", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), null, tr);
+         queues[4] = new LocalClusteredQueue(office2, 2, "sub5", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[4] = office2.bindClusteredQueue(new SimpleCondition("topic1"), queues[4]);
          
-         queues[5] = new LocalClusteredQueue(office1, 1, "sub6", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         queues[5] = new LocalClusteredQueue(office1, 1, "sub6", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[5] = office1.bindClusteredQueue(new SimpleCondition("topic1"), queues[5]);
          
-         queues[6] = new LocalClusteredQueue(office1, 1, "sub7", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), null, tr);
+         queues[6] = new LocalClusteredQueue(office1, 1, "sub7", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[6] = office1.bindClusteredQueue(new SimpleCondition("topic1"), queues[6]);
          
-         queues[7] = new LocalClusteredQueue(office1, 1, "sub8", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), null, tr);
+         queues[7] = new LocalClusteredQueue(office1, 1, "sub8", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[7] = office1.bindClusteredQueue(new SimpleCondition("topic1"), queues[7]);
          
-         queues[8] = new LocalClusteredQueue(office1, 1, "sub9", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         queues[8] = new LocalClusteredQueue(office1, 1, "sub9", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[8] = office1.bindClusteredQueue(new SimpleCondition("topic2"), queues[8]);
          
-         queues[9] = new LocalClusteredQueue(office1, 1, "sub10", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         queues[9] = new LocalClusteredQueue(office1, 1, "sub10", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[9] = office1.bindClusteredQueue(new SimpleCondition("topic2"), queues[9]);
          
-         queues[10] = new LocalClusteredQueue(office2, 2, "sub11", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         queues[10] = new LocalClusteredQueue(office2, 2, "sub11", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[10] = office2.bindClusteredQueue(new SimpleCondition("topic2"), queues[10]);
          
-         queues[11] = new LocalClusteredQueue(office2, 2, "sub12", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         queues[11] = new LocalClusteredQueue(office2, 2, "sub12", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[11] = office2.bindClusteredQueue(new SimpleCondition("topic2"), queues[11]);
          
-         queues[12] = new LocalClusteredQueue(office2, 2, "sub13", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), null, tr);
+         queues[12] = new LocalClusteredQueue(office2, 2, "sub13", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[12] = office2.bindClusteredQueue(new SimpleCondition("topic2"), queues[12]);
          
-         queues[13] = new LocalClusteredQueue(office1, 1, "sub14", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         queues[13] = new LocalClusteredQueue(office1, 1, "sub14", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[13] = office1.bindClusteredQueue(new SimpleCondition("topic2"), queues[13]);
          
-         queues[14] = new LocalClusteredQueue(office1, 1, "sub15", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), null, tr);
+         queues[14] = new LocalClusteredQueue(office1, 1, "sub15", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[14] = office1.bindClusteredQueue(new SimpleCondition("topic2"), queues[14]);
          
-         queues[15] = new LocalClusteredQueue(office1, 1, "sub16", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), null, tr);
+         queues[15] = new LocalClusteredQueue(office1, 1, "sub16", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[15] = office1.bindClusteredQueue(new SimpleCondition("topic2"), queues[15]);
        
          SimpleReceiver[] receivers = new SimpleReceiver[16];
@@ -1001,27 +1001,27 @@
          //We deploy the queue on nodes 1, 2, 3, 4 and 5
          //We don't deploy on node 6
          
-         LocalClusteredQueue queue1 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue1 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding1 = office1.bindClusteredQueue(new SimpleCondition("queue1"), queue1);
          SimpleReceiver receiver1 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          queue1.add(receiver1);
          
-         LocalClusteredQueue queue2 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue2 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding2 = office2.bindClusteredQueue(new SimpleCondition("queue1"), queue2); 
          SimpleReceiver receiver2 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          queue2.add(receiver2);
          
-         LocalClusteredQueue queue3 = new LocalClusteredQueue(office3, 3, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue3 = new LocalClusteredQueue(office3, 3, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding3 = office3.bindClusteredQueue(new SimpleCondition("queue1"), queue3);
          SimpleReceiver receiver3 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          queue3.add(receiver3);
          
-         LocalClusteredQueue queue4 = new LocalClusteredQueue(office4, 4, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue4 = new LocalClusteredQueue(office4, 4, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding4 = office4.bindClusteredQueue(new SimpleCondition("queue1"), queue4); 
          SimpleReceiver receiver4 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          queue4.add(receiver4);
          
-         LocalClusteredQueue queue5 = new LocalClusteredQueue(office5, 5, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue5 = new LocalClusteredQueue(office5, 5, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding5 = office5.bindClusteredQueue(new SimpleCondition("queue1"), queue5);
          SimpleReceiver receiver5 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          queue5.add(receiver5);
@@ -1154,17 +1154,17 @@
          office2 = createClusteredPostOffice(2, "testgroup");
          office3 = createClusteredPostOffice(3, "testgroup");
 
-         LocalClusteredQueue sub1 = new LocalClusteredQueue(office1, 1, "sub1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue sub1 = new LocalClusteredQueue(office1, 1, "sub1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding1 = office1.bindQueue(new SimpleCondition("topic"), sub1);
          SimpleReceiver receiver1 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          sub1.add(receiver1);
          
-         LocalClusteredQueue sub2 = new LocalClusteredQueue(office2, 2, "sub2", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue sub2 = new LocalClusteredQueue(office2, 2, "sub2", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding2 = office2.bindQueue(new SimpleCondition("topic"), sub2); 
          SimpleReceiver receiver2 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          sub2.add(receiver2);
          
-         LocalClusteredQueue sub3 = new LocalClusteredQueue(office3, 3, "sub3", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue sub3 = new LocalClusteredQueue(office3, 3, "sub3", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding3 = office3.bindQueue(new SimpleCondition("topic"), sub3);
          SimpleReceiver receiver3 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          sub3.add(receiver3);
@@ -1271,13 +1271,13 @@
          //======
          
          //Non durable 1 on node 2
-         LocalClusteredQueue nonDurable1 = new LocalClusteredQueue(office2, 2, "nondurable1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue nonDurable1 = new LocalClusteredQueue(office2, 2, "nondurable1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding1 = office2.bindClusteredQueue(new SimpleCondition("topic"), nonDurable1);
          SimpleReceiver receiver1 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          nonDurable1.add(receiver1);
          
          //Non durable 2 on node 2
-         LocalClusteredQueue nonDurable2 = new LocalClusteredQueue(office2, 2, "nondurable2", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue nonDurable2 = new LocalClusteredQueue(office2, 2, "nondurable2", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding2 = office2.bindClusteredQueue(new SimpleCondition("topic"), nonDurable2);
          SimpleReceiver receiver2 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          nonDurable2.add(receiver2);
@@ -1286,13 +1286,13 @@
          //======
          
          //Non shared durable
-         LocalClusteredQueue nonSharedDurable1 = new LocalClusteredQueue(office3, 3, "nonshareddurable1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue nonSharedDurable1 = new LocalClusteredQueue(office3, 3, "nonshareddurable1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding3 = office3.bindClusteredQueue(new SimpleCondition("topic"), nonSharedDurable1);
          SimpleReceiver receiver3 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          nonSharedDurable1.add(receiver3);
          
          //Non durable
-         LocalClusteredQueue nonDurable3 = new LocalClusteredQueue(office3, 3, "nondurable3", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue nonDurable3 = new LocalClusteredQueue(office3, 3, "nondurable3", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding4 = office3.bindClusteredQueue(new SimpleCondition("topic"), nonDurable3);
          SimpleReceiver receiver4 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          nonDurable3.add(receiver4);
@@ -1301,31 +1301,31 @@
          //======
          
          //Shared durable
-         LocalClusteredQueue sharedDurable1 = new LocalClusteredQueue(office4, 4, "shareddurable1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue sharedDurable1 = new LocalClusteredQueue(office4, 4, "shareddurable1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding5 = office4.bindClusteredQueue(new SimpleCondition("topic"), sharedDurable1);
          SimpleReceiver receiver5 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          sharedDurable1.add(receiver5);
          
          //Non shared durable
-         LocalClusteredQueue nonSharedDurable2 = new LocalClusteredQueue(office4, 4, "nonshareddurable2", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue nonSharedDurable2 = new LocalClusteredQueue(office4, 4, "nonshareddurable2", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding6 = office4.bindClusteredQueue(new SimpleCondition("topic"), nonSharedDurable2);
          SimpleReceiver receiver6 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          nonSharedDurable2.add(receiver6);
          
          //Non durable
-         LocalClusteredQueue nonDurable4 = new LocalClusteredQueue(office4, 4, "nondurable4", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue nonDurable4 = new LocalClusteredQueue(office4, 4, "nondurable4", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding7 = office4.bindClusteredQueue(new SimpleCondition("topic"), nonDurable4);
          SimpleReceiver receiver7 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          nonDurable4.add(receiver7);
          
          // Non durable
-         LocalClusteredQueue nonDurable5 = new LocalClusteredQueue(office4, 4, "nondurable5", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue nonDurable5 = new LocalClusteredQueue(office4, 4, "nondurable5", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding8 = office4.bindClusteredQueue(new SimpleCondition("topic"), nonDurable5);
          SimpleReceiver receiver8 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          nonDurable5.add(receiver8);
          
          //Non durable
-         LocalClusteredQueue nonDurable6 = new LocalClusteredQueue(office4, 4, "nondurable6", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue nonDurable6 = new LocalClusteredQueue(office4, 4, "nondurable6", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding9 = office4.bindClusteredQueue(new SimpleCondition("topic"), nonDurable6);
          SimpleReceiver receiver9 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          nonDurable6.add(receiver9);
@@ -1333,32 +1333,32 @@
          // Node 5
          //=======
          //Shared durable
-         LocalClusteredQueue sharedDurable2 = new LocalClusteredQueue(office5, 5, "shareddurable1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue sharedDurable2 = new LocalClusteredQueue(office5, 5, "shareddurable1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding10 = office5.bindClusteredQueue(new SimpleCondition("topic"), sharedDurable2);
          SimpleReceiver receiver10 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          sharedDurable2.add(receiver10);
          
          //Shared durable
-         LocalClusteredQueue sharedDurable3 = new LocalClusteredQueue(office5, 5, "shareddurable2", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue sharedDurable3 = new LocalClusteredQueue(office5, 5, "shareddurable2", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding11 = office5.bindClusteredQueue(new SimpleCondition("topic"), sharedDurable3);
          SimpleReceiver receiver11 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          sharedDurable3.add(receiver11);
          
          // Node 6
          //=========
-         LocalClusteredQueue sharedDurable4 = new LocalClusteredQueue(office6, 6, "shareddurable2", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue sharedDurable4 = new LocalClusteredQueue(office6, 6, "shareddurable2", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding12 = office6.bindClusteredQueue(new SimpleCondition("topic"), sharedDurable4);
          SimpleReceiver receiver12 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          sharedDurable4.add(receiver12);
          
-         LocalClusteredQueue nonDurable7 = new LocalClusteredQueue(office6, 6, "nondurable7", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue nonDurable7 = new LocalClusteredQueue(office6, 6, "nondurable7", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding13 = office6.bindClusteredQueue(new SimpleCondition("topic"), nonDurable7);
          SimpleReceiver receiver13 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          nonDurable7.add(receiver13);
          
          //Node 7
          //=======
-         LocalClusteredQueue sharedDurable5 = new LocalClusteredQueue(office7, 7, "shareddurable2", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue sharedDurable5 = new LocalClusteredQueue(office7, 7, "shareddurable2", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding14 = office7.bindClusteredQueue(new SimpleCondition("topic"), sharedDurable5);
          SimpleReceiver receiver14 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          sharedDurable5.add(receiver14);
@@ -1690,52 +1690,52 @@
          LocalClusteredQueue[] queues = new LocalClusteredQueue[16];
          Binding[] bindings = new Binding[16];
          
-         queues[0] = new LocalClusteredQueue(office1, 1, "sub1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         queues[0] = new LocalClusteredQueue(office1, 1, "sub1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[0] = office1.bindClusteredQueue(new SimpleCondition("topic1"), queues[0]);
          
-         queues[1] = new LocalClusteredQueue(office1, 1, "sub2", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         queues[1] = new LocalClusteredQueue(office1, 1, "sub2", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[1] = office1.bindClusteredQueue(new SimpleCondition("topic1"), queues[1]);
          
-         queues[2] = new LocalClusteredQueue(office2, 2, "sub3", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         queues[2] = new LocalClusteredQueue(office2, 2, "sub3", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[2] = office2.bindClusteredQueue(new SimpleCondition("topic1"), queues[2]);
          
-         queues[3] = new LocalClusteredQueue(office2, 2, "sub4", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         queues[3] = new LocalClusteredQueue(office2, 2, "sub4", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[3] = office2.bindClusteredQueue(new SimpleCondition("topic1"), queues[3]);
          
-         queues[4] = new LocalClusteredQueue(office2, 2, "sub5", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), null, tr);
+         queues[4] = new LocalClusteredQueue(office2, 2, "sub5", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[4] = office2.bindClusteredQueue(new SimpleCondition("topic1"), queues[4]);
          
-         queues[5] = new LocalClusteredQueue(office1, 1, "sub6", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         queues[5] = new LocalClusteredQueue(office1, 1, "sub6", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[5] = office1.bindClusteredQueue(new SimpleCondition("topic1"), queues[5]);
          
-         queues[6] = new LocalClusteredQueue(office1, 1, "sub7", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), null, tr);
+         queues[6] = new LocalClusteredQueue(office1, 1, "sub7", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[6] = office1.bindClusteredQueue(new SimpleCondition("topic1"), queues[6]);
          
-         queues[7] = new LocalClusteredQueue(office1, 1, "sub8", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), null, tr);
+         queues[7] = new LocalClusteredQueue(office1, 1, "sub8", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[7] = office1.bindClusteredQueue(new SimpleCondition("topic1"), queues[7]);
          
-         queues[8] = new LocalClusteredQueue(office1, 1, "sub9", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         queues[8] = new LocalClusteredQueue(office1, 1, "sub9", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[8] = office1.bindClusteredQueue(new SimpleCondition("topic2"), queues[8]);
          
-         queues[9] = new LocalClusteredQueue(office1, 1, "sub10", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         queues[9] = new LocalClusteredQueue(office1, 1, "sub10", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[9] = office1.bindClusteredQueue(new SimpleCondition("topic2"), queues[9]);
          
-         queues[10] = new LocalClusteredQueue(office2, 2, "sub11", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         queues[10] = new LocalClusteredQueue(office2, 2, "sub11", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[10] = office2.bindClusteredQueue(new SimpleCondition("topic2"), queues[10]);
          
-         queues[11] = new LocalClusteredQueue(office2, 2, "sub12", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         queues[11] = new LocalClusteredQueue(office2, 2, "sub12", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[11] = office2.bindClusteredQueue(new SimpleCondition("topic2"), queues[11]);
          
-         queues[12] = new LocalClusteredQueue(office2, 2, "sub13", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), null, tr);
+         queues[12] = new LocalClusteredQueue(office2, 2, "sub13", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[12] = office2.bindClusteredQueue(new SimpleCondition("topic2"), queues[12]);
          
-         queues[13] = new LocalClusteredQueue(office1, 1, "sub14", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         queues[13] = new LocalClusteredQueue(office1, 1, "sub14", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[13] = office1.bindClusteredQueue(new SimpleCondition("topic2"), queues[13]);
          
-         queues[14] = new LocalClusteredQueue(office1, 1, "sub15", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), null, tr);
+         queues[14] = new LocalClusteredQueue(office1, 1, "sub15", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[14] = office1.bindClusteredQueue(new SimpleCondition("topic2"), queues[14]);
          
-         queues[15] = new LocalClusteredQueue(office1, 1, "sub16", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), null, tr);
+         queues[15] = new LocalClusteredQueue(office1, 1, "sub16", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor)pool.get(), -1, null, tr);
          bindings[15] = office1.bindClusteredQueue(new SimpleCondition("topic2"), queues[15]);
 
          SimpleReceiver[] receivers = new SimpleReceiver[16];

Modified: trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/DefaultClusteredPostOfficeWithDefaultRouterTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/DefaultClusteredPostOfficeWithDefaultRouterTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/DefaultClusteredPostOfficeWithDefaultRouterTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -128,27 +128,27 @@
          
          office6 = createClusteredPostOffice(6, "testgroup");
          
-         LocalClusteredQueue queue1 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue1 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding1 = office2.bindClusteredQueue(new SimpleCondition("topic"), queue1);
          SimpleReceiver receiver1 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          queue1.add(receiver1);
          
-         LocalClusteredQueue queue2 = new LocalClusteredQueue(office3, 3, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue2 = new LocalClusteredQueue(office3, 3, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding2 = office3.bindClusteredQueue(new SimpleCondition("topic"), queue2);
          SimpleReceiver receiver2 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          queue2.add(receiver2);
          
-         LocalClusteredQueue queue3 = new LocalClusteredQueue(office4, 4, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue3 = new LocalClusteredQueue(office4, 4, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding3 = office4.bindClusteredQueue(new SimpleCondition("topic"), queue3);
          SimpleReceiver receiver3 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          queue3.add(receiver3);
          
-         LocalClusteredQueue queue4 = new LocalClusteredQueue(office5, 5, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue4 = new LocalClusteredQueue(office5, 5, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding4 = office5.bindClusteredQueue(new SimpleCondition("topic"), queue4);
          SimpleReceiver receiver4 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          queue4.add(receiver4);
          
-         LocalClusteredQueue queue5 = new LocalClusteredQueue(office6, 6, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue5 = new LocalClusteredQueue(office6, 6, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding5 = office6.bindClusteredQueue(new SimpleCondition("topic"), queue5);
          SimpleReceiver receiver5 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          queue5.add(receiver5);
@@ -269,27 +269,27 @@
          
          office6 = createClusteredPostOffice(6, "testgroup");
          
-         LocalClusteredQueue queue1 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue1 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding1 = office2.bindClusteredQueue(new SimpleCondition("topic"), queue1);
          SimpleReceiver receiver1 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          queue1.add(receiver1);
          
-         LocalClusteredQueue queue2 = new LocalClusteredQueue(office3, 3, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue2 = new LocalClusteredQueue(office3, 3, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding2 = office3.bindClusteredQueue(new SimpleCondition("topic"), queue2);
          SimpleReceiver receiver2 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          queue2.add(receiver2);
          
-         LocalClusteredQueue queue3 = new LocalClusteredQueue(office4, 4, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue3 = new LocalClusteredQueue(office4, 4, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding3 = office4.bindClusteredQueue(new SimpleCondition("topic"), queue3);
          SimpleReceiver receiver3 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          queue3.add(receiver3);
          
-         LocalClusteredQueue queue4 = new LocalClusteredQueue(office5, 5, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue4 = new LocalClusteredQueue(office5, 5, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding4 = office5.bindClusteredQueue(new SimpleCondition("topic"), queue4);
          SimpleReceiver receiver4 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          queue4.add(receiver4);
          
-         LocalClusteredQueue queue5 = new LocalClusteredQueue(office6, 6, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), null, tr);
+         LocalClusteredQueue queue5 = new LocalClusteredQueue(office6, 6, "queue1", channelIDManager.getID(), ms, pm, true, false, (QueuedExecutor)pool.get(), -1, null, tr);
          Binding binding5 = office6.bindClusteredQueue(new SimpleCondition("topic"), queue5);
          SimpleReceiver receiver5 = new SimpleReceiver("blah", SimpleReceiver.ACCEPTING);
          queue5.add(receiver5);

Modified: trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/DefaultMessagePullPolicyTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/DefaultMessagePullPolicyTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/DefaultMessagePullPolicyTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -358,7 +358,7 @@
          return null;
       }
 
-      public int numberOfReceivers()
+      public int getNumberOfReceivers()
       {
          // TODO Auto-generated method stub
          return 0;
@@ -387,6 +387,30 @@
          // TODO Auto-generated method stub
          return 0;
       }
+
+      public int getMaxSize()
+      {
+         // TODO Auto-generated method stub
+         return 0;
+      }
+
+      public int getMessagesAdded()
+      {
+         // TODO Auto-generated method stub
+         return 0;
+      }
+
+      public void setMaxSize(int newSize)
+      {
+         // TODO Auto-generated method stub
+         
+      }
+
+      public int getScheduledCount()
+      {
+         // TODO Auto-generated method stub
+         return 0;
+      }
       
    }
 

Modified: trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/DefaultRouterTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/DefaultRouterTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/DefaultRouterTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -97,34 +97,34 @@
       ClusteredQueue queue1 = new SimpleQueue(true);
       dr.add(queue1);
       
-      assertEquals(1, dr.numberOfReceivers());
+      assertEquals(1, dr.getNumberOfReceivers());
       assertEquals(1, dr.getQueues().size());
       
       ClusteredQueue queue2 = new SimpleQueue(false);
       dr.add(queue2);
       
-      assertEquals(2, dr.numberOfReceivers());
+      assertEquals(2, dr.getNumberOfReceivers());
       assertEquals(2, dr.getQueues().size());
       
       ClusteredQueue queue3 = new SimpleQueue(false);
       dr.add(queue3);
       
-      assertEquals(3, dr.numberOfReceivers());
+      assertEquals(3, dr.getNumberOfReceivers());
       assertEquals(3, dr.getQueues().size());
       
       dr.remove(queue3);
       
-      assertEquals(2, dr.numberOfReceivers());
+      assertEquals(2, dr.getNumberOfReceivers());
       assertEquals(2, dr.getQueues().size());
       
       dr.remove(queue2);
       
-      assertEquals(1, dr.numberOfReceivers());
+      assertEquals(1, dr.getNumberOfReceivers());
       assertEquals(1, dr.getQueues().size());
       
       dr.remove(queue1);
       
-      assertEquals(0, dr.numberOfReceivers());
+      assertEquals(0, dr.getNumberOfReceivers());
       assertTrue(dr.getQueues().isEmpty());
       
    }
@@ -586,7 +586,7 @@
          return null;
       }
 
-      public int numberOfReceivers()
+      public int getNumberOfReceivers()
       {
          if (receiver != null)
          {
@@ -621,6 +621,30 @@
          // TODO Auto-generated method stub
          return 0;
       }
+
+      public int getMaxSize()
+      {
+         // TODO Auto-generated method stub
+         return 0;
+      }
+
+      public int getMessagesAdded()
+      {
+         // TODO Auto-generated method stub
+         return 0;
+      }
+
+      public void setMaxSize(int newSize)
+      {
+         // TODO Auto-generated method stub
+         
+      }
+
+      public int getScheduledCount()
+      {
+         // TODO Auto-generated method stub
+         return 0;
+      }
       
    }
    

Modified: trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/RecoveryTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/RecoveryTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/RecoveryTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -99,15 +99,15 @@
 
          office3 = (DefaultClusteredPostOffice) createClusteredPostOffice(3, "testgroup");
 
-         LocalClusteredQueue queue1 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), null, tr);
+         LocalClusteredQueue queue1 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), -1, null, tr);
          Binding binding1 =
             office1.bindClusteredQueue(new SimpleCondition("topic1"), queue1);
 
-         LocalClusteredQueue queue2 = new LocalClusteredQueue(office2, 2, "queue2", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), null, tr);
+         LocalClusteredQueue queue2 = new LocalClusteredQueue(office2, 2, "queue2", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), -1, null, tr);
          Binding binding2 =
             office2.bindClusteredQueue(new SimpleCondition("topic1"), queue2);
 
-         LocalClusteredQueue queue3 = new LocalClusteredQueue(office3, 3, "queue3", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), null, tr);
+         LocalClusteredQueue queue3 = new LocalClusteredQueue(office3, 3, "queue3", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), -1, null, tr);
          Binding binding3 =
             office3.bindClusteredQueue(new SimpleCondition("topic1"), queue3);
 
@@ -234,15 +234,15 @@
 
          office3 = (DefaultClusteredPostOffice) createClusteredPostOffice(3, "testgroup");
 
-         LocalClusteredQueue queue1 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), null, tr);
+         LocalClusteredQueue queue1 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), -1, null, tr);
          Binding binding1 =
             office1.bindClusteredQueue(new SimpleCondition("topic1"), queue1);
 
-         LocalClusteredQueue queue2 = new LocalClusteredQueue(office2, 2, "queue2", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), null, tr);
+         LocalClusteredQueue queue2 = new LocalClusteredQueue(office2, 2, "queue2", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), -1, null, tr);
          Binding binding2 =
             office2.bindClusteredQueue(new SimpleCondition("topic1"), queue2);
 
-         LocalClusteredQueue queue3 = new LocalClusteredQueue(office3, 3, "queue3", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), null, tr);
+         LocalClusteredQueue queue3 = new LocalClusteredQueue(office3, 3, "queue3", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), -1, null, tr);
          Binding binding3 =
             office3.bindClusteredQueue(new SimpleCondition("topic1"), queue3);
 

Modified: trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/RedistributionWithDefaultMessagePullPolicyTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/RedistributionWithDefaultMessagePullPolicyTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/core/plugin/postoffice/cluster/RedistributionWithDefaultMessagePullPolicyTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -142,11 +142,11 @@
 
          office2 = (DefaultClusteredPostOffice) createClusteredPostOffice(2, "testgroup");
 
-         LocalClusteredQueue queue1 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), null, tr);
+         LocalClusteredQueue queue1 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), -1, null, tr);
          Binding binding1 =
             office1.bindClusteredQueue(new SimpleCondition("queue1"), queue1);
 
-         LocalClusteredQueue queue2 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), null, tr);
+         LocalClusteredQueue queue2 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), -1, null, tr);
          Binding binding2 =
             office2.bindClusteredQueue(new SimpleCondition("queue1"), queue2);
 
@@ -182,7 +182,7 @@
 
          receiver2.setMaxRefs(1);
 
-         log.info("delivering");
+         log.trace("delivering");
          queue2.deliver(false);
 
          Thread.sleep(3000);
@@ -190,10 +190,10 @@
          assertTrue(office1.getHoldingTransactions().isEmpty());
          assertTrue(office2.getHoldingTransactions().isEmpty());
 
-         log.info("r2 " + receiver2.getMessages().size());
+         log.trace("r2 " + receiver2.getMessages().size());
 
-         log.info("queue1 refs:" + queue1.memoryRefCount() + " dels:" + queue1.getDeliveringCount());
-         log.info("queue2 refs:" + queue2.memoryRefCount() + " dels:" + queue2.getDeliveringCount());
+         log.trace("queue1 refs:" + queue1.memoryRefCount() + " dels:" + queue1.getDeliveringCount());
+         log.trace("queue2 refs:" + queue2.memoryRefCount() + " dels:" + queue2.getDeliveringCount());
 
          assertEquals(0, queue1.memoryRefCount());
          assertEquals(0, queue1.getDeliveringCount());
@@ -236,11 +236,11 @@
 
          office2 = (DefaultClusteredPostOffice) createClusteredPostOffice(2, "testgroup");
 
-         LocalClusteredQueue queue1 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), null, tr);
+         LocalClusteredQueue queue1 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), -1, null, tr);
          Binding binding1 =
             office1.bindClusteredQueue(new SimpleCondition("queue1"), queue1);
 
-         LocalClusteredQueue queue2 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), null, tr);
+         LocalClusteredQueue queue2 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), -1, null, tr);
          Binding binding2 =
             office2.bindClusteredQueue(new SimpleCondition("queue1"), queue2);
 
@@ -279,7 +279,7 @@
          //Force a failure before commit
          office2.setFail(true, false, false);
 
-         log.info("delivering");
+         log.trace("delivering");
          queue2.deliver(false);
 
          Thread.sleep(3000);
@@ -287,8 +287,8 @@
          assertEquals(1, office1.getHoldingTransactions().size());
          assertTrue(office2.getHoldingTransactions().isEmpty());
 
-         log.info("queue1 refs:" + queue1.memoryRefCount() + " dels:" + queue1.getDeliveringCount());
-         log.info("queue2 refs:" + queue2.memoryRefCount() + " dels:" + queue2.getDeliveringCount());
+         log.trace("queue1 refs:" + queue1.memoryRefCount() + " dels:" + queue1.getDeliveringCount());
+         log.trace("queue2 refs:" + queue2.memoryRefCount() + " dels:" + queue2.getDeliveringCount());
 
          assertEquals(0, queue1.memoryRefCount());
          assertEquals(1, queue1.getDeliveringCount());
@@ -336,11 +336,11 @@
 
          office2 = (DefaultClusteredPostOffice) createClusteredPostOffice(2, "testgroup");
 
-         LocalClusteredQueue queue1 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), null, tr);
+         LocalClusteredQueue queue1 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), -1, null, tr);
          Binding binding1 =
             office1.bindClusteredQueue(new SimpleCondition("queue1"), queue1);
 
-         LocalClusteredQueue queue2 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), null, tr);
+         LocalClusteredQueue queue2 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), -1, null, tr);
          Binding binding2 =
             office2.bindClusteredQueue(new SimpleCondition("queue1"), queue2);
 
@@ -379,7 +379,7 @@
          //Force a failure after commit the ack to storage
          office2.setFail(false, true, false);
 
-         log.info("delivering");
+         log.trace("delivering");
          queue2.deliver(false);
 
          Thread.sleep(3000);
@@ -387,8 +387,8 @@
          assertEquals(1, office1.getHoldingTransactions().size());
          assertTrue(office2.getHoldingTransactions().isEmpty());
 
-         log.info("queue1 refs:" + queue1.memoryRefCount() + " dels:" + queue1.getDeliveringCount());
-         log.info("queue2 refs:" + queue2.memoryRefCount() + " dels:" + queue2.getDeliveringCount());
+         log.trace("queue1 refs:" + queue1.memoryRefCount() + " dels:" + queue1.getDeliveringCount());
+         log.trace("queue2 refs:" + queue2.memoryRefCount() + " dels:" + queue2.getDeliveringCount());
 
          assertEquals(0, queue1.memoryRefCount());
          assertEquals(1, queue1.getDeliveringCount());
@@ -432,11 +432,11 @@
 
          office2 = (DefaultClusteredPostOffice) createClusteredPostOffice(2, "testgroup");
 
-         LocalClusteredQueue queue1 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), null, tr);
+         LocalClusteredQueue queue1 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), -1, null, tr);
          Binding binding1 =
             office1.bindClusteredQueue(new SimpleCondition("queue1"), queue1);
 
-         LocalClusteredQueue queue2 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), null, tr);
+         LocalClusteredQueue queue2 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, true, (QueuedExecutor) pool.get(), -1, null, tr);
          Binding binding2 =
             office2.bindClusteredQueue(new SimpleCondition("queue1"), queue2);
 
@@ -474,7 +474,7 @@
 
          office2.setFail(false, false, true);
 
-         log.info("delivering");
+         log.trace("delivering");
          queue2.deliver(false);
 
          Thread.sleep(3000);
@@ -484,8 +484,8 @@
          assertTrue(office2.getHoldingTransactions().isEmpty());
          assertTrue(office2.getHoldingTransactions().isEmpty());
 
-         log.info("queue1 refs:" + queue1.memoryRefCount() + " dels:" + queue1.getDeliveringCount());
-         log.info("queue2 refs:" + queue2.memoryRefCount() + " dels:" + queue2.getDeliveringCount());
+         log.trace("queue1 refs:" + queue1.memoryRefCount() + " dels:" + queue1.getDeliveringCount());
+         log.trace("queue2 refs:" + queue2.memoryRefCount() + " dels:" + queue2.getDeliveringCount());
 
          assertEquals(1, queue1.memoryRefCount());
          assertEquals(0, queue1.getDeliveringCount());
@@ -531,19 +531,19 @@
 
          office5 = (DefaultClusteredPostOffice) createClusteredPostOffice(5, "testgroup");
 
-         LocalClusteredQueue queue1 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor) pool.get(), null, tr);
+         LocalClusteredQueue queue1 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor) pool.get(), -1, null, tr);
          Binding binding1 = office1.bindClusteredQueue(new SimpleCondition("queue1"), queue1);
 
-         LocalClusteredQueue queue2 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor) pool.get(), null, tr);
+         LocalClusteredQueue queue2 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor) pool.get(), -1, null, tr);
          Binding binding2 = office2.bindClusteredQueue(new SimpleCondition("queue1"), queue2);
 
-         LocalClusteredQueue queue3 = new LocalClusteredQueue(office3, 3, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor) pool.get(), null, tr);
+         LocalClusteredQueue queue3 = new LocalClusteredQueue(office3, 3, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor) pool.get(), -1, null, tr);
          Binding binding3 = office3.bindClusteredQueue(new SimpleCondition("queue1"), queue3);
 
-         LocalClusteredQueue queue4 = new LocalClusteredQueue(office4, 4, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor) pool.get(), null, tr);
+         LocalClusteredQueue queue4 = new LocalClusteredQueue(office4, 4, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor) pool.get(), -1, null, tr);
          Binding binding4 = office4.bindClusteredQueue(new SimpleCondition("queue1"), queue4);
 
-         LocalClusteredQueue queue5 = new LocalClusteredQueue(office5, 5, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor) pool.get(), null, tr);
+         LocalClusteredQueue queue5 = new LocalClusteredQueue(office5, 5, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor) pool.get(), -1, null, tr);
          Binding binding5 = office5.bindClusteredQueue(new SimpleCondition("queue1"), queue5);
 
          final int NUM_MESSAGES = 100;
@@ -558,12 +558,12 @@
 
          //Check the sizes
 
-         log.info("Here are the sizes:");
-         log.info("queue1, refs:" + queue1.memoryRefCount() + " dels:" + queue1.getDeliveringCount());
-         log.info("queue2, refs:" + queue2.memoryRefCount() + " dels:" + queue2.getDeliveringCount());
-         log.info("queue3, refs:" + queue3.memoryRefCount() + " dels:" + queue3.getDeliveringCount());
-         log.info("queue4, refs:" + queue4.memoryRefCount() + " dels:" + queue4.getDeliveringCount());
-         log.info("queue5, refs:" + queue5.memoryRefCount() + " dels:" + queue5.getDeliveringCount());
+         log.trace("Here are the sizes:");
+         log.trace("queue1, refs:" + queue1.memoryRefCount() + " dels:" + queue1.getDeliveringCount());
+         log.trace("queue2, refs:" + queue2.memoryRefCount() + " dels:" + queue2.getDeliveringCount());
+         log.trace("queue3, refs:" + queue3.memoryRefCount() + " dels:" + queue3.getDeliveringCount());
+         log.trace("queue4, refs:" + queue4.memoryRefCount() + " dels:" + queue4.getDeliveringCount());
+         log.trace("queue5, refs:" + queue5.memoryRefCount() + " dels:" + queue5.getDeliveringCount());
 
          assertEquals(NUM_MESSAGES, queue1.memoryRefCount());
          assertEquals(0, queue1.getDeliveringCount());
@@ -588,12 +588,12 @@
 
          Thread.sleep(7000);
 
-         log.info("Here are the sizes:");
-         log.info("queue1, refs:" + queue1.memoryRefCount() + " dels:" + queue1.getDeliveringCount());
-         log.info("queue2, refs:" + queue2.memoryRefCount() + " dels:" + queue2.getDeliveringCount());
-         log.info("queue3, refs:" + queue3.memoryRefCount() + " dels:" + queue3.getDeliveringCount());
-         log.info("queue4, refs:" + queue4.memoryRefCount() + " dels:" + queue4.getDeliveringCount());
-         log.info("queue5, refs:" + queue5.memoryRefCount() + " dels:" + queue5.getDeliveringCount());
+         log.trace("Here are the sizes:");
+         log.trace("queue1, refs:" + queue1.memoryRefCount() + " dels:" + queue1.getDeliveringCount());
+         log.trace("queue2, refs:" + queue2.memoryRefCount() + " dels:" + queue2.getDeliveringCount());
+         log.trace("queue3, refs:" + queue3.memoryRefCount() + " dels:" + queue3.getDeliveringCount());
+         log.trace("queue4, refs:" + queue4.memoryRefCount() + " dels:" + queue4.getDeliveringCount());
+         log.trace("queue5, refs:" + queue5.memoryRefCount() + " dels:" + queue5.getDeliveringCount());
 
          assertEquals(0, queue1.memoryRefCount());
          assertEquals(NUM_MESSAGES * 5, queue1.getDeliveringCount());
@@ -694,19 +694,19 @@
 
          office5 = (DefaultClusteredPostOffice) createClusteredPostOffice(5, "testgroup");
 
-         LocalClusteredQueue queue1 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor) pool.get(), null, tr);
+         LocalClusteredQueue queue1 = new LocalClusteredQueue(office1, 1, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor) pool.get(), -1, null, tr);
          Binding binding1 = office1.bindClusteredQueue(new SimpleCondition("queue1"), queue1);
 
-         LocalClusteredQueue queue2 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor) pool.get(), null, tr);
+         LocalClusteredQueue queue2 = new LocalClusteredQueue(office2, 2, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor) pool.get(), -1, null, tr);
          Binding binding2 = office2.bindClusteredQueue(new SimpleCondition("queue1"), queue2);
 
-         LocalClusteredQueue queue3 = new LocalClusteredQueue(office3, 3, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor) pool.get(), null, tr);
+         LocalClusteredQueue queue3 = new LocalClusteredQueue(office3, 3, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor) pool.get(), -1, null, tr);
          Binding binding3 = office3.bindClusteredQueue(new SimpleCondition("queue1"), queue3);
 
-         LocalClusteredQueue queue4 = new LocalClusteredQueue(office4, 4, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor) pool.get(), null, tr);
+         LocalClusteredQueue queue4 = new LocalClusteredQueue(office4, 4, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor) pool.get(), -1, null, tr);
          Binding binding4 = office4.bindClusteredQueue(new SimpleCondition("queue1"), queue4);
 
-         LocalClusteredQueue queue5 = new LocalClusteredQueue(office5, 5, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor) pool.get(), null, tr);
+         LocalClusteredQueue queue5 = new LocalClusteredQueue(office5, 5, "queue1", channelIDManager.getID(), ms, pm, true, recoverable, (QueuedExecutor) pool.get(), -1, null, tr);
          Binding binding5 = office5.bindClusteredQueue(new SimpleCondition("queue1"), queue5);
 
          final int NUM_MESSAGES = 100;
@@ -721,12 +721,12 @@
 
          //Check the sizes
 
-         log.info("Here are the sizes 1:");
-         log.info("queue1, refs:" + queue1.memoryRefCount() + " dels:" + queue1.getDeliveringCount());
-         log.info("queue2, refs:" + queue2.memoryRefCount() + " dels:" + queue2.getDeliveringCount());
-         log.info("queue3, refs:" + queue3.memoryRefCount() + " dels:" + queue3.getDeliveringCount());
-         log.info("queue4, refs:" + queue4.memoryRefCount() + " dels:" + queue4.getDeliveringCount());
-         log.info("queue5, refs:" + queue5.memoryRefCount() + " dels:" + queue5.getDeliveringCount());
+         log.trace("Here are the sizes 1:");
+         log.trace("queue1, refs:" + queue1.memoryRefCount() + " dels:" + queue1.getDeliveringCount());
+         log.trace("queue2, refs:" + queue2.memoryRefCount() + " dels:" + queue2.getDeliveringCount());
+         log.trace("queue3, refs:" + queue3.memoryRefCount() + " dels:" + queue3.getDeliveringCount());
+         log.trace("queue4, refs:" + queue4.memoryRefCount() + " dels:" + queue4.getDeliveringCount());
+         log.trace("queue5, refs:" + queue5.memoryRefCount() + " dels:" + queue5.getDeliveringCount());
 
          assertEquals(NUM_MESSAGES, queue1.memoryRefCount());
          assertEquals(0, queue1.getDeliveringCount());
@@ -810,26 +810,26 @@
          assertTrue(office4.getHoldingTransactions().isEmpty());
          assertTrue(office5.getHoldingTransactions().isEmpty());
 
-         log.info("Here are the sizes 2:");
-         log.info("queue1, refs:" + queue1.memoryRefCount() + " dels:" + queue1.getDeliveringCount());
-         log.info("queue2, refs:" + queue2.memoryRefCount() + " dels:" + queue2.getDeliveringCount());
-         log.info("queue3, refs:" + queue3.memoryRefCount() + " dels:" + queue3.getDeliveringCount());
-         log.info("queue4, refs:" + queue4.memoryRefCount() + " dels:" + queue4.getDeliveringCount());
-         log.info("queue5, refs:" + queue5.memoryRefCount() + " dels:" + queue5.getDeliveringCount());
+         log.trace("Here are the sizes 2:");
+         log.trace("queue1, refs:" + queue1.memoryRefCount() + " dels:" + queue1.getDeliveringCount());
+         log.trace("queue2, refs:" + queue2.memoryRefCount() + " dels:" + queue2.getDeliveringCount());
+         log.trace("queue3, refs:" + queue3.memoryRefCount() + " dels:" + queue3.getDeliveringCount());
+         log.trace("queue4, refs:" + queue4.memoryRefCount() + " dels:" + queue4.getDeliveringCount());
+         log.trace("queue5, refs:" + queue5.memoryRefCount() + " dels:" + queue5.getDeliveringCount());
 
          //Consume the rest from queue 5
          receiver5.setMaxRefs(NUM_MESSAGES - 25);
          queue5.deliver(false);
          Thread.sleep(5000);
 
-         log.info("receiver5 msgs:" + receiver5.getMessages().size());
+         log.trace("receiver5 msgs:" + receiver5.getMessages().size());
 
-         log.info("Here are the sizes 3:");
-         log.info("queue1, refs:" + queue1.memoryRefCount() + " dels:" + queue1.getDeliveringCount());
-         log.info("queue2, refs:" + queue2.memoryRefCount() + " dels:" + queue2.getDeliveringCount());
-         log.info("queue3, refs:" + queue3.memoryRefCount() + " dels:" + queue3.getDeliveringCount());
-         log.info("queue4, refs:" + queue4.memoryRefCount() + " dels:" + queue4.getDeliveringCount());
-         log.info("queue5, refs:" + queue5.memoryRefCount() + " dels:" + queue5.getDeliveringCount());
+         log.trace("Here are the sizes 3:");
+         log.trace("queue1, refs:" + queue1.memoryRefCount() + " dels:" + queue1.getDeliveringCount());
+         log.trace("queue2, refs:" + queue2.memoryRefCount() + " dels:" + queue2.getDeliveringCount());
+         log.trace("queue3, refs:" + queue3.memoryRefCount() + " dels:" + queue3.getDeliveringCount());
+         log.trace("queue4, refs:" + queue4.memoryRefCount() + " dels:" + queue4.getDeliveringCount());
+         log.trace("queue5, refs:" + queue5.memoryRefCount() + " dels:" + queue5.getDeliveringCount());
 
          //This will result in an extra one being pulled from queue1 - we cannot avoid this
          //This is because the channel does not know that the receiver is full unless it tries
@@ -864,18 +864,18 @@
 
          //Now consume 5 more from queue5, they should come from queue1 which has the most messages
 
-         log.info("Consume 5 more from queue 5");
+         log.trace("Consume 5 more from queue 5");
 
          receiver5.setMaxRefs(5);
          queue5.deliver(false);
          Thread.sleep(5000);
 
-         log.info("Here are the sizes 4:");
-         log.info("queue1, refs:" + queue1.memoryRefCount() + " dels:" + queue1.getDeliveringCount());
-         log.info("queue2, refs:" + queue2.memoryRefCount() + " dels:" + queue2.getDeliveringCount());
-         log.info("queue3, refs:" + queue3.memoryRefCount() + " dels:" + queue3.getDeliveringCount());
-         log.info("queue4, refs:" + queue4.memoryRefCount() + " dels:" + queue4.getDeliveringCount());
-         log.info("queue5, refs:" + queue5.memoryRefCount() + " dels:" + queue5.getDeliveringCount());
+         log.trace("Here are the sizes 4:");
+         log.trace("queue1, refs:" + queue1.memoryRefCount() + " dels:" + queue1.getDeliveringCount());
+         log.trace("queue2, refs:" + queue2.memoryRefCount() + " dels:" + queue2.getDeliveringCount());
+         log.trace("queue3, refs:" + queue3.memoryRefCount() + " dels:" + queue3.getDeliveringCount());
+         log.trace("queue4, refs:" + queue4.memoryRefCount() + " dels:" + queue4.getDeliveringCount());
+         log.trace("queue5, refs:" + queue5.memoryRefCount() + " dels:" + queue5.getDeliveringCount());
 
          assertEquals(NUM_MESSAGES - 11, queue1.memoryRefCount());
 
@@ -911,12 +911,12 @@
          queue5.deliver(false);
          Thread.sleep(2000);
 
-         log.info("Here are the sizes 5:");
-         log.info("queue1, refs:" + queue1.memoryRefCount() + " dels:" + queue1.getDeliveringCount());
-         log.info("queue2, refs:" + queue2.memoryRefCount() + " dels:" + queue2.getDeliveringCount());
-         log.info("queue3, refs:" + queue3.memoryRefCount() + " dels:" + queue3.getDeliveringCount());
-         log.info("queue4, refs:" + queue4.memoryRefCount() + " dels:" + queue4.getDeliveringCount());
-         log.info("queue5, refs:" + queue5.memoryRefCount() + " dels:" + queue5.getDeliveringCount());
+         log.trace("Here are the sizes 5:");
+         log.trace("queue1, refs:" + queue1.memoryRefCount() + " dels:" + queue1.getDeliveringCount());
+         log.trace("queue2, refs:" + queue2.memoryRefCount() + " dels:" + queue2.getDeliveringCount());
+         log.trace("queue3, refs:" + queue3.memoryRefCount() + " dels:" + queue3.getDeliveringCount());
+         log.trace("queue4, refs:" + queue4.memoryRefCount() + " dels:" + queue4.getDeliveringCount());
+         log.trace("queue5, refs:" + queue5.memoryRefCount() + " dels:" + queue5.getDeliveringCount());
 
          assertEquals(NUM_MESSAGES - 11, queue1.memoryRefCount());
          assertEquals(0, queue1.getDeliveringCount());
@@ -951,12 +951,12 @@
          queue4.deliver(false);
          Thread.sleep(7000);
 
-         log.info("Here are the sizes 6:");
-         log.info("queue1, refs:" + queue1.memoryRefCount() + " dels:" + queue1.getDeliveringCount());
-         log.info("queue2, refs:" + queue2.memoryRefCount() + " dels:" + queue2.getDeliveringCount());
-         log.info("queue3, refs:" + queue3.memoryRefCount() + " dels:" + queue3.getDeliveringCount());
-         log.info("queue4, refs:" + queue4.memoryRefCount() + " dels:" + queue4.getDeliveringCount());
-         log.info("queue5, refs:" + queue5.memoryRefCount() + " dels:" + queue5.getDeliveringCount());
+         log.trace("Here are the sizes 6:");
+         log.trace("queue1, refs:" + queue1.memoryRefCount() + " dels:" + queue1.getDeliveringCount());
+         log.trace("queue2, refs:" + queue2.memoryRefCount() + " dels:" + queue2.getDeliveringCount());
+         log.trace("queue3, refs:" + queue3.memoryRefCount() + " dels:" + queue3.getDeliveringCount());
+         log.trace("queue4, refs:" + queue4.memoryRefCount() + " dels:" + queue4.getDeliveringCount());
+         log.trace("queue5, refs:" + queue5.memoryRefCount() + " dels:" + queue5.getDeliveringCount());
 
          assertEquals(0, queue1.memoryRefCount());
          assertEquals(0, queue1.getDeliveringCount());
@@ -1060,9 +1060,9 @@
             return null;
          }
 
-         //log.info(this + " got ref");
+         //log.trace(this + " got ref");
 
-         //log.info("cnt:" + totalCount);
+         //log.trace("cnt:" + totalCount);
 
          SimpleDelivery del = new SimpleDelivery(observer, reference);
 

Modified: trunk/tests/src/org/jboss/test/messaging/jms/ConsumerClosedTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/ConsumerClosedTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/jms/ConsumerClosedTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -68,6 +68,9 @@
       cons.close();
 
       log.debug("consumer closed");
+      
+      //Need to sleep - cancelling back to queue is asynch and can take some time
+      Thread.sleep(500);
 
       // make sure that all messages are in queue
       ObjectName on =

Modified: trunk/tests/src/org/jboss/test/messaging/jms/DLQTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/DLQTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/jms/DLQTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -21,6 +21,9 @@
  */
 package org.jboss.test.messaging.jms;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import javax.jms.Connection;
 import javax.jms.ConnectionFactory;
 import javax.jms.DeliveryMode;
@@ -36,6 +39,7 @@
 import javax.naming.NameNotFoundException;
 
 import org.jboss.jms.destination.JBossQueue;
+import org.jboss.jms.server.endpoint.ServerSessionEndpoint;
 import org.jboss.test.messaging.MessagingTestCase;
 import org.jboss.test.messaging.tools.ServerManagement;
 
@@ -264,7 +268,6 @@
             
             conn = cf.createConnection();
             
-            log.info("I am setting dlq with " + overrideDLQObjectName);
             ServerManagement.setAttribute(new ObjectName(testQueueObjectName), "DLQ", overrideDLQObjectName);
             
             Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
@@ -364,9 +367,135 @@
    public void testWithReceiveTransactionalNonPersistent() throws Exception
    {
       testWithReceiveTransactional(false);
+   }   
+   
+   public void testHeadersSet() throws Exception
+   {
+      Connection conn = null;
+
+      ServerManagement.deployQueue("DLQ");
+
+      Queue dlq = (Queue)ic.lookup("/queue/DLQ");
+      
+      drainDestination(cf, dlq);
+      
+      ObjectName serverPeerObjectName = ServerManagement.getServerPeerObjectName();
+      
+      final int MAX_DELIVERIES = 16;
+      
+      final int NUM_MESSAGES = 5;      
+        
+      ServerManagement.setAttribute(serverPeerObjectName, "DefaultMaxDeliveryAttempts", String.valueOf(MAX_DELIVERIES));
+      
+      int maxRedeliveryAttempts =
+         ((Integer)ServerManagement.getAttribute(serverPeerObjectName, "DefaultMaxDeliveryAttempts")).intValue();
+      
+      assertEquals(MAX_DELIVERIES, maxRedeliveryAttempts);
+
+      try
+      {
+         conn = cf.createConnection();
+
+         Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+
+         MessageProducer prod = sess.createProducer(queue);
+         
+         Map origIds = new HashMap();         
+
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = sess.createTextMessage("Message:" + i);
+
+            prod.send(tm);
+            
+            origIds.put(tm.getText(), tm.getJMSMessageID());
+         }
+
+         Session sess2 = conn.createSession(true, Session.SESSION_TRANSACTED);
+
+         MessageConsumer cons = sess2.createConsumer(queue);
+
+         conn.start();
+
+         for (int i = 0; i < MAX_DELIVERIES; i++) 
+         {
+            for (int j = 0; j < NUM_MESSAGES; j++)
+            {
+               TextMessage tm = (TextMessage)cons.receive(1000);
+
+               assertNotNull(tm);
+
+               assertEquals("Message:" + j, tm.getText());
+            }
+
+            sess2.rollback();
+         }
+         
+         //At this point all the messages have been delivered exactly MAX_DELIVERIES times - this is ok
+         //they haven't exceeded max delivery attempts so shouldn't be in the DLQ - let's check
+         
+         MessageConsumer cons3 = sess.createConsumer(dlq);
+         
+         Message m = cons3.receive(1000);
+         
+         assertNull(m);
+         
+         //So let's try and consume them - this should cause them to go to the DLQ - since they will then exceed max
+         //delivery attempts
+         m = cons.receive(1000);
+         
+         assertNull(m);
+         
+         //All the messages should now be in the DLQ
+         
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = (TextMessage)cons3.receive(1000);
+            
+            assertNotNull(tm);
+
+            assertEquals("Message:" + i, tm.getText());
+            
+            //Check the headers
+            String origDest = tm.getStringProperty(ServerSessionEndpoint.JBOSS_MESSAGING_ORIG_DESTINATION);
+            
+            String origMessageId = tm.getStringProperty(ServerSessionEndpoint.JBOSS_MESSAGING_ORIG_MESSAGEID);
+            
+            assertEquals(queue.toString(), origDest);
+            
+            String origId = (String)origIds.get(tm.getText());
+            
+            assertEquals(origId, origMessageId);
+         }
+
+         //No more should be available
+         
+         m = cons.receive(1000);
+         
+         assertNull(m);
+         
+         cons.close();
+
+         MessageConsumer cons2 = sess2.createConsumer(queue);
+
+         m = cons2.receive(1000);
+
+         assertNull(m);
+      }
+      finally
+      {
+         ServerManagement.undeployQueue("DLQ");
+
+         if (conn != null) conn.close();
+      }
    }
 
-   public void testWithMessageListener(boolean persistent) throws Exception
+      
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+   
+   protected void testWithMessageListener(boolean persistent) throws Exception
    {
       Connection conn = null;
 
@@ -447,7 +576,7 @@
    }
    
 
-   public void testWithReceiveClientAck(boolean persistent) throws Exception
+   protected void testWithReceiveClientAck(boolean persistent) throws Exception
    {
       Connection conn = null;
 
@@ -556,7 +685,7 @@
       }
    }
    
-   public void testWithReceiveTransactional(boolean persistent) throws Exception
+   protected void testWithReceiveTransactional(boolean persistent) throws Exception
    {
       Connection conn = null;
 
@@ -664,11 +793,6 @@
       }
    }
 
-      
-   // Package protected ---------------------------------------------
-
-   // Protected -----------------------------------------------------
-
    protected void setUp() throws Exception
    {
       super.setUp();

Modified: trunk/tests/src/org/jboss/test/messaging/jms/DurableSubscriberTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/DurableSubscriberTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/jms/DurableSubscriberTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -21,6 +21,8 @@
   */
 package org.jboss.test.messaging.jms;
 
+import java.util.List;
+
 import javax.jms.Connection;
 import javax.jms.ConnectionFactory;
 import javax.jms.DeliveryMode;
@@ -39,6 +41,7 @@
 import javax.naming.InitialContext;
 import javax.naming.NamingException;
 
+import org.jboss.jms.server.destination.SubscriptionInfo;
 import org.jboss.test.messaging.MessagingTestCase;
 import org.jboss.test.messaging.tools.ServerManagement;
 
@@ -112,18 +115,28 @@
 
       ObjectName destObjectName =
          new ObjectName("jboss.messaging.destination:service=Topic,name=Topic");
-      String text = (String)ServerManagement.invoke(destObjectName, "listSubscriptionsAsText", null, null);
+      List subs = (List)ServerManagement.invoke(destObjectName, "listAllSubscriptions", null, null);
+      
+      assertNotNull(subs);
+      
+      assertEquals(1, subs.size());
+      
+      SubscriptionInfo info = (SubscriptionInfo)subs.get(0);
 
-      assertTrue(text.indexOf("monicabelucci") != -1);
+      assertEquals("monicabelucci", info.getName());
 
       prod.send(s.createTextMessage("k"));
 
       conn.close();
 
-      text = (String)ServerManagement.invoke(destObjectName, "listSubscriptionsAsText", null, null);
+      subs = (List)ServerManagement.invoke(destObjectName, "listAllSubscriptions", null, null);
 
-      assertTrue(text.indexOf("monicabelucci") != -1);
+      assertEquals(1, subs.size());
+      
+      info = (SubscriptionInfo)subs.get(0);
 
+      assertEquals("monicabelucci", info.getName());
+
       conn = cf.createConnection();
       conn.setClientID("brookeburke");
 
@@ -448,6 +461,10 @@
       conn.start();
 
       assertNull(ds.receive(1000));
+      
+      ds.close();
+      
+      s.unsubscribe("uzzi");
 
       conn.close();
    }
@@ -498,6 +515,8 @@
       }
          
       dursub.close();
+      
+      s.unsubscribe("dursub0");
 
       conn.close();
    }

Modified: trunk/tests/src/org/jboss/test/messaging/jms/ExpiryQueueTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/ExpiryQueueTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/jms/ExpiryQueueTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -21,6 +21,9 @@
  */
 package org.jboss.test.messaging.jms;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import javax.jms.Connection;
 import javax.jms.ConnectionFactory;
 import javax.jms.DeliveryMode;
@@ -37,6 +40,7 @@
 import javax.naming.NameNotFoundException;
 
 import org.jboss.jms.destination.JBossQueue;
+import org.jboss.jms.server.endpoint.ServerSessionEndpoint;
 import org.jboss.test.messaging.MessagingTestCase;
 import org.jboss.test.messaging.tools.ServerManagement;
 
@@ -352,6 +356,10 @@
          
          MessageConsumer sub3 = sess.createDurableSubscriber(topic, "sub3");
          
+         Map origIds = new HashMap();
+                           
+         long now = System.currentTimeMillis();
+         
          for (int i = 0; i < NUM_MESSAGES; i++)
          {
             TextMessage tm = sess.createTextMessage("Message:" + i);
@@ -359,8 +367,13 @@
             //Send messages with time to live of 3000 enough time to get to client consumer - so 
             //they won't be expired on the server side
             prod.send(tm, DeliveryMode.PERSISTENT, 4, 3000);
+            
+            origIds.put(tm.getText(), tm.getJMSMessageID());
          }
          
+         long approxExpiry = now + 3000;
+         
+                  
          //Now sleep. This wil give them enough time to expire
          
          Thread.sleep(3500);
@@ -389,8 +402,35 @@
                break;
             }
             
-            log.info("Got message: " + tm.getText());
+            //Check the headers
+            String origDest = tm.getStringProperty(ServerSessionEndpoint.JBOSS_MESSAGING_ORIG_DESTINATION);
+            
+            String origMessageId = tm.getStringProperty(ServerSessionEndpoint.JBOSS_MESSAGING_ORIG_MESSAGEID);
+            
+            long actualExpiryTime = tm.getLongProperty(ServerSessionEndpoint.JBOSS_MESSAGING_ACTUAL_EXPIRY_TIME);
+            
+            assertEquals(topic.toString(), origDest);
+            
+            String origId = (String)origIds.get(tm.getText());
+            
+            assertEquals(origId, origMessageId);
+            
+            assertTrue(actualExpiryTime >= approxExpiry);
          }
+         
+         cons2.close();
+         
+         sub1.close();
+         
+         sub2.close();
+         
+         sub3.close();
+         
+         sess.unsubscribe("sub1");
+         
+         sess.unsubscribe("sub2");
+         
+         sess.unsubscribe("sub3");
             
       }
       finally

Modified: trunk/tests/src/org/jboss/test/messaging/jms/MessageConsumerTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/MessageConsumerTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/jms/MessageConsumerTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -146,6 +146,61 @@
       super.tearDown();
    }
 
+   
+   public void testReceiveWithClientAckThenCloseSession() throws Exception
+   {
+      Connection conn = null;
+      
+      try
+      {
+         conn = cf.createConnection();
+         
+         Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         
+         MessageProducer prod = sess.createProducer(queue);
+         
+         final int NUM_MESSAGES = 5;
+         
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = sess.createTextMessage("message" + i);
+            
+            prod.send(tm);
+         }
+         
+         Session sess2 = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+         
+         MessageConsumer cons = sess2.createConsumer(queue);
+         
+         conn.start();
+         
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = (TextMessage)cons.receive(500);
+            
+            assertNotNull(tm);
+            
+            assertEquals("message" + i, tm.getText());
+         }
+         
+         //Now close the session
+ 
+         long now = System.currentTimeMillis();
+         
+         sess2.close();
+         
+      }
+      finally
+      {
+         if (conn != null)
+         {
+            conn.close();
+         }
+      }
+       
+   }
+   
+   
    public void testRelayMessage() throws Exception
    {
       Connection conn = cf.createConnection();

Modified: trunk/tests/src/org/jboss/test/messaging/jms/MessageProducerTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/MessageProducerTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/jms/MessageProducerTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -166,6 +166,42 @@
          cconn.close();
       }
    }
+   
+   //I moved this into it's own class so we can catch any exception that occurs
+   //Since this test intermittently fails.
+   //(As an aside, technically this test is invalid anyway since the sessions is used for sending
+   //and consuming concurrently - and sessions are supposed to be single threaded)
+   private class Sender implements Runnable
+   {
+      volatile Exception ex;
+      
+      MessageProducer prod;
+      
+      Message m;
+      
+      Sender(MessageProducer prod, Message m)
+      {
+         this.prod = prod;
+         
+         this.m = m;
+      }
+      
+      public void run()
+      {
+         try
+         {
+            // this is needed to make sure the main thread has enough time to block
+            Thread.sleep(3000);
+            prod.send(m);
+         }
+         catch(Exception e)
+         {
+            log.error(e);
+            
+            ex = e;
+         }
+      }
+   }
 
    public void testPersistentSendToTopic() throws Exception
    {
@@ -182,28 +218,21 @@
 
          cconn.start();
 
-         final TextMessage m1 = ps.createTextMessage("test");
+         TextMessage m1 = ps.createTextMessage("test");
+          
+         Sender sender = new Sender(p, m1);
 
-         Thread t = new Thread(new Runnable()
-         {
-            public void run()
-            {
-               try
-               {
-                  // this is needed to make sure the main thread has enough time to block
-                  Thread.sleep(3000);
-                  p.send(m1);
-               }
-               catch(Exception e)
-               {
-                  log.error(e);
-               }
-            }
-         }, "Producer Thread");
+         Thread t = new Thread(sender, "Producer Thread");
 
          t.start();
 
          TextMessage m2 = (TextMessage)c.receive(8000);
+         
+         if (sender.ex != null)
+         {
+            //If an exception was caught in sending we rethrow here so as not to lose it
+            throw sender.ex;
+         }
 
          assertEquals(m2.getJMSMessageID(), m1.getJMSMessageID());
          assertEquals("test", m2.getText());

Modified: trunk/tests/src/org/jboss/test/messaging/jms/MiscellaneousTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/MiscellaneousTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/jms/MiscellaneousTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -242,6 +242,7 @@
             }
             catch(Exception e)
             {
+               e.printStackTrace();
                result.setFailure(e);
             }
          }

Added: trunk/tests/src/org/jboss/test/messaging/jms/ScheduledDeliveryTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/ScheduledDeliveryTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/jms/ScheduledDeliveryTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -0,0 +1,568 @@
+/*
+ * 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.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+import javax.jms.Topic;
+import javax.management.ObjectName;
+import javax.naming.InitialContext;
+
+import org.jboss.jms.message.JBossMessage;
+import org.jboss.test.messaging.MessagingTestCase;
+import org.jboss.test.messaging.tools.ServerManagement;
+
+/**
+ * 
+ * A ScheduledDeliveryTest
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ * @version <tt>$Revision: 1.1 $</tt>
+ *
+ * $Id$
+ *
+ */
+public class ScheduledDeliveryTest extends MessagingTestCase
+{
+   // Constants -----------------------------------------------------
+
+   // Static --------------------------------------------------------
+
+   // Attributes ----------------------------------------------------
+
+   protected InitialContext ic;
+   protected ConnectionFactory cf;
+   protected Queue queue;
+   protected Topic topic;
+
+   // Constructors --------------------------------------------------
+
+   public ScheduledDeliveryTest(String name)
+   {
+      super(name);
+   }
+
+   // Public --------------------------------------------------------
+   
+   public void testScheduledDelivery() throws Exception
+   {
+      Connection conn = null;
+      
+      try
+      {
+         conn = cf.createConnection();
+         
+         Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         
+         MessageProducer prod = sess.createProducer(queue);
+         
+         MessageConsumer cons = sess.createConsumer(queue);
+         
+         conn.start();
+         
+         //Send one scheduled
+         
+         long now = System.currentTimeMillis();
+         
+         TextMessage tm1 = sess.createTextMessage("testScheduled1");      
+         tm1.setLongProperty(JBossMessage.JMS_JBOSS_SCHEDULED_DELIVERY_PROP_NAME, now + 7000);
+         prod.send(tm1);
+ 
+         //First send some non scheduled messages
+         
+         TextMessage tm2 = sess.createTextMessage("testScheduled2");
+         prod.send(tm2);
+
+         TextMessage tm3 = sess.createTextMessage("testScheduled3");
+         prod.send(tm3);
+
+         TextMessage tm4 = sess.createTextMessage("testScheduled4");
+         prod.send(tm4);
+
+         
+         //Now send some more scheduled messages   
+         
+         TextMessage tm5 = sess.createTextMessage("testScheduled5");      
+         tm5.setLongProperty(JBossMessage.JMS_JBOSS_SCHEDULED_DELIVERY_PROP_NAME, now + 5000);
+         prod.send(tm5);
+         
+         TextMessage tm6 = sess.createTextMessage("testScheduled6");      
+         tm6.setLongProperty(JBossMessage.JMS_JBOSS_SCHEDULED_DELIVERY_PROP_NAME, now + 4000);
+         prod.send(tm6);
+   
+         TextMessage tm7 = sess.createTextMessage("testScheduled7");      
+         tm7.setLongProperty(JBossMessage.JMS_JBOSS_SCHEDULED_DELIVERY_PROP_NAME, now + 3000);
+         prod.send(tm7);
+
+         TextMessage tm8 = sess.createTextMessage("testScheduled8");      
+         tm8.setLongProperty(JBossMessage.JMS_JBOSS_SCHEDULED_DELIVERY_PROP_NAME, now + 6000);
+         prod.send(tm8);
+
+         //And one scheduled with a -ve number
+         
+         TextMessage tm9 = sess.createTextMessage("testScheduled9");      
+         tm8.setLongProperty(JBossMessage.JMS_JBOSS_SCHEDULED_DELIVERY_PROP_NAME, -3);
+         prod.send(tm9);
+ 
+         //First the non scheduled messages should be received
+         
+         TextMessage rm1 = (TextMessage)cons.receive(250);      
+         assertNotNull(rm1);      
+         assertEquals(tm2.getText(), rm1.getText());
+         
+         TextMessage rm2 = (TextMessage)cons.receive(250);      
+         assertNotNull(rm2);      
+         assertEquals(tm3.getText(), rm2.getText());
+         
+         TextMessage rm3 = (TextMessage)cons.receive(250);      
+         assertNotNull(rm3);      
+         assertEquals(tm4.getText(), rm3.getText());
+         
+         //Now the one with a scheduled with a -ve number
+         TextMessage rm5 = (TextMessage)cons.receive(250);      
+         assertNotNull(rm5);      
+         assertEquals(tm9.getText(), rm5.getText());
+         
+         //Now the scheduled
+         TextMessage rm6 = (TextMessage)cons.receive(3250);      
+         assertNotNull(rm6);      
+         assertEquals(tm7.getText(), rm6.getText());
+         
+         long now2 = System.currentTimeMillis();
+         
+         assertTrue(now2 - now >= 3000);
+         
+         
+         TextMessage rm7 = (TextMessage)cons.receive(1250);      
+         assertNotNull(rm7);      
+         assertEquals(tm6.getText(), rm7.getText());
+         
+         now2 = System.currentTimeMillis();
+         
+         assertTrue(now2 - now >= 4000);
+         
+         
+         TextMessage rm8 = (TextMessage)cons.receive(1250);      
+         assertNotNull(rm8);      
+         assertEquals(tm5.getText(), rm8.getText());
+         
+         now2 = System.currentTimeMillis();
+         
+         assertTrue(now2 - now >= 5000);
+         
+         
+         TextMessage rm9 = (TextMessage)cons.receive(1250);      
+         assertNotNull(rm9);      
+         assertEquals(tm8.getText(), rm9.getText());
+         
+         now2 = System.currentTimeMillis();
+         
+         assertTrue(now2 - now >= 6000);
+         
+         
+         TextMessage rm10 = (TextMessage)cons.receive(1250);      
+         assertNotNull(rm10);      
+         assertEquals(tm1.getText(), rm10.getText());
+         
+         now2 = System.currentTimeMillis();
+         
+         assertTrue(now2 - now >= 7000);
+         
+         Message m = cons.receive(1000);
+         
+         assertNull(m);
+      }
+      finally
+      {
+         if (conn != null)
+         {
+            conn.close();
+         }
+      }           
+   }
+   
+   
+   public void testScheduledDeliveryWithRestart() throws Exception
+   {
+      Connection conn = null;
+      
+      try
+      {
+         conn = cf.createConnection();
+         
+         Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         
+         MessageProducer prod = sess.createProducer(queue);
+         
+         //Send one scheduled
+         
+         long now = System.currentTimeMillis();
+         
+         TextMessage tm1 = sess.createTextMessage("testScheduled1");      
+         tm1.setLongProperty(JBossMessage.JMS_JBOSS_SCHEDULED_DELIVERY_PROP_NAME, now + 7000);
+         prod.send(tm1);
+ 
+         //First send some non scheduled messages
+         
+         TextMessage tm2 = sess.createTextMessage("testScheduled2");
+         prod.send(tm2);
+
+         TextMessage tm3 = sess.createTextMessage("testScheduled3");
+         prod.send(tm3);
+
+         TextMessage tm4 = sess.createTextMessage("testScheduled4");
+         prod.send(tm4);
+
+         
+         //Now send some more scheduled messages   
+         
+         TextMessage tm5 = sess.createTextMessage("testScheduled5");      
+         tm5.setLongProperty(JBossMessage.JMS_JBOSS_SCHEDULED_DELIVERY_PROP_NAME, now + 5000);
+         prod.send(tm5);
+         
+         TextMessage tm6 = sess.createTextMessage("testScheduled6");      
+         tm6.setLongProperty(JBossMessage.JMS_JBOSS_SCHEDULED_DELIVERY_PROP_NAME, now + 4000);
+         prod.send(tm6);
+   
+         TextMessage tm7 = sess.createTextMessage("testScheduled7");      
+         tm7.setLongProperty(JBossMessage.JMS_JBOSS_SCHEDULED_DELIVERY_PROP_NAME, now + 3000);
+         prod.send(tm7);
+
+         TextMessage tm8 = sess.createTextMessage("testScheduled8");      
+         tm8.setLongProperty(JBossMessage.JMS_JBOSS_SCHEDULED_DELIVERY_PROP_NAME, now + 6000);
+         prod.send(tm8);
+
+         //And one scheduled with a -ve number
+         
+         TextMessage tm9 = sess.createTextMessage("testScheduled9");      
+         tm8.setLongProperty(JBossMessage.JMS_JBOSS_SCHEDULED_DELIVERY_PROP_NAME, -3);
+         prod.send(tm9);
+         
+         //Now stop the server and restart it
+         
+         conn.close();
+         
+         ServerManagement.stopServerPeer();
+         
+         ServerManagement.startServerPeer();
+         
+         // Messaging server restart implies new ConnectionFactory lookup
+         cf = (ConnectionFactory)ic.lookup("/ConnectionFactory");
+
+         ServerManagement.deployQueue("Queue");
+         
+         conn = cf.createConnection();
+         
+         conn.start();
+         
+         sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         
+         MessageConsumer cons = sess.createConsumer(queue);
+ 
+         //First the non scheduled messages should be received
+         
+         TextMessage rm1 = (TextMessage)cons.receive(250);      
+         assertNotNull(rm1);      
+         assertEquals(tm2.getText(), rm1.getText());
+         
+         TextMessage rm2 = (TextMessage)cons.receive(250);      
+         assertNotNull(rm2);      
+         assertEquals(tm3.getText(), rm2.getText());
+         
+         TextMessage rm3 = (TextMessage)cons.receive(250);      
+         assertNotNull(rm3);      
+         assertEquals(tm4.getText(), rm3.getText());
+         
+         //Now the one with a scheduled with a -ve number
+         TextMessage rm5 = (TextMessage)cons.receive(250);      
+         assertNotNull(rm5);      
+         assertEquals(tm9.getText(), rm5.getText());
+         
+         //Now the scheduled
+         TextMessage rm6 = (TextMessage)cons.receive(3250);      
+         assertNotNull(rm6);      
+         assertEquals(tm7.getText(), rm6.getText());
+         
+         long now2 = System.currentTimeMillis();
+         
+         assertTrue(now2 - now >= 3000);
+         
+         
+         TextMessage rm7 = (TextMessage)cons.receive(1250);      
+         assertNotNull(rm7);      
+         assertEquals(tm6.getText(), rm7.getText());
+         
+         now2 = System.currentTimeMillis();
+         
+         assertTrue(now2 - now >= 4000);
+         
+         
+         TextMessage rm8 = (TextMessage)cons.receive(1250);      
+         assertNotNull(rm8);      
+         assertEquals(tm5.getText(), rm8.getText());
+         
+         now2 = System.currentTimeMillis();
+         
+         assertTrue(now2 - now >= 5000);
+         
+         
+         TextMessage rm9 = (TextMessage)cons.receive(1250);      
+         assertNotNull(rm9);      
+         assertEquals(tm8.getText(), rm9.getText());
+         
+         now2 = System.currentTimeMillis();
+         
+         assertTrue(now2 - now >= 6000);
+         
+         
+         TextMessage rm10 = (TextMessage)cons.receive(1250);      
+         assertNotNull(rm10);      
+         assertEquals(tm1.getText(), rm10.getText());
+         
+         now2 = System.currentTimeMillis();
+         
+         assertTrue(now2 - now >= 7000);
+         
+         Message m = cons.receive(1000);
+         
+         assertNull(m);
+      }
+      finally
+      {
+         if (conn != null)
+         {
+            conn.close();
+         }
+      }           
+   }
+   
+   public void testDelayedRedeliveryDefault() throws Exception
+   {   
+      ObjectName serverPeerObjectName = ServerManagement.getServerPeerObjectName();
+      
+      String queueObjectName = "jboss.messaging.destination:service=Queue,name=Queue";
+      
+      ServerManagement.setAttribute(new ObjectName(queueObjectName), "RedeliveryDelay", String.valueOf(0));
+      
+      final long delay = 3000;
+      
+      ServerManagement.setAttribute(serverPeerObjectName, "DefaultRedeliveryDelay", String.valueOf(delay));
+      
+      Connection conn = null;
+      
+      try
+      {
+         conn = cf.createConnection();
+         
+         Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         
+         MessageProducer prod = sess.createProducer(queue);
+         
+         final int NUM_MESSAGES = 5;
+         
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = sess.createTextMessage("message" + i);
+            
+            prod.send(tm);
+         }
+         
+         Session sess2 = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+         
+         MessageConsumer cons = sess2.createConsumer(queue);
+         
+         conn.start();
+         
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = (TextMessage)cons.receive(500);
+            
+            assertNotNull(tm);
+            
+            assertEquals("message" + i, tm.getText());
+         }
+         
+         //Now close the session
+         //This should cancel back to the queue with a delayed redelivery
+         
+         long now = System.currentTimeMillis();
+         
+         sess2.close();
+         
+         Session sess3 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         
+         MessageConsumer cons2 = sess3.createConsumer(queue);
+         
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = (TextMessage)cons2.receive(delay + 500);
+            
+            long time = System.currentTimeMillis();
+            
+            assertTrue(time - now >= delay);
+            assertTrue(time - now < delay + 250);
+            
+            assertNotNull(tm);
+         }
+         
+         TextMessage tm = (TextMessage)cons2.receive(500);
+         
+         assertNull(tm);
+      }
+      finally
+      {
+         if (conn != null)
+         {
+            conn.close();
+         }
+      }
+   }
+   
+   public void testDelayedRedeliveryOverride() throws Exception
+   {   
+      ObjectName serverPeerObjectName = ServerManagement.getServerPeerObjectName();
+      
+      String queueObjectName = "jboss.messaging.destination:service=Queue,name=Queue";
+      
+      final long delay = 3000;
+            
+      ServerManagement.setAttribute(new ObjectName(queueObjectName), "RedeliveryDelay", String.valueOf(delay));
+        
+      ServerManagement.setAttribute(serverPeerObjectName, "DefaultRedeliveryDelay", String.valueOf(delay * 3));
+      
+      Connection conn = null;
+      
+      try
+      {
+         conn = cf.createConnection();
+         
+         Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         
+         MessageProducer prod = sess.createProducer(queue);
+         
+         final int NUM_MESSAGES = 5;
+         
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = sess.createTextMessage("message" + i);
+            
+            prod.send(tm);
+         }
+         
+         Session sess2 = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+         
+         MessageConsumer cons = sess2.createConsumer(queue);
+         
+         conn.start();
+         
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = (TextMessage)cons.receive(500);
+            
+            assertNotNull(tm);
+            
+            assertEquals("message" + i, tm.getText());
+         }
+         
+         //Now close the session
+         //This should cancel back to the queue with a delayed redelivery
+         
+         long now = System.currentTimeMillis();
+         
+         sess2.close();
+         
+         Session sess3 = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         
+         MessageConsumer cons2 = sess3.createConsumer(queue);
+         
+         for (int i = 0; i < NUM_MESSAGES; i++)
+         {
+            TextMessage tm = (TextMessage)cons2.receive(delay + 500);
+            
+            long time = System.currentTimeMillis();
+            
+            assertTrue(time - now >= delay);
+            assertTrue(time - now < delay + 250);
+            
+            assertNotNull(tm);
+         }
+         
+         TextMessage tm = (TextMessage)cons2.receive(500);
+         
+         assertNull(tm);
+      }
+      finally
+      {
+         if (conn != null)
+         {
+            conn.close();
+         }
+      }
+   }
+
+      
+   // Package protected ---------------------------------------------
+
+   // Protected -----------------------------------------------------
+
+   protected void setUp() throws Exception
+   {
+      super.setUp();
+
+      ServerManagement.start("all");
+
+      ic = new InitialContext(ServerManagement.getJNDIEnvironment());
+
+      cf = (ConnectionFactory)ic.lookup("/ConnectionFactory");
+
+      ServerManagement.deployQueue("Queue");
+      
+      ServerManagement.deployTopic("Topic");
+
+      queue = (Queue)ic.lookup("/queue/Queue");
+      
+      topic = (Topic)ic.lookup("/topic/Topic");
+
+   }
+
+   protected void tearDown() throws Exception
+   {
+      super.tearDown();
+
+      ServerManagement.undeployQueue("Queue");
+      
+      ServerManagement.undeployTopic("Topic");
+
+      if (ic != null) ic.close();
+   }
+
+   // Private -------------------------------------------------------
+
+   // Inner classes -------------------------------------------------
+   
+}

Modified: trunk/tests/src/org/jboss/test/messaging/jms/SessionTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/SessionTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/jms/SessionTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -523,6 +523,9 @@
       session.close();
 
       // JMS 1.1 4.4.1: "Closing a transacted session must roll back its transaction in progress"
+      
+      //Cancelling is asynch so may take a little while
+      Thread.sleep(500);
 
       mc = (Integer)ServerManagement.getAttribute(on, "MessageCount");
       assertEquals(1, mc.intValue());

Modified: trunk/tests/src/org/jboss/test/messaging/jms/TransactedSessionTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/TransactedSessionTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/jms/TransactedSessionTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -124,6 +124,10 @@
       assertEquals(2, m.getIntProperty("JMSXDeliveryCount"));
 
       conn.close();
+      
+      //Need to pause a little while - cancelling back to the queue is async
+      
+      Thread.sleep(500);
 
       ObjectName on = new ObjectName("jboss.messaging.destination:service=Queue,name=Queue");
       Integer i = (Integer)ServerManagement.getAttribute(on, "MessageCount");
@@ -574,8 +578,6 @@
 
          assertEquals("a message", tm.getText());
          
-         log.info("del count1:" + tm.getIntProperty("JMSXDeliveryCount"));
-
          assertFalse(tm.getJMSRedelivered());
          assertEquals(1, tm.getIntProperty("JMSXDeliveryCount"));
 

Modified: trunk/tests/src/org/jboss/test/messaging/jms/XATest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/XATest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/jms/XATest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -98,6 +98,8 @@
       ServerManagement.undeployQueue("Queue");
       ServerManagement.deployQueue("Queue");
       queue = (Destination)initialContext.lookup("/queue/Queue");
+      
+      drainDestination(cf, queue);
 
 
       if (!ServerManagement.isRemote())
@@ -138,6 +140,340 @@
 
    // Public --------------------------------------------------------
    
+   
+
+   //http://jira.jboss.com/jira/browse/JBMESSAGING-721
+   public void testConvertFromLocalTx() throws Exception
+   {
+      if (ServerManagement.isRemote()) return;
+      
+      Connection conn = null;
+      
+      XAConnection xaConn = null;
+      
+      try
+      {
+      
+         //First send some messages to a queue
+         
+         conn = cf.createConnection();
+         
+         Session sessSend = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         
+         MessageProducer prod = sessSend.createProducer(queue);
+         
+         TextMessage tm1 = sessSend.createTextMessage("message1");
+         
+         TextMessage tm2 = sessSend.createTextMessage("message2");
+         
+         prod.send(tm1);
+         
+         prod.send(tm2);
+         
+         
+         xaConn = cf.createXAConnection();
+         
+         XASession xaSession = xaConn.createXASession();
+         
+         xaConn.start();
+         
+         MessageConsumer cons = xaSession.createConsumer(queue);
+         
+         //Receive the two messages outside of a transaction
+         
+         TextMessage rm1 = (TextMessage)cons.receive(1000);
+         
+         assertNotNull(rm1);
+         
+         assertEquals("message1", rm1.getText());
+         
+         TextMessage rm2 = (TextMessage)cons.receive(1000);
+         
+         assertNotNull(rm2);
+         
+         assertEquals("message2", rm2.getText());
+         
+         Message rm3 = cons.receive(1000);
+         
+         assertNull(rm3);
+         
+         //Now we enlist the session in an xa transaction
+         
+         XAResource res = xaSession.getXAResource();
+         
+         tm.begin();
+         
+         Transaction tx = tm.getTransaction();
+         tx.enlistResource(res);
+         
+         //This should cause the work done previously to be converted into work done in the xa transaction
+         //this is what an MDB does
+         //There is a difficulty in transactional delivery with an MDB.
+         //The message is received from the destination and then sent to the mdb container so
+         //it can call onMessage.
+         //For transactional delivery the receipt of the message should be in a transaction but by the time
+         //the mdb container is invoked the message has already been received it is too late - the message
+         //has already been received and passed on (see page 199 (chapter 5 JMS and Transactions, section "Application Server Integration"
+         //of Mark Little's book Java Transaction processing
+         //for a discussion of how different app serves deal with this)
+         //The way jboss messaging (and jboss mq) deals with this is to convert any work done
+         //prior to when the xasession is enlisted in the tx, into work done in the xa tx
+         
+         //Now rollback the tx - this should cause redelivery of the two messages
+         tx.rollback();
+         
+         rm1 = (TextMessage)cons.receive(1000);
+         
+         assertNotNull(rm1);
+         
+         assertEquals("message1", rm1.getText());
+         
+         rm2 = (TextMessage)cons.receive(1000);
+         
+         assertNotNull(rm2);
+         
+         assertEquals("message2", rm2.getText());
+         
+         rm3 = cons.receive(1000);
+         
+         assertNull(rm3);
+      }
+      finally
+      {         
+         if (conn != null)
+         {
+            conn.close();
+         }
+         
+         if (xaConn != null)
+         {
+            xaConn.close();
+         }
+      }
+   }
+   
+   //http://jira.jboss.com/jira/browse/JBMESSAGING-721
+   public void testTransactionIdSetAfterCommit() throws Exception
+   {
+      if (ServerManagement.isRemote()) return;
+      
+      Connection conn = null;
+      
+      XAConnection xaConn = null;
+      
+      try
+      {
+      
+         //First send some messages to a queue
+         
+         conn = cf.createConnection();
+         
+         Session sessSend = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         
+         MessageProducer prod = sessSend.createProducer(queue);
+         
+         TextMessage tm1 = sessSend.createTextMessage("message1");
+         
+         TextMessage tm2 = sessSend.createTextMessage("message2");
+         
+         prod.send(tm1);
+         
+         prod.send(tm2);
+         
+         
+         xaConn = cf.createXAConnection();
+         
+         XASession xaSession = xaConn.createXASession();
+         
+         xaConn.start();
+         
+         MessageConsumer cons = xaSession.createConsumer(queue);
+         
+         //Now we enlist the session in an xa transaction
+         
+         XAResource res = xaSession.getXAResource();
+         
+         tm.begin();
+         
+         Transaction tx = tm.getTransaction();
+         tx.enlistResource(res);
+         
+         //Then we do a commit
+         tm.commit();
+         
+         //And enlist again
+         
+         tx = tm.getTransaction();
+         
+
+         tm.begin();
+         
+         tx = tm.getTransaction();
+         tx.enlistResource(res);
+                  
+         //Then we receive the messages
+         
+         TextMessage rm1 = (TextMessage)cons.receive(1000);
+         
+         assertNotNull(rm1);
+         
+         assertEquals("message1", rm1.getText());
+         
+         TextMessage rm2 = (TextMessage)cons.receive(1000);
+         
+         assertNotNull(rm2);
+         
+         assertEquals("message2", rm2.getText());
+         
+         Message rm3 = cons.receive(1000);
+         
+         assertNull(rm3);
+               
+         //Now rollback the tx - this should cause redelivery of the two messages
+         tx.rollback();
+         
+         rm1 = (TextMessage)cons.receive(1000);
+         
+         assertNotNull(rm1);
+         
+         assertEquals("message1", rm1.getText());
+         
+         rm2 = (TextMessage)cons.receive(1000);
+         
+         assertNotNull(rm2);
+         
+         assertEquals("message2", rm2.getText());
+         
+         rm3 = cons.receive(1000);
+         
+         assertNull(rm3);
+      }
+      finally
+      {         
+         if (conn != null)
+         {
+            conn.close();
+         }
+         
+         if (xaConn != null)
+         {
+            xaConn.close();
+         }
+      }
+
+   }
+   
+   //http://jira.jboss.com/jira/browse/JBMESSAGING-721
+   public void testTransactionIdSetAfterRollback() throws Exception
+   {
+      if (ServerManagement.isRemote()) return;
+      
+      Connection conn = null;
+      
+      XAConnection xaConn = null;
+      
+      try
+      {
+      
+         //First send some messages to a queue
+         
+         conn = cf.createConnection();
+         
+         Session sessSend = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         
+         MessageProducer prod = sessSend.createProducer(queue);
+         
+         TextMessage tm1 = sessSend.createTextMessage("message1");
+         
+         TextMessage tm2 = sessSend.createTextMessage("message2");
+         
+         prod.send(tm1);
+         
+         prod.send(tm2);
+         
+         
+         xaConn = cf.createXAConnection();
+         
+         XASession xaSession = xaConn.createXASession();
+         
+         xaConn.start();
+         
+         MessageConsumer cons = xaSession.createConsumer(queue);
+         
+         //Now we enlist the session in an xa transaction
+         
+         XAResource res = xaSession.getXAResource();
+         
+         tm.begin();
+         
+         Transaction tx = tm.getTransaction();
+         tx.enlistResource(res);
+         
+         //Then we do a rollback
+         tm.rollback();
+         
+         tm.begin();
+                  
+         //And enlist again
+         
+         tx = tm.getTransaction();
+         tx.enlistResource(res);
+
+         //Then we receive the messages
+         
+         TextMessage rm1 = (TextMessage)cons.receive(1000);
+         
+         assertNotNull(rm1);
+         
+         assertEquals("message1", rm1.getText());
+         
+         TextMessage rm2 = (TextMessage)cons.receive(1000);
+         
+         assertNotNull(rm2);
+         
+         assertEquals("message2", rm2.getText());
+         
+         Message rm3 = cons.receive(1000);
+         
+         assertNull(rm3);
+               
+         //Now rollback the tx - this should cause redelivery of the two messages
+         tx.rollback();
+         
+         rm1 = (TextMessage)cons.receive(1000);
+         
+         assertNotNull(rm1);
+         
+         assertEquals("message1", rm1.getText());
+         
+         rm2 = (TextMessage)cons.receive(1000);
+         
+         assertNotNull(rm2);
+         
+         assertEquals("message2", rm2.getText());
+         
+         rm3 = cons.receive(1000);
+         
+         assertNull(rm3);
+      }
+      finally
+      {         
+         if (conn != null)
+         {
+            conn.close();
+         }
+         
+         if (xaConn != null)
+         {
+            xaConn.close();
+         }
+      }
+
+   }
+   
+   
+   
+   
    public void test2PCSendCommit1PCOptimization() throws Exception
    {
       if (ServerManagement.isRemote()) return;

Modified: trunk/tests/src/org/jboss/test/messaging/jms/message/JMSExpirationHeaderTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/message/JMSExpirationHeaderTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/jms/message/JMSExpirationHeaderTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -318,7 +318,7 @@
       
       List list = (List)ServerManagement.invoke(
             destObjectName, 
-            "listMessages", 
+            "listAllMessages", 
             new Object[] {null}, 
             new String[] {"java.lang.String"});
       assertNotNull(list);

Modified: trunk/tests/src/org/jboss/test/messaging/jms/message/MessageTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/message/MessageTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/jms/message/MessageTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -596,8 +596,6 @@
       double myDouble = Double.MAX_VALUE - 72387633;
       String myString = "abcdef&^*&!^ghijkl";
 
-
-
       m1.setBooleanProperty("myBool", myBool);
       m1.setByteProperty("myByte", myByte);
       m1.setShortProperty("myShort", myShort);
@@ -698,8 +696,6 @@
       }
       catch (MessageNotWriteableException e) {}
 
-
-
       assertTrue(m2.propertyExists("myBool"));
       assertTrue(m2.propertyExists("myByte"));
       assertTrue(m2.propertyExists("myShort"));
@@ -709,7 +705,6 @@
       assertTrue(m2.propertyExists("myDouble"));
       assertTrue(m2.propertyExists("myString"));
 
-
       assertFalse(m2.propertyExists("sausages"));
 
       HashSet propNames = new HashSet();

Modified: trunk/tests/src/org/jboss/test/messaging/jms/server/ServerPeerTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/server/ServerPeerTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/jms/server/ServerPeerTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -21,12 +21,32 @@
   */
 package org.jboss.test.messaging.jms.server;
 
+import java.util.Iterator;
+import java.util.List;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
 import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TemporaryQueue;
+import javax.jms.TextMessage;
 import javax.jms.Topic;
+import javax.jms.XAConnection;
+import javax.jms.XAConnectionFactory;
+import javax.jms.XASession;
+import javax.management.ObjectName;
 import javax.naming.Context;
 import javax.naming.InitialContext;
 import javax.naming.NameNotFoundException;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+import org.jboss.jms.server.messagecounter.MessageCounter;
+import org.jboss.jms.server.messagecounter.MessageStatistics;
 import org.jboss.jms.util.MessagingJMSException;
+import org.jboss.messaging.core.tx.XidImpl;
 import org.jboss.test.messaging.MessagingTestCase;
 import org.jboss.test.messaging.tools.ServerManagement;
 
@@ -154,7 +174,428 @@
       }
    }
 
+   //Full DLQ functionality is tested in DLQTest
+   public void testSetGetDefaultDLQ() throws Exception
+   {
+      if(!ServerManagement.isServerPeerStarted())
+      {
+         ServerManagement.startServerPeer();
+      }
+            
+      ObjectName on = new ObjectName("jboss.messaging.destination:service=Queue,name=DefaultDLQ");
+      
+      ServerManagement.setAttribute(ServerManagement.getServerPeerObjectName(), "DefaultDLQ", on.toString());
+      
+      ObjectName defaultDLQ =
+         (ObjectName)ServerManagement.getAttribute(ServerManagement.getServerPeerObjectName(), "DefaultDLQ");
 
+      assertEquals(on, defaultDLQ);
+   }
+   
+   //Full Expiry Queue functionality is tested in ExpiryQueueTest
+   public void testSetGetDefaultExpiryQueue() throws Exception
+   {
+      if(!ServerManagement.isServerPeerStarted())
+      {
+         ServerManagement.startServerPeer();
+      }
+            
+      ObjectName on = new ObjectName("jboss.messaging.destination:service=Queue,name=DefaultExpiry");
+      
+      ServerManagement.setAttribute(ServerManagement.getServerPeerObjectName(), "DefaultExpiryQueue", on.toString());
+      
+      ObjectName defaultExpiry =
+         (ObjectName)ServerManagement.getAttribute(ServerManagement.getServerPeerObjectName(), "DefaultExpiryQueue");
+
+      assertEquals(on, defaultExpiry);
+   }
+   
+   
+   public void testRetrievePreparedTransactions() throws Exception
+   {
+      if(!ServerManagement.isServerPeerStarted())
+      {
+         ServerManagement.startServerPeer();
+      }
+      
+      XAConnectionFactory cf = (XAConnectionFactory)initialContext.lookup("/ConnectionFactory");
+      
+      ServerManagement.deployQueue("Queue");
+
+      Queue queue = (Queue)initialContext.lookup("/queue/Queue");
+      
+      XAConnection conn = null;
+      
+      try
+      {
+         conn = cf.createXAConnection();
+         
+         Xid xid1, xid2;
+         
+         {
+         
+            XASession sess = conn.createXASession();
+            
+            XAResource res = sess.getXAResource();
+            
+            MessageProducer prod = sess.createProducer(queue);
+            
+            xid1 = new XidImpl("blah1".getBytes(), 42, "blahblah1".getBytes());
+                     
+            TextMessage tm = sess.createTextMessage("message1");
+            
+            res.start(xid1, XAResource.TMNOFLAGS);
+            
+            prod.send(tm);
+            
+            res.end(xid1, XAResource.TMSUCCESS);
+            
+            res.prepare(xid1);
+         
+         }
+         
+         {
+            
+            XASession sess = conn.createXASession();
+            
+            XAResource res = sess.getXAResource();
+            
+            MessageProducer prod = sess.createProducer(queue);
+            
+            xid2 = new XidImpl("blah2".getBytes(), 42, "blahblah2".getBytes());
+                     
+            TextMessage tm = sess.createTextMessage("message1");
+            
+            res.start(xid2, XAResource.TMNOFLAGS);
+            
+            prod.send(tm);
+            
+            res.end(xid2, XAResource.TMSUCCESS);
+            
+            res.prepare(xid2);
+         
+         }
+         
+         List txList = (List)ServerManagement.invoke(ServerManagement.getServerPeerObjectName(), 
+                  "retrievePreparedTransactions", null, null);
+         
+         assertNotNull(txList);
+         
+         assertEquals(2, txList.size());
+         
+         Xid rxid1 = (Xid)txList.get(0);
+         
+         Xid rxid2 = (Xid)txList.get(1);
+         
+         
+         boolean ok = (xid1.equals(rxid1) && xid2.equals(rxid2)) ||
+                      (xid2.equals(rxid1) && xid1.equals(rxid2));
+         
+         assertTrue(ok);
+         
+         String listAsHTML = (String)ServerManagement.invoke(ServerManagement.getServerPeerObjectName(), 
+                  "showPreparedTransactionsAsHTML", null, null);
+         
+         assertNotNull(listAsHTML); 
+         
+         assertTrue(listAsHTML.indexOf(xid1.toString()) != -1);
+         
+         assertTrue(listAsHTML.indexOf(xid2.toString()) != -1);                      
+         
+      }
+      finally
+      {
+         if (conn != null)
+         {
+            conn.close();
+         }
+         
+         ServerManagement.undeployQueue("Queue");
+      }
+   }
+   
+   public void testMessageCounter() throws Exception
+   {
+      if(!ServerManagement.isServerPeerStarted())
+      {
+         ServerManagement.startServerPeer();
+      }
+      
+      ConnectionFactory cf = (ConnectionFactory)initialContext.lookup("/ConnectionFactory");
+      
+      ServerManagement.deployQueue("Queue1");
+      
+      ServerManagement.deployQueue("Queue2");
+      
+      ServerManagement.deployQueue("Queue3");
+      
+      ServerManagement.deployTopic("Topic1");
+      
+      ServerManagement.deployTopic("Topic2");
+      
+      Queue queue1 = (Queue)initialContext.lookup("/queue/Queue1");
+      
+      Queue queue2 = (Queue)initialContext.lookup("/queue/Queue2");
+      
+      Queue queue3 = (Queue)initialContext.lookup("/queue/Queue3");
+      
+      Topic topic1 = (Topic)initialContext.lookup("/topic/Topic1");
+      
+      Topic topic2 = (Topic)initialContext.lookup("/topic/Topic2");
+      
+      Connection conn = null;
+      
+      try
+      {
+         conn = cf.createConnection();
+         
+         conn.setClientID("wib");
+         
+         Integer i = (Integer)ServerManagement.getAttribute(ServerManagement.getServerPeerObjectName(), "DefaultMessageCounterHistoryDayLimit");
+         
+         assertNotNull(i);
+         
+         assertEquals(-1, i.intValue());
+         
+         ServerManagement.setAttribute(ServerManagement.getServerPeerObjectName(), "DefaultMessageCounterHistoryDayLimit", String.valueOf(23));
+         
+         i = (Integer)ServerManagement.getAttribute(ServerManagement.getServerPeerObjectName(), "DefaultMessageCounterHistoryDayLimit");
+         
+         assertNotNull(i);
+         
+         assertEquals(23, i.intValue());
+         
+         ServerManagement.setAttribute(ServerManagement.getServerPeerObjectName(), "DefaultMessageCounterHistoryDayLimit", String.valueOf(-100));
+         
+         i = (Integer)ServerManagement.getAttribute(ServerManagement.getServerPeerObjectName(), "DefaultMessageCounterHistoryDayLimit");
+         
+         assertNotNull(i);
+         
+         assertEquals(-1, i.intValue());
+         
+         Long l = (Long)ServerManagement.getAttribute(ServerManagement.getServerPeerObjectName(), "QueueStatsSamplePeriod");
+         
+         assertNotNull(l);
+         
+         assertEquals(5000, l.longValue()); //default value
+         
+         ServerManagement.setAttribute(ServerManagement.getServerPeerObjectName(), "QueueStatsSamplePeriod", String.valueOf(1000));
+         
+         l = (Long)ServerManagement.getAttribute(ServerManagement.getServerPeerObjectName(), "QueueStatsSamplePeriod");
+         
+         assertNotNull(l);
+         
+         assertEquals(1000, l.longValue());
+         
+         
+         List counters = (List)
+            ServerManagement.invoke(ServerManagement.getServerPeerObjectName(), "getMessageCounters", null, null);
+         
+         assertNotNull(counters);
+         
+         assertEquals(3, counters.size());
+         
+         
+         //Create some subscriptions
+         
+         Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         
+         MessageConsumer cons1 = sess.createConsumer(topic1);
+         
+         MessageConsumer cons2 = sess.createConsumer(topic2);
+         
+         MessageConsumer cons3 = sess.createDurableSubscriber(topic2, "sub1");
+         
+         
+         counters = (List)
+         ServerManagement.invoke(ServerManagement.getServerPeerObjectName(), "getMessageCounters", null, null);
+      
+         assertNotNull(counters);
+      
+         //Should now be 6 - 3 more for subscriptions
+         assertEquals(6, counters.size());
+         
+         
+         Iterator iter = counters.iterator();
+         
+         while (iter.hasNext())
+         {
+            MessageCounter counter = (MessageCounter)iter.next();
+            
+            assertEquals(0, counter.getCount());
+            
+            assertEquals(0, counter.getCountDelta());
+            
+            assertEquals(-1, counter.getHistoryLimit());
+            
+         }
+         
+         //Create a temp queue
+         
+         TemporaryQueue tempQueue = sess.createTemporaryQueue();
+         
+         counters = (List)
+         ServerManagement.invoke(ServerManagement.getServerPeerObjectName(), "getMessageCounters", null, null);
+      
+         assertNotNull(counters);
+      
+         //Should now be 7
+         assertEquals(7, counters.size());
+         
+         //Send some messages
+         
+         MessageProducer prod = sess.createProducer(null);
+         
+         TextMessage tm1 = sess.createTextMessage("message1");
+         
+         TextMessage tm2 = sess.createTextMessage("message2");
+         
+         TextMessage tm3 = sess.createTextMessage("message3");
+         
+         prod.send(queue1, tm1);         
+         prod.send(queue1, tm2);         
+         prod.send(queue1, tm3);
+         
+         prod.send(queue2, tm1);         
+         prod.send(queue2, tm2);         
+         prod.send(queue2, tm3);
+         
+         prod.send(queue3, tm1);         
+         prod.send(queue3, tm2);         
+         prod.send(queue3, tm3);
+         
+         prod.send(tempQueue, tm1);         
+         prod.send(tempQueue, tm2);         
+         prod.send(tempQueue, tm3);
+         
+         prod.send(topic1, tm1);         
+         prod.send(topic1, tm2);         
+         prod.send(topic1, tm3);
+         
+         prod.send(topic2, tm1);         
+         prod.send(topic2, tm2);         
+         prod.send(topic2, tm3);
+         
+         iter = counters.iterator();
+         
+         //Wait until the stats are updated
+         Thread.sleep(1500);
+         
+         while (iter.hasNext())
+         {
+            MessageCounter counter = (MessageCounter)iter.next();
+            
+            assertEquals(3, counter.getCount());
+            
+            assertEquals(3, counter.getCountDelta());
+            
+            assertEquals(-1, counter.getHistoryLimit());
+            
+         }
+         
+         while (iter.hasNext())
+         {
+            MessageCounter counter = (MessageCounter)iter.next();
+                
+            assertEquals(3, counter.getCount());
+            
+            assertEquals(0, counter.getCountDelta());
+            
+            assertEquals(-1, counter.getHistoryLimit());
+            
+         }
+            
+         ServerManagement.invoke(ServerManagement.getServerPeerObjectName(), "resetAllMessageCounters", null, null);
+         
+         ServerManagement.invoke(ServerManagement.getServerPeerObjectName(), "resetAllMessageCounterHistories", null, null);
+         
+         
+         while (iter.hasNext())
+         {
+            MessageCounter counter = (MessageCounter)iter.next();
+            
+            assertEquals(0, counter.getCount());
+            
+            assertEquals(0, counter.getCountDelta());
+            
+            assertEquals(-1, counter.getHistoryLimit());            
+         }
+         
+         String html = (String)ServerManagement.invoke(ServerManagement.getServerPeerObjectName(), "listMessageCountersAsHTML", null, null);
+         
+         assertNotNull(html);
+         
+         while (iter.hasNext())
+         {
+            MessageCounter counter = (MessageCounter)iter.next();
+
+            assertTrue(html.indexOf(counter.getDestinationName()) != -1);           
+         }
+         
+         List stats = (List)ServerManagement.invoke(ServerManagement.getServerPeerObjectName(), "getMessageStatistics", null, null);
+         
+         assertNotNull(stats);
+         
+         assertEquals(7, stats.size());
+         
+         iter = stats.iterator();
+         
+         while (iter.hasNext())
+         {
+            MessageStatistics stat = (MessageStatistics)iter.next();
+            
+            assertEquals(0, stat.getCount());
+            
+            assertEquals(0, stat.getCountDelta());
+            
+            assertEquals(3, stat.getDepth());
+            
+            assertEquals(0, stat.getDepthDelta());   
+         }
+         
+         cons1.close();
+         cons2.close();
+         cons3.close();
+         sess.unsubscribe("sub1");
+         
+         counters = (List)
+         ServerManagement.invoke(ServerManagement.getServerPeerObjectName(), "getMessageCounters", null, null);
+      
+         assertNotNull(counters);
+      
+         assertEquals(4, counters.size());
+                  
+         tempQueue.delete();
+         
+         
+         counters = (List)
+         ServerManagement.invoke(ServerManagement.getServerPeerObjectName(), "getMessageCounters", null, null);
+      
+         assertNotNull(counters);
+      
+         assertEquals(3, counters.size());
+         
+      }
+      finally
+      {
+         if (conn != null)
+         {
+            conn.close();
+         }
+         
+         ServerManagement.undeployQueue("Queue1");
+         
+         ServerManagement.undeployQueue("Queue2");
+         
+         ServerManagement.undeployQueue("Queue3");
+         
+         ServerManagement.undeployTopic("Topic1");
+         
+         ServerManagement.undeployTopic("Topic2");
+      }
+   }
+
+
    // Package protected ---------------------------------------------
    
    // Protected -----------------------------------------------------

Modified: trunk/tests/src/org/jboss/test/messaging/jms/server/destination/QueueManagementTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/server/destination/QueueManagementTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/jms/server/destination/QueueManagementTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -22,9 +22,23 @@
 package org.jboss.test.messaging.jms.server.destination;
 
 import java.util.List;
-import javax.jms.*;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.DeliveryMode;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
 import javax.management.ObjectName;
 import javax.naming.InitialContext;
+
+import org.jboss.jms.message.JBossMessage;
+import org.jboss.jms.server.messagecounter.MessageCounter;
+import org.jboss.jms.server.messagecounter.MessageStatistics;
 import org.jboss.test.messaging.jms.server.destination.base.DestinationManagementTestBase;
 import org.jboss.test.messaging.tools.ServerManagement;
 
@@ -217,7 +231,71 @@
          ServerManagement.undeployQueue("QueueMessageCount");
       }
    }
+   
+   public void testScheduledMessageCount() throws Exception
+   {
+      InitialContext ic = new InitialContext(ServerManagement.getJNDIEnvironment());
+      ConnectionFactory cf = (ConnectionFactory)ic.lookup("/ConnectionFactory");
 
+      ServerManagement.deployQueue("QueueMessageCount");
+
+      try
+      {
+         Queue queue = (Queue)ic.lookup("/queue/QueueMessageCount");
+
+         // Test MessageCount, should be 0 msg
+         ObjectName destObjectName =
+            new ObjectName("jboss.messaging.destination:service=Queue,name=QueueMessageCount");
+         Integer count = (Integer)ServerManagement.getAttribute(destObjectName, "ScheduledMessageCount");
+         assertEquals(0, count.intValue());
+
+         // Send 1 message to queue
+         Connection conn = cf.createConnection();
+         Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         MessageProducer prod = session.createProducer(queue);         
+         prod.setDeliveryMode(DeliveryMode.PERSISTENT);
+
+         TextMessage m = session.createTextMessage("message one");
+         m.setLongProperty(JBossMessage.JMS_JBOSS_SCHEDULED_DELIVERY_PROP_NAME, System.currentTimeMillis() + 1000);
+         prod.send(m);
+         conn.close();
+
+         // Test MessageCount again, should be 1 msg
+         count = (Integer)ServerManagement.getAttribute(destObjectName, "MessageCount");
+         assertEquals(1, count.intValue());
+         
+         count = (Integer)ServerManagement.getAttribute(destObjectName, "ScheduledMessageCount");
+         assertEquals(1, count.intValue());
+         
+         Thread.sleep(2000);
+         
+         count = (Integer)ServerManagement.getAttribute(destObjectName, "ScheduledMessageCount");
+         assertEquals(0, count.intValue());
+
+         // Consume the message
+         conn = cf.createConnection();
+         session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         MessageConsumer cons = session.createConsumer(queue);
+         conn.start();
+
+         cons.receive();
+         conn.close();
+
+         //Need to pause for a bit since the message is not necessarily removed
+         //in memory until sometime after receive has completed
+         Thread.sleep(1000);
+
+         // Test MessageCount again, should be 0 msg
+         count = (Integer)ServerManagement.getAttribute(destObjectName, "MessageCount");
+         assertEquals(0, count.intValue());
+      }
+      finally
+      {
+
+         ServerManagement.undeployQueue("QueueMessageCount");
+      }
+   }
+
    public void testMessageCountOverFullSize() throws Exception
    {
       InitialContext ic = new InitialContext(ServerManagement.getJNDIEnvironment());
@@ -293,27 +371,75 @@
       }
    }
 
-    /** this method will retry getting MessageCount until it gets a sucessful result.
-     *  This is done just so you can visualize a logs what's the real racing condition. (caused by the delivery thread at the time of the construction of this method)
-     */
-    private void retryForLogs(int mc, int receivedCount, int MESSAGE_COUNT, ObjectName destObjectName) throws Exception {
-        int retry=0;
-        while ((MESSAGE_COUNT - receivedCount != mc) && retry<10)
-        {
-           log.info("******************** Still failing");
-           mc = ((Integer) ServerManagement.
-               getAttribute(destObjectName, "MessageCount")).intValue();
-            Thread.sleep(50);
-            retry++;
-        }
-        if (retry<10)
-        {
-            log.info("There is a racing condition that was fixed after " + retry + " retries. Look at log4j traces.");
-        }
-    }
+   public void testMaxSize() throws Exception
+   {
+      InitialContext ic = new InitialContext(ServerManagement.getJNDIEnvironment());
+      ConnectionFactory cf = (ConnectionFactory)ic.lookup("/ConnectionFactory");
 
-   // TODO this test should be done in DestinationManagementTestBase, once implemented in Topic
-   // TODO this only tests reliable non-tx messages
+      ServerManagement.deployQueue("QueueMaxSize");
+
+      try
+      {
+         Queue queue = (Queue)ic.lookup("/queue/QueueMaxSize");
+         
+         ObjectName destObjectName =
+            new ObjectName("jboss.messaging.destination:service=Queue,name=QueueMaxSize");
+         
+         Integer i = (Integer)ServerManagement.getAttribute(destObjectName, "MaxSize");
+         
+         assertEquals(-1, i.intValue());
+         
+         ServerManagement.setAttribute(destObjectName, "MaxSize", String.valueOf(2));
+         
+         i = (Integer)ServerManagement.getAttribute(destObjectName, "MaxSize");
+         
+         assertEquals(2, i.intValue());
+         
+         Connection conn = cf.createConnection();
+         Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         MessageProducer prod = session.createProducer(queue);
+         prod.setDeliveryMode(DeliveryMode.PERSISTENT);
+
+         TextMessage m1 = session.createTextMessage("message one");
+         prod.send(m1);
+         TextMessage m2 = session.createTextMessage("message two");
+         prod.send(m2);
+         TextMessage m3 = session.createTextMessage("message three");
+         try
+         {
+            prod.send(m3);
+         }
+         catch (JMSException e)
+         {
+            //OK
+         }
+         
+         conn.close();
+
+         conn = cf.createConnection();
+         session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         MessageConsumer cons = session.createConsumer(queue);
+         conn.start();
+
+         TextMessage rm1 = (TextMessage)cons.receive(1000);
+         assertNotNull(rm1);
+         assertEquals("message one", rm1.getText());
+         
+         TextMessage rm2 = (TextMessage)cons.receive(1000);
+         assertNotNull(rm2);
+         assertEquals("message two", rm2.getText());
+         
+         Message m = cons.receive(1000);
+         assertNull(m);
+         
+         conn.close();
+      }
+      finally
+      {
+         ServerManagement.undeployQueue("QueueMaxSize");
+      }
+   }
+
    public void testRemoveAllMessages() throws Exception
    {
       InitialContext ic = new InitialContext(ServerManagement.getJNDIEnvironment());
@@ -368,74 +494,169 @@
    }
 
    public void testListMessages() throws Exception
-   {
+   {   
       InitialContext ic = new InitialContext(ServerManagement.getJNDIEnvironment());
+      
       ConnectionFactory cf = (ConnectionFactory)ic.lookup("/ConnectionFactory");
-
+ 
       ServerManagement.deployQueue("QueueListMessages");
-
+      
+      Connection conn = null;
+      
+      Queue queue = (Queue)ic.lookup("/queue/QueueListMessages");      
+      
       try
-      {
-
-         Queue queue = (Queue)ic.lookup("/queue/QueueListMessages");
-
-         // Test listMessages, should be 0 msg
-         ObjectName destObjectName =
-            new ObjectName("jboss.messaging.destination:service=Queue,name=QueueListMessages");
-
-         List list = (List)ServerManagement.invoke(
-               destObjectName,
-               "listMessages",
-               new Object[] {null},
-               new String[] {"java.lang.String"});
-         assertNotNull(list);
-         assertEquals(0, list.size());
-
-         // Send 1 message to queue
-         Connection conn = cf.createConnection();
-         Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-         MessageProducer prod = session.createProducer(queue);
-         prod.setDeliveryMode(DeliveryMode.PERSISTENT);
-
-         TextMessage m = session.createTextMessage("message one");
-         prod.send(m);
-         conn.close();
-
-         // Test listMessages again, should be 1 msg
-         list = (List)ServerManagement.invoke(
-               destObjectName,
-               "listMessages",
-               new Object[] {null},
-               new String[] {"java.lang.String"});
-         assertEquals(1, list.size());
-         assertTrue(list.get(0) instanceof TextMessage);
-         TextMessage m1 = (TextMessage)list.get(0);
-         assertEquals(m1.getText(), m.getText());
-
-         // Consume the message
+      {         
          conn = cf.createConnection();
-         session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
-         MessageConsumer cons = session.createConsumer(queue);
-         conn.start();
-
-         cons.receive();
-         conn.close();
+   
+         Session s = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
          
-         //Cancel is asynch
-         Thread.sleep(500);
-
-         // Test MessageCount again, should be 0 msg
-         list = (List)ServerManagement.invoke(
-               destObjectName,
-               "listMessages",
-               new Object[] {null},
-               new String[] {"java.lang.String"});
-         assertEquals(0, list.size());
+         MessageProducer prod = s.createProducer(queue);
+   
+         // Send some persistent message
+         TextMessage tm1 = s.createTextMessage("message1");
+         tm1.setStringProperty("vegetable", "parsnip");
+         TextMessage tm2 = s.createTextMessage("message2");
+         tm2.setStringProperty("vegetable", "parsnip");
+         TextMessage tm3 = s.createTextMessage("message3");
+         tm3.setStringProperty("vegetable", "parsnip");
+         prod.send(tm1);
+         prod.send(tm2);
+         prod.send(tm3);
+         
+         // and some non persistent with a selector
+         prod.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
+         
+         TextMessage tm4 = s.createTextMessage("message4");
+         tm4.setStringProperty("vegetable", "artichoke");
+         TextMessage tm5 = s.createTextMessage("message5");
+         tm5.setStringProperty("vegetable", "artichoke");
+         TextMessage tm6 = s.createTextMessage("message6");
+         tm6.setStringProperty("vegetable", "artichoke");
+         prod.send(tm4);
+         prod.send(tm5);
+         prod.send(tm6);
+         
+         ObjectName destObjectName = 
+            new ObjectName("jboss.messaging.destination:service=Queue,name=QueueListMessages");
+          
+         List allMsgs = (List)ServerManagement.invoke(destObjectName, "listAllMessages", null, null);
+         
+         assertNotNull(allMsgs);         
+         assertEquals(6, allMsgs.size());
+         
+         TextMessage rm1 = (TextMessage)allMsgs.get(0);
+         TextMessage rm2 = (TextMessage)allMsgs.get(1);
+         TextMessage rm3 = (TextMessage)allMsgs.get(2);
+         TextMessage rm4 = (TextMessage)allMsgs.get(3);
+         TextMessage rm5 = (TextMessage)allMsgs.get(4);
+         TextMessage rm6 = (TextMessage)allMsgs.get(5);
+         
+         assertEquals(tm1.getText(), rm1.getText());
+         assertEquals(tm2.getText(), rm2.getText());
+         assertEquals(tm3.getText(), rm3.getText());
+         assertEquals(tm4.getText(), rm4.getText());
+         assertEquals(tm5.getText(), rm5.getText());
+         assertEquals(tm6.getText(), rm6.getText());
+         
+         assertTrue(rm1.getJMSDeliveryMode() == DeliveryMode.PERSISTENT);
+         assertTrue(rm2.getJMSDeliveryMode() == DeliveryMode.PERSISTENT);
+         assertTrue(rm3.getJMSDeliveryMode() == DeliveryMode.PERSISTENT);         
+         assertTrue(rm4.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT);
+         assertTrue(rm5.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT);
+         assertTrue(rm6.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT);
+         
+         List durMsgs = (List)ServerManagement.invoke(destObjectName, "listDurableMessages", null, null);
+         
+         assertNotNull(durMsgs);         
+         assertEquals(3, durMsgs.size());
+         
+         rm1 = (TextMessage)durMsgs.get(0);
+         rm2 = (TextMessage)durMsgs.get(1);
+         rm3 = (TextMessage)durMsgs.get(2);
+                
+         assertEquals(tm1.getText(), rm1.getText());
+         assertEquals(tm2.getText(), rm2.getText());
+         assertEquals(tm3.getText(), rm3.getText());
+         
+         assertTrue(rm1.getJMSDeliveryMode() == DeliveryMode.PERSISTENT);
+         assertTrue(rm2.getJMSDeliveryMode() == DeliveryMode.PERSISTENT);
+         assertTrue(rm3.getJMSDeliveryMode() == DeliveryMode.PERSISTENT);                 
+         
+         
+         List nondurMsgs = (List)ServerManagement.invoke(destObjectName, "listNonDurableMessages", null, null);
+         
+         assertNotNull(nondurMsgs);         
+         assertEquals(3, nondurMsgs.size());
+               
+         rm4 = (TextMessage)nondurMsgs.get(0);
+         rm5 = (TextMessage)nondurMsgs.get(1);
+         rm6 = (TextMessage)nondurMsgs.get(2);
+                 
+         assertEquals(tm4.getText(), rm4.getText());
+         assertEquals(tm5.getText(), rm5.getText());
+         assertEquals(tm6.getText(), rm6.getText());
+             
+         assertTrue(rm4.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT);
+         assertTrue(rm5.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT);
+         assertTrue(rm6.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT);
+         
+         //Now with a selector
+         
+         String sel = "vegetable='artichoke'";
+         
+         allMsgs = (List)ServerManagement.invoke(destObjectName, "listAllMessages", new Object[] { sel }, new String[] { "java.lang.String" });
+         
+         assertNotNull(allMsgs);         
+         assertEquals(3, allMsgs.size());
+         
+         rm4 = (TextMessage)allMsgs.get(0);
+         rm5 = (TextMessage)allMsgs.get(1);
+         rm6 = (TextMessage)allMsgs.get(2);
+         
+         assertEquals(tm4.getText(), rm4.getText());
+         assertEquals(tm5.getText(), rm5.getText());
+         assertEquals(tm6.getText(), rm6.getText());
+            
+         assertTrue(rm4.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT);
+         assertTrue(rm5.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT);
+         assertTrue(rm6.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT);
+                  
+         durMsgs = (List)ServerManagement.invoke(destObjectName, "listDurableMessages", new Object[] { sel }, new String[] { "java.lang.String" });
+         
+         assertNotNull(durMsgs);         
+         assertEquals(0, durMsgs.size());
+         
+         
+         nondurMsgs = (List)ServerManagement.invoke(destObjectName, "listNonDurableMessages", new Object[] { sel }, new String[] { "java.lang.String" });
+         
+         assertNotNull(nondurMsgs);         
+         assertEquals(3, nondurMsgs.size());
+               
+         rm4 = (TextMessage)nondurMsgs.get(0);
+         rm5 = (TextMessage)nondurMsgs.get(1);
+         rm6 = (TextMessage)nondurMsgs.get(2);
+                 
+         assertEquals(tm4.getText(), rm4.getText());
+         assertEquals(tm5.getText(), rm5.getText());
+         assertEquals(tm6.getText(), rm6.getText());
+             
+         assertTrue(rm4.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT);
+         assertTrue(rm5.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT);
+         assertTrue(rm6.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT);                  
+         
       }
       finally
       {
-
+         if (conn != null)
+         {
+            conn.close();
+         }
+         
+         drainDestination(cf, queue);
+         
          ServerManagement.undeployQueue("QueueListMessages");
+      
       }
    }
 
@@ -446,25 +667,165 @@
    public void testListMessagesEmptySelector() throws Exception
    {
       ServerManagement.deployQueue("QueueListMessages");
+      
+      try
+      {
+   
+         ObjectName destObjectName =
+            new ObjectName("jboss.messaging.destination:service=Queue,name=QueueListMessages");
+   
+         List list = (List)ServerManagement.invoke(destObjectName,
+                                                   "listAllMessages",
+                                                   new Object[] {""},
+                                                   new String[] {"java.lang.String"});
+         assertNotNull(list);
+         assertEquals(0, list.size());
+   
+         list = (List)ServerManagement.invoke(destObjectName,
+                                                   "listAllMessages",
+                                                   new Object[] {"             "},
+                                                   new String[] {"java.lang.String"});
+         assertNotNull(list);
+         assertEquals(0, list.size());
+      }
+      finally
+      {
+         ServerManagement.undeployQueue("QueueListMessages");
+      }
+   }
+   
+   public void testMessageCounter() throws Exception
+   {
+      InitialContext ic = new InitialContext(ServerManagement.getJNDIEnvironment());
+      ConnectionFactory cf = (ConnectionFactory)ic.lookup("/ConnectionFactory");
+      
+      ServerManagement.setAttribute(ServerManagement.getServerPeerObjectName(), "QueueStatsSamplePeriod", String.valueOf(1000));
+      
 
+      ServerManagement.deployQueue("QueueMessageCounter");
+      
+      Queue queue = (Queue)ic.lookup("/queue/QueueMessageCounter");      
+
       ObjectName destObjectName =
-         new ObjectName("jboss.messaging.destination:service=Queue,name=QueueListMessages");
+         new ObjectName("jboss.messaging.destination:service=Queue,name=QueueMessageCounter");
+      
+      //Most of this is tested in ServerPeerTest
+      
+      MessageCounter counter = (MessageCounter)ServerManagement.getAttribute(destObjectName, "MessageCounter");
+      
+      assertNotNull(counter);
+      
+      assertEquals(0, counter.getCount());
+      
+      assertEquals(0, counter.getCountDelta());
+      
+      assertEquals(-1, counter.getHistoryLimit());
+      
+      Connection conn = cf.createConnection();
+      
+      Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+      
+      MessageProducer prod = sess.createProducer(queue);
+      
+      TextMessage tm1 = sess.createTextMessage("message1");
+      prod.send(tm1);
+      
+      TextMessage tm2 = sess.createTextMessage("message2");
+      prod.send(tm2);
+      
+      TextMessage tm3 = sess.createTextMessage("message3");
+      prod.send(tm3);
+      
+      Thread.sleep(1500);
+      
+      assertEquals(3, counter.getCount());
+      
+      assertEquals(3, counter.getCountDelta());
+      
+      assertEquals(3, counter.getCount());
+      
+      assertEquals(0, counter.getCountDelta());
+      
+      MessageStatistics stats = (MessageStatistics)ServerManagement.getAttribute(destObjectName, "MessageStatistics");
+      
+      assertNotNull(stats);
+      
+      assertEquals(3, stats.getCount());
+      
+      assertEquals(0, stats.getCountDelta());
+      
+      assertEquals(3, stats.getDepth());
+      
+      ServerManagement.invoke(destObjectName, "resetMessageCounter", null, null);
+      
+      assertEquals(0, counter.getCount());
+      
+      ServerManagement.invoke(destObjectName, "resetMessageCounterHistory", null, null);
+      
+      String html = (String)ServerManagement.invoke(destObjectName, "getMessageCounterHistoryAsHTML", null, null);
+      
+      assertNotNull(html);
+      
+      html = (String)ServerManagement.invoke(destObjectName, "getMessageCounterAsHTML", null, null);
+      
+      assertNotNull(html);
+      
+      assertTrue(html.indexOf("QueueMessageCounter") != -1);
+            
+      
+      ServerManagement.undeployQueue("QueueMessageCounter");
 
-      List list = (List)ServerManagement.invoke(destObjectName,
-                                                "listMessages",
-                                                new Object[] {""},
-                                                new String[] {"java.lang.String"});
-      assertNotNull(list);
-      assertEquals(0, list.size());
+   }
+   
+   public void testConsumersCount() throws Exception
+   {
+      InitialContext ic = new InitialContext(ServerManagement.getJNDIEnvironment());
+      ConnectionFactory cf = (ConnectionFactory)ic.lookup("/ConnectionFactory");
+      
 
-      list = (List)ServerManagement.invoke(destObjectName,
-                                                "listMessages",
-                                                new Object[] {"             "},
-                                                new String[] {"java.lang.String"});
-      assertNotNull(list);
-      assertEquals(0, list.size());
+      ServerManagement.deployQueue("QueueConsumerCount");
+      
+      Queue queue = (Queue)ic.lookup("/queue/QueueConsumerCount");      
 
-      ServerManagement.undeployQueue("QueueListMessages");
+      ObjectName destObjectName =
+         new ObjectName("jboss.messaging.destination:service=Queue,name=QueueConsumerCount");
+          
+      Connection conn = cf.createConnection();
+      
+      Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+      
+      Integer i = (Integer)ServerManagement.getAttribute(destObjectName, "ConsumerCount");
+      
+      assertEquals(0, i.intValue());
+      
+      MessageConsumer cons1 = sess.createConsumer(queue);
+      
+      MessageConsumer cons2 = sess.createConsumer(queue);
+      
+      MessageConsumer cons3 = sess.createConsumer(queue);
+      
+      i = (Integer)ServerManagement.getAttribute(destObjectName, "ConsumerCount");
+      
+      assertEquals(3, i.intValue());
+      
+      cons3.close();
+      
+      i = (Integer)ServerManagement.getAttribute(destObjectName, "ConsumerCount");
+      
+      assertEquals(2, i.intValue());
+      
+      cons1.close();
+      
+      cons2.close();
+      
+      i = (Integer)ServerManagement.getAttribute(destObjectName, "ConsumerCount");
+      
+      assertEquals(0, i.intValue());
+      
+      conn.close();
+      
+      ServerManagement.undeployQueue("QueueConsumerCount");
+
    }
 
    // Package protected ---------------------------------------------
@@ -477,6 +838,26 @@
    }
 
    // Private -------------------------------------------------------
+   
+   /** this method will retry getting MessageCount until it gets a sucessful result.
+    *  This is done just so you can visualize a logs what's the real racing condition. (caused by the delivery thread at the time of the construction of this method)
+    */
+   private void retryForLogs(int mc, int receivedCount, int MESSAGE_COUNT, ObjectName destObjectName) throws Exception
+   {
+      int retry=0;
+      while ((MESSAGE_COUNT - receivedCount != mc) && retry < 10)
+      {
+         log.info("******************** Still failing");
+         mc = ((Integer) ServerManagement.
+                  getAttribute(destObjectName, "MessageCount")).intValue();
+         Thread.sleep(50);
+         retry++;
+      }
+      if (retry<10)
+      {
+         log.info("There is a racing condition that was fixed after " + retry + " retries. Look at log4j traces.");
+      }
+   }
 
    // Inner classes -------------------------------------------------
 }

Modified: trunk/tests/src/org/jboss/test/messaging/jms/server/destination/TopicManagementTest.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/server/destination/TopicManagementTest.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/jms/server/destination/TopicManagementTest.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -26,6 +26,7 @@
 import javax.jms.Connection;
 import javax.jms.ConnectionFactory;
 import javax.jms.DeliveryMode;
+import javax.jms.Message;
 import javax.jms.MessageConsumer;
 import javax.jms.MessageProducer;
 import javax.jms.Session;
@@ -38,10 +39,11 @@
 import javax.naming.InitialContext;
 
 import org.jboss.jms.client.JBossConnectionFactory;
+import org.jboss.jms.selector.Selector;
+import org.jboss.jms.server.destination.SubscriptionInfo;
 import org.jboss.test.messaging.jms.server.destination.base.DestinationManagementTestBase;
 import org.jboss.test.messaging.tools.ServerManagement;
 
-
 /**
  * Tests a topic's management interface.
  *
@@ -191,19 +193,19 @@
    }
    
    /**
-    * Test subscriptionCount() and subscriptionCount(boolean durable).
+    * Test removeAllMessages().
     * @throws Exception
     */
-   public void testSubscriptionCount() throws Exception
+   public void testRemoveAllMessages() throws Exception
    {
       InitialContext ic = new InitialContext(ServerManagement.getJNDIEnvironment());
       TopicConnectionFactory cf = (JBossConnectionFactory)ic.lookup("/ConnectionFactory");
  
-      ServerManagement.deployTopic("TopicSubscription");
+      ServerManagement.deployTopic("TopicRemoveAllMessages");
       
       try
       {
-         Topic topic = (Topic)ic.lookup("/topic/TopicSubscription");
+         Topic topic = (Topic)ic.lookup("/topic/TopicRemoveAllMessages");
    
          TopicConnection conn = cf.createTopicConnection();
    
@@ -213,617 +215,680 @@
          MessageProducer prod = s.createProducer(topic);
          prod.setDeliveryMode(DeliveryMode.PERSISTENT);
    
+         // Create 1 durable subscription and 1 non-durable subscription
+         s.createDurableSubscriber(topic, "Durable1");
+         s.createSubscriber(topic);
+         
+         // Send 1 message
+         prod.send(s.createTextMessage("First one"));         
+         
+         ObjectName destObjectName = 
+            new ObjectName("jboss.messaging.destination:service=Topic,name=TopicRemoveAllMessages");
+         
+         int count = ((Integer)ServerManagement.getAttribute(destObjectName, "AllMessageCount")).intValue();
+         
+         assertEquals(2, count);
+         
+         // Start the connection for delivery
+         conn.start();
+         
+         // Remove all messages from the topic
+         
+         //Need to pause since delivery may still be in progress
+         Thread.sleep(2000);
+         
+         ServerManagement.invoke(destObjectName, "removeAllMessages", null, null);
+   
+         count = ((Integer)ServerManagement.getAttribute(destObjectName, "AllMessageCount")).intValue();
+         
+         assertEquals(0, count);
+                  
+         // Now close the connection
+         conn.close();
+         
+         count = ((Integer)ServerManagement.getAttribute(destObjectName, "AllMessageCount")).intValue();
+         
+         assertEquals(0, count);
+         
+         // Connect again to the same topic
+         conn = cf.createTopicConnection();
+         conn.setClientID("Client1");
+         s = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
+         prod = s.createProducer(topic);
+         prod.setDeliveryMode(DeliveryMode.PERSISTENT);
+   
+         // Send another message
+         prod.send(s.createTextMessage("Second one"));
+         
+         count = ((Integer)ServerManagement.getAttribute(destObjectName, "AllMessageCount")).intValue();
+         
+         assertEquals(1, count);
+
+         // Start the connection for delivery
+         conn.start();
+         
+         // Remove all messages from the topic
+         ServerManagement.invoke(destObjectName, "removeAllMessages", null, null);
+   
+         count = ((Integer)ServerManagement.getAttribute(destObjectName, "AllMessageCount")).intValue();
+         
+         assertEquals(0, count);
+         
+         // Clean-up
+         conn.close();
+      }
+      finally
+      {         
+         ServerManagement.undeployTopic("TopicRemoveAllMessages");
+      }
+   }
+  
+   public void testMessageCount() throws Exception
+   {
+      InitialContext ic = new InitialContext(ServerManagement.getJNDIEnvironment());
+      TopicConnectionFactory cf = (JBossConnectionFactory)ic.lookup("/ConnectionFactory");
+ 
+      ServerManagement.deployTopic("TopicGetAllMessageCount");
+      
+      TopicConnection conn = null;
+      
+      
+      try
+      {                  
+         Topic topic = (Topic)ic.lookup("/topic/TopicGetAllMessageCount");
+   
+         conn = cf.createTopicConnection();
+   
+         conn.setClientID("Client1");
+   
+         TopicSession s = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
+         MessageProducer prod = s.createProducer(topic);
+         prod.setDeliveryMode(DeliveryMode.PERSISTENT);
+   
          // Create 1 durable subscription and 2 non-durable subscription
          s.createDurableSubscriber(topic, "SubscriberA");
          
          s.createSubscriber(topic);
          s.createSubscriber(topic);
+         
+         //Send a couple of messages
+         TextMessage tm1 = s.createTextMessage("message1");
+         TextMessage tm2 = s.createTextMessage("message2");
+         
+         prod.send(tm1);
+         prod.send(tm2);
    
          // There should be 3 subscriptions
          ObjectName destObjectName = 
-            new ObjectName("jboss.messaging.destination:service=Topic,name=TopicSubscription");
-         Integer count = (Integer)ServerManagement.invoke(destObjectName, "subscriptionCount", null, null);
-         assertEquals(3, count.intValue());
+            new ObjectName("jboss.messaging.destination:service=Topic,name=TopicGetAllMessageCount");
          
-         // There should be 1 durable subscription
-         Integer duraCount = (Integer)ServerManagement.invoke(
-               destObjectName, 
-               "subscriptionCount", 
-               new Object[] {Boolean.TRUE}, 
-               new String[] {"boolean"});
-         assertEquals(1, duraCount.intValue());
+         Integer count = (Integer)ServerManagement.getAttribute(destObjectName, "AllMessageCount");
+         assertEquals(6, count.intValue());
          
-         // There should be 2 non-durable subscription
-         Integer nonduraCount = (Integer)ServerManagement.invoke(
-               destObjectName, 
-               "subscriptionCount", 
-               new Object[] {Boolean.FALSE}, 
-               new String[] {"boolean"});
-         assertEquals(2, nonduraCount.intValue());
+         count = (Integer)ServerManagement.getAttribute(destObjectName, "DurableMessageCount");
+         assertEquals(2, count.intValue());
          
+         count = (Integer)ServerManagement.getAttribute(destObjectName, "NonDurableMessageCount");
+         assertEquals(4, count.intValue());
+                  
          // Now disconnect
          conn.close();
          
-         // There should be only 1 subscription totally
-         count = (Integer)ServerManagement.invoke(destObjectName, "subscriptionCount", null, null);
-         assertEquals(1, count.intValue());
+         // Only the durable should survive
+         count = (Integer)ServerManagement.getAttribute(destObjectName, "AllMessageCount");
+         assertEquals(2, count.intValue());
          
-         // There should be 1 durable subscription
-         duraCount = (Integer)ServerManagement.invoke(
-               destObjectName, 
-               "subscriptionCount", 
-               new Object[] {Boolean.TRUE}, 
-               new String[] {"boolean"});
-         assertEquals(1, duraCount.intValue());
+         count = (Integer)ServerManagement.getAttribute(destObjectName, "DurableMessageCount");
+         assertEquals(2, count.intValue());
          
-         // There should be 0 non-durable subscription
-         nonduraCount = (Integer)ServerManagement.invoke(
-               destObjectName, 
-               "subscriptionCount", 
-               new Object[] {Boolean.FALSE}, 
-               new String[] {"boolean"});
-         assertEquals(0, nonduraCount.intValue());
+         count = (Integer)ServerManagement.getAttribute(destObjectName, "NonDurableMessageCount");
+         assertEquals(0, count.intValue());
          
          // Now connect again and restore the durable subscription
          conn = cf.createTopicConnection();
          conn.setClientID("Client1");
          s = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
-         s.createDurableSubscriber(topic, "SubscriberA");
+         MessageConsumer cons = s.createDurableSubscriber(topic, "SubscriberA");
          
-         // There should be still 1 subscription
-         count = (Integer)ServerManagement.invoke(destObjectName, "subscriptionCount", null, null);
-         assertEquals(1, count.intValue());
+         count = (Integer)ServerManagement.getAttribute(destObjectName, "AllMessageCount");
+         assertEquals(2, count.intValue());
    
          // Now create another durable subscription
          s.createDurableSubscriber(topic, "SubscriberB");
          
-         // There should be 2 durable subscription
-         duraCount = (Integer)ServerManagement.invoke(
-               destObjectName, 
-               "subscriptionCount", 
-               new Object[] {Boolean.TRUE}, 
-               new String[] {"boolean"});
-         assertEquals(2, duraCount.intValue());
+         //Now consume
          
-         // There should be 0 non-durable subscription
-         nonduraCount = (Integer)ServerManagement.invoke(
-               destObjectName, 
-               "subscriptionCount", 
-               new Object[] {Boolean.FALSE}, 
-               new String[] {"boolean"});
-         assertEquals(0, nonduraCount.intValue());
-   
-         // And close the connection
-         conn.close();
+         conn.start();
          
-         // There should be 2 subscription still
-         count = (Integer)ServerManagement.invoke(destObjectName, "subscriptionCount", null, null);
-         assertEquals(2, count.intValue());
-   
-         // There should be 2 durable subscription
-         duraCount = (Integer)ServerManagement.invoke(
-               destObjectName, 
-               "subscriptionCount", 
-               new Object[] {Boolean.TRUE}, 
-               new String[] {"boolean"});
-         assertEquals(2, duraCount.intValue());
+         TextMessage rm1 = (TextMessage)cons.receive(500);
+         assertNotNull(rm1);
+         assertEquals(tm1.getText(), rm1.getText());
          
-         // There should be 0 non-durable subscription
-         nonduraCount = (Integer)ServerManagement.invoke(
-               destObjectName, 
-               "subscriptionCount", 
-               new Object[] {Boolean.FALSE}, 
-               new String[] {"boolean"});
-         assertEquals(0, nonduraCount.intValue());
+         TextMessage rm2 = (TextMessage)cons.receive(500);
+         assertNotNull(rm2);
+         assertEquals(tm2.getText(), rm2.getText());
          
+         Message m = cons.receive(500);
+         assertNull(m);
+         
+         count = (Integer)ServerManagement.getAttribute(destObjectName, "AllMessageCount");
+         assertEquals(0, count.intValue());
+         
+         count = (Integer)ServerManagement.getAttribute(destObjectName, "DurableMessageCount");
+         assertEquals(0, count.intValue());
+         
+         count = (Integer)ServerManagement.getAttribute(destObjectName, "NonDurableMessageCount");
+         assertEquals(0, count.intValue());
+         
       }
       finally
       {
-      
-         ServerManagement.undeployTopic("TopicSubscription");
+         if (conn != null)
+         {
+            conn.close();
+         }
+         ServerManagement.undeployTopic("TopicGetAllMessageCount");
       }
    }
+   
 
-   /**
-    * XXX Placeholder
-    * Test listSubscriptions() and listSubscriptions(boolean durable).
-    * @throws Exception
-    */
-   /*
-   public void testListSubscriptions() throws Exception
+   public void testSubscriptionsCount() throws Exception
    {
       InitialContext ic = new InitialContext(ServerManagement.getJNDIEnvironment());
       TopicConnectionFactory cf = (JBossConnectionFactory)ic.lookup("/ConnectionFactory");
  
-      ServerManagement.deployTopic("TopicSubscriptionList");
-      Topic topic = (Topic)ic.lookup("/topic/TopicSubscriptionList");
-
-      TopicConnection conn = cf.createTopicConnection();
-
-      conn.setClientID("Client1");
-
-      TopicSession s = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
-      MessageProducer prod = s.createProducer(topic);
-      prod.setDeliveryMode(DeliveryMode.PERSISTENT);
-
-      // Create 1 durable subscription and 2 non-durable subscription
-      s.createDurableSubscriber(topic, "SubscriberA");
+      ServerManagement.deployTopic("TopicSubscriptionsCount");
       
-      s.createSubscriber(topic);
-      s.createSubscriber(topic);
-
-      // There should be 3 subscriptions
-      ObjectName destObjectName = 
-         new ObjectName("jboss.messaging.destination:service=Topic,name=TopicSubscriptionList");
-      List list = (List)ServerManagement.invoke(destObjectName, "listSubscriptions", null, null);
-      assertEquals(3, list.size());
-      
-      // There should be 1 durable subscription
-      List duraList = (List)ServerManagement.invoke(
-            destObjectName, 
-            "listSubscriptions", 
-            new Object[] {Boolean.TRUE}, 
-            new String[] {"boolean"});
-      assertEquals(1, duraList.size());
-      // String[] {ChannelID, ClientID, SubscriptionName}
-      String[] strs = (String[])duraList.get(0);
-      assertEquals("Client1", strs[1]);
-      assertEquals("SubscriberA", strs[2]);
-      
-      // There should be 2 non-durable subscription
-      List nonduraList = (List)ServerManagement.invoke(
-            destObjectName, 
-            "listSubscriptions", 
-            new Object[] {Boolean.FALSE}, 
-            new String[] {"boolean"});
-      assertEquals(2, nonduraList.size());
-      // String[] {ChannelID, ClientID, SubscriptionName}
-      strs = (String[])nonduraList.get(0);
-      assertEquals("", strs[1]);
-      assertEquals("", strs[2]);
-      // String[] {ChannelID, ClientID, SubscriptionName}
-      strs = (String[])nonduraList.get(1);
-      assertEquals("", strs[1]);
-      assertEquals("", strs[2]);
-      
-      // Now disconnect
-      conn.close();
-      
-      // There should be only 1 subscription totally
-      list = (List)ServerManagement.invoke(destObjectName, "listSubscriptions", null, null);
-      assertEquals(1, list.size());
-      
-      // There should be 1 durable subscription
-      duraList = (List)ServerManagement.invoke(
-            destObjectName, 
-            "listSubscriptions", 
-            new Object[] {Boolean.TRUE}, 
-            new String[] {"boolean"});
-      assertEquals(1, duraList.size());
-       
-      // There should be 0 non-durable subscription
-      nonduraList = (List)ServerManagement.invoke(
-            destObjectName, 
-            "listSubscriptions", 
-            new Object[] {Boolean.FALSE}, 
-            new String[] {"boolean"});
-      assertEquals(0, nonduraList.size());
-      ServerManagement.undeployTopic("TopicSubscriptionList");
-   }
-   */
-
-   /**
-    * Test listSubscriptionsAsText().
-    * @throws Exception
-    */
-   public void testListSubscriptionsAsText() throws Exception
-   {
-      ServerManagement.deployTopic("TopicSubscription");
-      
-      InitialContext ic = new InitialContext(ServerManagement.getJNDIEnvironment());
-      TopicConnectionFactory cf = (JBossConnectionFactory)ic.lookup("/ConnectionFactory");
- 
-      ServerManagement.deployTopic("TopicSubscriptionListAsText");
-      
+      TopicConnection conn = null;
+            
       try
       {
-         Topic topic = (Topic)ic.lookup("/topic/TopicSubscriptionListAsText");
+         Topic topic = (Topic)ic.lookup("/topic/TopicSubscriptionsCount");
    
-         TopicConnection conn = cf.createTopicConnection();
+         conn = cf.createTopicConnection();
    
          conn.setClientID("Client1");
    
          TopicSession s = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
-         MessageProducer prod = s.createProducer(topic);
-         prod.setDeliveryMode(DeliveryMode.PERSISTENT);
-   
-         // Create 1 durable subscription and 2 non-durable subscription
+
+         // Create 2 durable subscription and 4 non-durable subscription
          s.createDurableSubscriber(topic, "SubscriberA");
+         s.createDurableSubscriber(topic, "SubscriberB");
          
          s.createSubscriber(topic);
          s.createSubscriber(topic);
+         s.createSubscriber(topic);
+         s.createSubscriber(topic);
    
-         // There should be 3 subscriptions
+         // There should be 6 subscriptions
          ObjectName destObjectName = 
-            new ObjectName("jboss.messaging.destination:service=Topic,name=TopicSubscriptionListAsText");
-         String text = (String)ServerManagement.invoke(destObjectName, "listSubscriptionsAsText", null, null);
-         //System.out.println("Text: \n" + text);
+            new ObjectName("jboss.messaging.destination:service=Topic,name=TopicSubscriptionsCount");
          
-         // Find the location of durable
-         int durableStart = text.indexOf("Durable");
-         assertTrue (durableStart != -1);
-         assertTrue (text.indexOf("SubscriberA", durableStart) != -1);
-         assertTrue (text.indexOf("Client1", durableStart) != -1);
-         // Find the first location of Non-durable
-         int nonDurableStart = text.indexOf("Non-durable");
-         assertTrue(nonDurableStart != -1);
-         // Find the 2nd Non-durable
-         int nonDurableSecond = text.substring(nonDurableStart).indexOf("Non-durable", 1);
-         assertTrue(nonDurableSecond != -1);
+         Integer count = (Integer)ServerManagement.getAttribute(destObjectName, "AllSubscriptionsCount");
+         assertEquals(6, count.intValue());
          
-         // Test durable subscriptions
-         text = (String)ServerManagement.invoke(
-               destObjectName, 
-               "listSubscriptionsAsText", 
-               new Object[] {Boolean.TRUE},
-               new String[] {"boolean"});
-         //System.out.println("Durable Text: \n" + text);
+         count = (Integer)ServerManagement.getAttribute(destObjectName, "DurableSubscriptionsCount");
+         assertEquals(2, count.intValue());
          
-         durableStart = text.indexOf("Durable");
-         assertTrue (durableStart != -1);
-         assertTrue (text.indexOf("SubscriberA", durableStart) != -1);
-         assertTrue (text.indexOf("Client1", durableStart) != -1);
+         count = (Integer)ServerManagement.getAttribute(destObjectName, "NonDurableSubscriptionsCount");
+         assertEquals(4, count.intValue());
          
-         // Test non-durable subscriptions
-         text = (String)ServerManagement.invoke(
-               destObjectName, 
-               "listSubscriptionsAsText", 
-               new Object[] {Boolean.FALSE},
-               new String[] {"boolean"});
-         //System.out.println("Non-durable Text: \n" + text);
-         nonDurableStart = text.indexOf("Non-durable");
-         assertTrue(nonDurableStart != -1);
-         // Find the 2nd Non-durable
-         nonDurableSecond = text.substring(nonDurableStart).indexOf("Non-durable", 1);
-         assertTrue(nonDurableSecond != -1);     
-         
+                
          // Now disconnect
          conn.close();
          
-         // There should be only 1 subscription totally
-         text = (String)ServerManagement.invoke(destObjectName, "listSubscriptionsAsText", null, null);
-         durableStart = text.indexOf("Durable");
-         assertTrue (durableStart != -1);
-         assertTrue (text.indexOf("SubscriberA", durableStart) != -1);
-         assertTrue (text.indexOf("Client1", durableStart) != -1);
+         // Only the durable should survive
+         count = (Integer)ServerManagement.getAttribute(destObjectName, "AllSubscriptionsCount");
+         assertEquals(2, count.intValue());
          
-         // There should be 1 durable subscription
-         text = (String)ServerManagement.invoke(
-               destObjectName, 
-               "listSubscriptionsAsText", 
-               new Object[] {Boolean.TRUE}, 
-               new String[] {"boolean"});
-         durableStart = text.indexOf("Durable");
-         assertTrue (durableStart != -1);
-         assertTrue (text.indexOf("SubscriberA", durableStart) != -1);
-         assertTrue (text.indexOf("Client1", durableStart) != -1);
-          
-         // There should be 0 non-durable subscription
-         text = (String)ServerManagement.invoke(
-               destObjectName, 
-               "listSubscriptionsAsText", 
-               new Object[] {Boolean.FALSE}, 
-               new String[] {"boolean"});
-         nonDurableStart = text.indexOf("Non-durable");
-         assertTrue(-1 == nonDurableStart);
+         count = (Integer)ServerManagement.getAttribute(destObjectName, "DurableSubscriptionsCount");
+         assertEquals(2, count.intValue());
+         
+         count = (Integer)ServerManagement.getAttribute(destObjectName, "NonDurableSubscriptionsCount");
+         assertEquals(0, count.intValue());
+         
+         
+         // Now connect again and restore the durable subscription
+         conn = cf.createTopicConnection();
+         conn.setClientID("Client1");
+         s = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
+         s.createDurableSubscriber(topic, "SubscriberA");
+         
+         count = (Integer)ServerManagement.getAttribute(destObjectName, "AllSubscriptionsCount");
+         assertEquals(2, count.intValue());
+         
+         count = (Integer)ServerManagement.getAttribute(destObjectName, "DurableSubscriptionsCount");
+         assertEquals(2, count.intValue());
+         
+         count = (Integer)ServerManagement.getAttribute(destObjectName, "NonDurableSubscriptionsCount");
+         assertEquals(0, count.intValue());
+         
       }
       finally
-      {      
-         ServerManagement.undeployTopic("TopicSubscriptionListAsText");
-         ServerManagement.undeployTopic("TopicSubscription");
+      {
+         if (conn != null)
+         {
+            conn.close();
+         }
+         ServerManagement.undeployTopic("TopicSubscriptionsCount");
       }
    }
 
-   /**
-    * Test removeAllMessages().
-    * @throws Exception
-    */
-   public void testRemoveAllMessages() throws Exception
+   
+   public void testListSubscriptions() throws Exception
    {
       InitialContext ic = new InitialContext(ServerManagement.getJNDIEnvironment());
       TopicConnectionFactory cf = (JBossConnectionFactory)ic.lookup("/ConnectionFactory");
  
-      ServerManagement.deployTopic("TopicRemoveAllMessages");
+      ServerManagement.deployTopic("TopicSubscriptionList");
+      Topic topic = (Topic)ic.lookup("/topic/TopicSubscriptionList");
+
+      TopicConnection conn = null;
       
       try
       {
-         Topic topic = (Topic)ic.lookup("/topic/TopicRemoveAllMessages");
+         conn = cf.createTopicConnection();
    
-         TopicConnection conn = cf.createTopicConnection();
-   
          conn.setClientID("Client1");
    
          TopicSession s = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
+
+         // Create 2 durable subscription and 2 non-durable subscription
+         s.createDurableSubscriber(topic, "SubscriberA");
+         
+         s.createDurableSubscriber(topic, "SubscriberB", "wibble is null", false);
+         
+         s.createSubscriber(topic);
+         
+         s.createSubscriber(topic);
+         
          MessageProducer prod = s.createProducer(topic);
          prod.setDeliveryMode(DeliveryMode.PERSISTENT);
-   
-         // Create 1 durable subscription and 1 non-durable subscription
-         s.createDurableSubscriber(topic, "Durable1");
-         s.createSubscriber(topic);
          
-         // Send 1 message
-         prod.send(s.createTextMessage("First one"));         
+         // Send a couple of messages
+         TextMessage tm1 = s.createTextMessage("message1");
+         TextMessage tm2 = s.createTextMessage("message2");
          
+         prod.send(tm1);
+         prod.send(tm2);
+      
+         // There should be 4 subscriptions
          ObjectName destObjectName = 
-            new ObjectName("jboss.messaging.destination:service=Topic,name=TopicRemoveAllMessages");
-         List listMsg = (List)ServerManagement.invoke(destObjectName, 
-                  "listMessagesDurableSub",
-                  new Object[] {"Durable1", "Client1", null},
-                  new String[] {"java.lang.String", "java.lang.String", "java.lang.String"});         
-         assertEquals(1, listMsg.size());
+            new ObjectName("jboss.messaging.destination:service=Topic,name=TopicSubscriptionList");
          
-         //TODO - Why the heck isn't there a messageCount method on the subscription
-         //like there is on queue??????????
+         List list = (List)ServerManagement.invoke(destObjectName, "listAllSubscriptions", null, null);
          
-         // Start the connection for delivery
-         conn.start();
+         assertEquals(4, list.size());
          
-         // Remove all messages from the topic
+         SubscriptionInfo sub1 = (SubscriptionInfo)list.get(0);
+         SubscriptionInfo sub2 = (SubscriptionInfo)list.get(1);
+         SubscriptionInfo sub3 = (SubscriptionInfo)list.get(2);
+         SubscriptionInfo sub4 = (SubscriptionInfo)list.get(3);
          
-         //Need to pause since delivery may still be in progress
-         Thread.sleep(2000);
+         assertEquals("Client1", sub1.getClientID());
+         assertEquals(-1, sub1.getMaxSize());
+         assertEquals(2, sub1.getMessageCount());
+         assertEquals(null, sub1.getSelector());
+         assertEquals("SubscriberA", sub1.getName());
          
-         ServerManagement.invoke(destObjectName, "removeAllMessages", null, null);
-   
-         // Try to receive messages from the two subscriptions, should be null
+         assertEquals("Client1", sub2.getClientID());
+         assertEquals(-1, sub2.getMaxSize());
+         assertEquals(2, sub2.getMessageCount());
+         assertEquals("wibble is null", sub2.getSelector());
+         assertEquals("SubscriberB", sub2.getName());
          
-         listMsg = (List)ServerManagement.invoke(destObjectName, 
-                  "listMessagesDurableSub",
-                  new Object[] {"Durable1", "Client1", null},
-                  new String[] {"java.lang.String", "java.lang.String", "java.lang.String"});         
-         assertEquals(0, listMsg.size());
-                  
-         // Now close the connection
-         conn.close();
+
+         assertEquals(null, sub3.getClientID());
+         assertEquals(-1, sub3.getMaxSize());
+         assertEquals(2, sub3.getMessageCount());
+         assertEquals(null, sub3.getSelector());
+         assertEquals(null, sub3.getName());
          
-         // Connect again to the same topic
-         conn = cf.createTopicConnection();
-         conn.setClientID("Client1");
-         s = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
-         prod = s.createProducer(topic);
-         prod.setDeliveryMode(DeliveryMode.PERSISTENT);
-   
-         // Send another message
-         prod.send(s.createTextMessage("Second one"));
+         assertEquals(null, sub4.getClientID());
+         assertEquals(-1, sub4.getMaxSize());
+         assertEquals(2, sub4.getMessageCount());
+         assertEquals(null, sub4.getSelector());
+         assertEquals(null, sub4.getName());
          
-         listMsg = (List)ServerManagement.invoke(destObjectName, 
-                  "listMessagesDurableSub",
-                  new Object[] {"Durable1", "Client1", null},
-                  new String[] {"java.lang.String", "java.lang.String", "java.lang.String"});   
+         //Now the durable
          
-         assertEquals(2, listMsg.size());
+         list = (List)ServerManagement.invoke(destObjectName, "listDurableSubscriptions", null, null);
+         
+         assertEquals(2, list.size());
+         
+         sub1 = (SubscriptionInfo)list.get(0);
+         sub2 = (SubscriptionInfo)list.get(1);
 
-         // Start the connection for delivery
-         conn.start();
          
-         // Remove all messages from the topic
-         ServerManagement.invoke(destObjectName, "removeAllMessages", null, null);
-   
-         listMsg = (List)ServerManagement.invoke(destObjectName, 
-                  "listMessagesDurableSub",
-                  new Object[] {"Durable1", "Client1", null},
-                  new String[] {"java.lang.String", "java.lang.String", "java.lang.String"});         
-         assertEquals(0, listMsg.size());
+         assertEquals("Client1", sub1.getClientID());
+         assertEquals(-1, sub1.getMaxSize());
+         assertEquals(2, sub1.getMessageCount());
+         assertEquals(null, sub1.getSelector());
+         assertEquals("SubscriberA", sub1.getName());
          
-         // Clean-up
-         conn.close();
+         assertEquals("Client1", sub2.getClientID());
+         assertEquals(-1, sub2.getMaxSize());
+         assertEquals(2, sub2.getMessageCount());
+         assertEquals("wibble is null", sub2.getSelector());
+         assertEquals("SubscriberB", sub2.getName());
+         
+         //and the non durable
+         
+         list = (List)ServerManagement.invoke(destObjectName, "listNonDurableSubscriptions", null, null);
+         
+         assertEquals(2, list.size());
+         
+         sub3 = (SubscriptionInfo)list.get(0);
+         sub4 = (SubscriptionInfo)list.get(1);
+         
+         assertEquals(null, sub3.getClientID());
+         assertEquals(-1, sub3.getMaxSize());
+         assertEquals(2, sub3.getMessageCount());
+         assertEquals(null, sub3.getSelector());
+         assertEquals(null, sub3.getName());
+         
+         assertEquals(null, sub4.getClientID());
+         assertEquals(-1, sub4.getMaxSize());
+         assertEquals(2, sub4.getMessageCount());
+         assertEquals(null, sub4.getSelector());
+         assertEquals(null, sub4.getName());
+         
+         
       }
       finally
-      {         
-         ServerManagement.undeployTopic("TopicRemoveAllMessages");
+      {
+         if (conn != null)
+         {
+            conn.close();
+         }
+      
+         ServerManagement.undeployTopic("TopicSubscriptionList");
       }
    }
-  
-   public void testListMessages() throws Exception
+   
+
+   public void testListSubscriptionsAsHTML() throws Exception
    {
-      ServerManagement.deployTopic("TopicSubscriptionListAsText");
-      
       InitialContext ic = new InitialContext(ServerManagement.getJNDIEnvironment());
       TopicConnectionFactory cf = (JBossConnectionFactory)ic.lookup("/ConnectionFactory");
  
-      ServerManagement.deployTopic("TopicMessageList");
+      ServerManagement.deployTopic("TopicSubscriptionList");
+      Topic topic = (Topic)ic.lookup("/topic/TopicSubscriptionList");
+
+      TopicConnection conn = null;
       
       try
       {
-         Topic topic = (Topic)ic.lookup("/topic/TopicMessageList");
+         conn = cf.createTopicConnection();
    
-         TopicConnection conn = cf.createTopicConnection();
-   
          conn.setClientID("Client1");
    
          TopicSession s = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
-         MessageProducer prod = s.createProducer(topic);
-         prod.setDeliveryMode(DeliveryMode.PERSISTENT);
-   
-         // Create 1 durable subscription and 2 non-durable subscription
+
+         // Create 2 durable subscription and 2 non-durable subscription
          s.createDurableSubscriber(topic, "SubscriberA");
          
+         s.createDurableSubscriber(topic, "SubscriberB", "wibble is null", false);
+         
          s.createSubscriber(topic);
+         
          s.createSubscriber(topic);
          
-         // Send 1 message
-         prod.send(s.createTextMessage("First one"));
+         MessageProducer prod = s.createProducer(topic);
+         prod.setDeliveryMode(DeliveryMode.PERSISTENT);
          
-         // Start the connection for delivery
-         conn.start();
-   
-         // There should be 3 subscriptions
+         // Send a couple of messages
+         TextMessage tm1 = s.createTextMessage("message1");
+         TextMessage tm2 = s.createTextMessage("message2");
+         
+         prod.send(tm1);
+         prod.send(tm2);
+      
+         // There should be 4 subscriptions
          ObjectName destObjectName = 
-            new ObjectName("jboss.messaging.destination:service=Topic,name=TopicMessageList");
+            new ObjectName("jboss.messaging.destination:service=Topic,name=TopicSubscriptionList");
          
-         ServerManagement.invoke(destObjectName, "listSubscriptionsAsText", null, null);
+         String html = (String)ServerManagement.invoke(destObjectName, "listAllSubscriptionsAsHTML", null, null);
          
+         assertTrue(html.startsWith("<table width=\"100%\" border=\"1\" cellpadding=\"1\" cellspacing=\"1\">"));
+         assertTrue(html.endsWith("</table>"));
          
-         // Note that listing the messages ONLY list those ones not in the process of delivery
-         // Therefore the following is invalid
+         assertTrue(html.indexOf("SubscriberA") != -1);
+         assertTrue(html.indexOf("Client1") != -1);
+         assertTrue(html.indexOf("SubscriberB") != -1);
+         assertTrue(html.indexOf("wibble is null") != -1);
          
          
-         // Send another message
-         prod.send(s.createTextMessage("Second one"));
-                  
+         //Now the durable
          
-         List listMsg = (List)ServerManagement.invoke(destObjectName, 
-                  "listMessagesDurableSub",
-                  new Object[] {"SubscriberA", "", null},
-                  new String[] {"java.lang.String", "java.lang.String", "java.lang.String"});
-         assertEquals(0, listMsg.size());
-            
-         conn.close();
+         html = (String)ServerManagement.invoke(destObjectName, "listDurableSubscriptionsAsHTML", null, null);
          
-         listMsg = (List)ServerManagement.invoke(destObjectName, 
-               "listMessagesDurableSub",
-               new Object[] {"SubscriberA", "", null},
-               new String[] {"java.lang.String", "java.lang.String", "java.lang.String"});
-         assertEquals(2, listMsg.size());
-         assertTrue(listMsg.get(0) instanceof TextMessage);
-         assertTrue(listMsg.get(1) instanceof TextMessage);
-         assertEquals(((TextMessage)listMsg.get(0)).getText(), "First one");
-         assertEquals(((TextMessage)listMsg.get(1)).getText(), "Second one");
+         assertTrue(html.startsWith("<table width=\"100%\" border=\"1\" cellpadding=\"1\" cellspacing=\"1\">"));
+         assertTrue(html.endsWith("</table>"));
          
+         assertTrue(html.indexOf("SubscriberA") != -1);
+         assertTrue(html.indexOf("Client1") != -1);
+         assertTrue(html.indexOf("SubscriberB") != -1);
+         assertTrue(html.indexOf("wibble is null") != -1);
+         
+         // Now the non durable
+         
+         html = (String)ServerManagement.invoke(destObjectName, "listNonDurableSubscriptionsAsHTML", null, null);
+         
+         assertTrue(html.startsWith("<table width=\"100%\" border=\"1\" cellpadding=\"1\" cellspacing=\"1\">"));
+         assertTrue(html.endsWith("</table>"));
+         
+         assertFalse(html.indexOf("SubscriberA") != -1);
+         assertFalse(html.indexOf("Client1") != -1);
+         assertFalse(html.indexOf("SubscriberB") != -1);
+         assertFalse(html.indexOf("wibble is null") != -1);
+                
       }
       finally
       {
-         ServerManagement.undeployTopic("TopicMessageList");
+         if (conn != null)
+         {
+            conn.close();
+         }
       
-         ServerManagement.undeployTopic("TopicSubscriptionListAsText");
+         ServerManagement.undeployTopic("TopicSubscriptionList");
       }
    }
-
-//   /*
-//    * XXX Placeholder
-//    * 
-//   public void testListMessages() throws Exception
-//   {
-//      InitialContext ic = new InitialContext(ServerManagement.getJNDIEnvironment());
-//      TopicConnectionFactory cf = (JBossConnectionFactory)ic.lookup("/ConnectionFactory");
-// 
-//      ServerManagement.deployTopic("TopicMessageList");
-//      Topic topic = (Topic)ic.lookup("/topic/TopicMessageList");
-//
-//      TopicConnection conn = cf.createTopicConnection();
-//
-//      conn.setClientID("Client1");
-//
-//      TopicSession s = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
-//      MessageProducer prod = s.createProducer(topic);
-//      prod.setDeliveryMode(DeliveryMode.PERSISTENT);
-//
-//      // Create 1 durable subscription and 2 non-durable subscription
-//      s.createDurableSubscriber(topic, "SubscriberA");
-//      
-//      s.createSubscriber(topic);
-//      s.createSubscriber(topic);
-//      
-//      // Send 1 message
-//      prod.send(s.createTextMessage("First one"));
-//      
-//      // Start the connection for delivery
-//      conn.start();
-//
-//      // There should be 3 subscriptions
-//      ObjectName destObjectName = 
-//         new ObjectName("jboss.messaging.destination:service=Topic,name=TopicMessageList");
-//      List listSub = (List)ServerManagement.invoke(destObjectName, "listSubscriptions", null, null);
-//      assertEquals(3, listSub.size());
-//      // Each subscription will have the same message
-//      for (int i = 0; i < 3; i++)
-//      {
-//         String[] strs = (String[])listSub.get(i);
-//         List listMsg = (List)ServerManagement.invoke(destObjectName, 
-//               "listMessages",
-//               new Object[] {new Long(strs[0]), strs[1], strs[2], null},
-//               new String[] {"long", "java.lang.String", "java.lang.String", "java.lang.String"});
-//         assertEquals(1, listMsg.size());
-//         assertTrue(listMsg.get(0) instanceof TextMessage);
-//         assertEquals(((TextMessage)listMsg.get(0)).getText(), "First one");
-//      }
-//
-//      // Send another message
-//      prod.send(s.createTextMessage("Second one"));
-//
-//      // There should be 1 durable subscription
-//      List duraListSub = (List)ServerManagement.invoke(
-//            destObjectName, 
-//            "listSubscriptions", 
-//            new Object[] {Boolean.TRUE}, 
-//            new String[] {"boolean"});
-//      assertEquals(1, duraListSub.size());
-//      String[] strs = (String[])duraListSub.get(0);
-//      // The durable subscription has 2 messages
-//      List listMsg = (List)ServerManagement.invoke(destObjectName, 
-//            "listMessages",
-//            new Object[] {new Long(strs[0]), strs[1], strs[2], null},
-//            new String[] {"long", "java.lang.String", "java.lang.String", "java.lang.String"});
-//      assertEquals(2, listMsg.size());
-//      assertTrue(listMsg.get(0) instanceof TextMessage);
-//      assertTrue(listMsg.get(1) instanceof TextMessage);
-//      assertEquals(((TextMessage)listMsg.get(0)).getText(), "First one");
-//      assertEquals(((TextMessage)listMsg.get(1)).getText(), "Second one");
-//      
-//      // Clean-up
-//      conn.close();
-//      ServerManagement.undeployTopic("TopicMessageList");
-//   }
-//   */
-//   
-   /**
-    * The jmx-console has the habit of sending an empty string if no argument is specified, so
-    * we test this eventuality.
-    */
-   public void testListMessagesEmptySelector() throws Exception
-   {
-      ServerManagement.deployTopic("TopicMessageList");
-      
+   
+  
+   public void testListMessages() throws Exception
+   {   
       InitialContext ic = new InitialContext(ServerManagement.getJNDIEnvironment());
       TopicConnectionFactory cf = (JBossConnectionFactory)ic.lookup("/ConnectionFactory");
-
-      ServerManagement.deployTopic("TopicMessageList2");
+ 
+      ServerManagement.deployTopic("TopicMessageList");
       
+      TopicConnection conn = null;
+      
       try
       {
-         Topic topic = (Topic)ic.lookup("/topic/TopicMessageList2");
+         Topic topic = (Topic)ic.lookup("/topic/TopicMessageList");
    
-         TopicConnection conn = cf.createTopicConnection();
+         conn = cf.createTopicConnection();
+   
          conn.setClientID("Client1");
+   
          TopicSession s = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
+         MessageProducer prod = s.createProducer(topic);
+         prod.setDeliveryMode(DeliveryMode.PERSISTENT);
    
-         s.createDurableSubscriber(topic, "SubscriberA");
+         MessageConsumer cons = s.createDurableSubscriber(topic, "SubscriberA");
+         
+         // Send some persistent message
+         TextMessage tm1 = s.createTextMessage("message1");
+         tm1.setStringProperty("vegetable", "parsnip");
+         TextMessage tm2 = s.createTextMessage("message2");
+         tm2.setStringProperty("vegetable", "parsnip");
+         TextMessage tm3 = s.createTextMessage("message3");
+         tm3.setStringProperty("vegetable", "parsnip");
+         prod.send(tm1);
+         prod.send(tm2);
+         prod.send(tm3);
+         
+         // and some non persistent with a selector
+         prod.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
+         
+         TextMessage tm4 = s.createTextMessage("message4");
+         tm4.setStringProperty("vegetable", "artichoke");
+         TextMessage tm5 = s.createTextMessage("message5");
+         tm5.setStringProperty("vegetable", "artichoke");
+         TextMessage tm6 = s.createTextMessage("message6");
+         tm6.setStringProperty("vegetable", "artichoke");
+         prod.send(tm4);
+         prod.send(tm5);
+         prod.send(tm6);
+         
+         // Start the connection for delivery
+         conn.start();
    
-         ObjectName topicON =
-            new ObjectName("jboss.messaging.destination:service=Topic,name=TopicMessageList2");
-   
-         List messages = (List)ServerManagement.invoke(topicON,
-               "listMessagesDurableSub",
-               new Object[] {"SubscriberA", "Client1", ""},
-               new String[] {"java.lang.String", "java.lang.String", "java.lang.String"});
-         assertTrue(messages.isEmpty());
+         // There should be 1 subscription
+         ObjectName destObjectName = 
+            new ObjectName("jboss.messaging.destination:service=Topic,name=TopicMessageList");
          
-         messages = (List)ServerManagement.invoke(topicON,
-               "listMessagesDurableSub",
-               new Object[] {"SubscriberA", "Client1", "                   "},
-               new String[] {"java.lang.String", "java.lang.String", "java.lang.String"});
-         assertTrue(messages.isEmpty());
-   
-         // Clean-up
-         conn.close();
+         List durableSubs = (List)ServerManagement.invoke(destObjectName, "listDurableSubscriptions", null, null);
+         
+         assertNotNull(durableSubs);
+         assertEquals(1, durableSubs.size());
+         
+         
+         //Note that listing messages DOES NOT list messages that are in the process of being delivered
+         //or scheduled
+         
+         //so we need to close the consumers otherwise the messages will be buffered in them and not
+         //visible
+         
+         cons.close();
+         
+         //Give time for cancel to occur
+         Thread.sleep(500);
+         
+         String sub1Id = ((SubscriptionInfo)durableSubs.get(0)).getId();
+                
+         List allMsgs = (List)ServerManagement.invoke(destObjectName, "listAllMessages", new Object[] { sub1Id }, new String[] { "java.lang.String" });
+         
+         assertNotNull(allMsgs);         
+         assertEquals(6, allMsgs.size());
+         
+         TextMessage rm1 = (TextMessage)allMsgs.get(0);
+         TextMessage rm2 = (TextMessage)allMsgs.get(1);
+         TextMessage rm3 = (TextMessage)allMsgs.get(2);
+         TextMessage rm4 = (TextMessage)allMsgs.get(3);
+         TextMessage rm5 = (TextMessage)allMsgs.get(4);
+         TextMessage rm6 = (TextMessage)allMsgs.get(5);
+         
+         assertEquals(tm1.getText(), rm1.getText());
+         assertEquals(tm2.getText(), rm2.getText());
+         assertEquals(tm3.getText(), rm3.getText());
+         assertEquals(tm4.getText(), rm4.getText());
+         assertEquals(tm5.getText(), rm5.getText());
+         assertEquals(tm6.getText(), rm6.getText());
+         
+         assertTrue(rm1.getJMSDeliveryMode() == DeliveryMode.PERSISTENT);
+         assertTrue(rm2.getJMSDeliveryMode() == DeliveryMode.PERSISTENT);
+         assertTrue(rm3.getJMSDeliveryMode() == DeliveryMode.PERSISTENT);         
+         assertTrue(rm4.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT);
+         assertTrue(rm5.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT);
+         assertTrue(rm6.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT);
+         
+         List durMsgs = (List)ServerManagement.invoke(destObjectName, "listDurableMessages", new Object[] { sub1Id }, new String[] { "java.lang.String" });
+         
+         assertNotNull(durMsgs);         
+         assertEquals(3, durMsgs.size());
+         
+         rm1 = (TextMessage)durMsgs.get(0);
+         rm2 = (TextMessage)durMsgs.get(1);
+         rm3 = (TextMessage)durMsgs.get(2);
+                
+         assertEquals(tm1.getText(), rm1.getText());
+         assertEquals(tm2.getText(), rm2.getText());
+         assertEquals(tm3.getText(), rm3.getText());
+         
+         assertTrue(rm1.getJMSDeliveryMode() == DeliveryMode.PERSISTENT);
+         assertTrue(rm2.getJMSDeliveryMode() == DeliveryMode.PERSISTENT);
+         assertTrue(rm3.getJMSDeliveryMode() == DeliveryMode.PERSISTENT);                 
+         
+         
+         List nondurMsgs = (List)ServerManagement.invoke(destObjectName, "listNonDurableMessages", new Object[] { sub1Id }, new String[] { "java.lang.String" });
+         
+         assertNotNull(nondurMsgs);         
+         assertEquals(3, nondurMsgs.size());
+               
+         rm4 = (TextMessage)nondurMsgs.get(0);
+         rm5 = (TextMessage)nondurMsgs.get(1);
+         rm6 = (TextMessage)nondurMsgs.get(2);
+                 
+         assertEquals(tm4.getText(), rm4.getText());
+         assertEquals(tm5.getText(), rm5.getText());
+         assertEquals(tm6.getText(), rm6.getText());
+             
+         assertTrue(rm4.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT);
+         assertTrue(rm5.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT);
+         assertTrue(rm6.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT);
+         
+         //Now with a selector
+         
+         String sel = "vegetable='artichoke'";
+         
+         allMsgs = (List)ServerManagement.invoke(destObjectName, "listAllMessages", new Object[] { sub1Id, sel }, new String[] { "java.lang.String", "java.lang.String" });
+         
+         assertNotNull(allMsgs);         
+         assertEquals(3, allMsgs.size());
+         
+         rm4 = (TextMessage)allMsgs.get(0);
+         rm5 = (TextMessage)allMsgs.get(1);
+         rm6 = (TextMessage)allMsgs.get(2);
+         
+         assertEquals(tm4.getText(), rm4.getText());
+         assertEquals(tm5.getText(), rm5.getText());
+         assertEquals(tm6.getText(), rm6.getText());
+            
+         assertTrue(rm4.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT);
+         assertTrue(rm5.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT);
+         assertTrue(rm6.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT);
+                  
+         durMsgs = (List)ServerManagement.invoke(destObjectName, "listDurableMessages", new Object[] { sub1Id, sel }, new String[] { "java.lang.String" , "java.lang.String" });
+         
+         assertNotNull(durMsgs);         
+         assertEquals(0, durMsgs.size());
+         
+         
+         nondurMsgs = (List)ServerManagement.invoke(destObjectName, "listNonDurableMessages", new Object[] { sub1Id, sel }, new String[] { "java.lang.String", "java.lang.String" });
+         
+         assertNotNull(nondurMsgs);         
+         assertEquals(3, nondurMsgs.size());
+               
+         rm4 = (TextMessage)nondurMsgs.get(0);
+         rm5 = (TextMessage)nondurMsgs.get(1);
+         rm6 = (TextMessage)nondurMsgs.get(2);
+                 
+         assertEquals(tm4.getText(), rm4.getText());
+         assertEquals(tm5.getText(), rm5.getText());
+         assertEquals(tm6.getText(), rm6.getText());
+             
+         assertTrue(rm4.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT);
+         assertTrue(rm5.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT);
+         assertTrue(rm6.getJMSDeliveryMode() == DeliveryMode.NON_PERSISTENT);                  
+         
       }
       finally
       {
-         ServerManagement.undeployTopic("TopicMessageList2");
+         if (conn != null)
+         {
+            conn.close();
+         }
+         
          ServerManagement.undeployTopic("TopicMessageList");
+      
       }
    }
 
+
+
    // Package protected ---------------------------------------------
    
    // Protected -----------------------------------------------------

Modified: trunk/tests/src/org/jboss/test/messaging/jms/server/destination/base/DestinationManagementTestBase.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/jms/server/destination/base/DestinationManagementTestBase.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/jms/server/destination/base/DestinationManagementTestBase.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -21,10 +21,15 @@
   */
 package org.jboss.test.messaging.jms.server.destination.base;
 
+import java.util.List;
 import java.util.Set;
 
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
 import javax.jms.Destination;
+import javax.jms.MessageConsumer;
 import javax.jms.Queue;
+import javax.jms.Session;
 import javax.jms.Topic;
 import javax.management.ObjectName;
 import javax.naming.InitialContext;
@@ -34,8 +39,7 @@
 import org.jboss.jms.destination.JBossQueue;
 import org.jboss.jms.destination.JBossTopic;
 import org.jboss.jms.server.destination.ManagedDestination;
-import org.jboss.jms.server.destination.ManagedQueue;
-import org.jboss.jms.server.destination.ManagedTopic;
+import org.jboss.jms.server.messagecounter.MessageCounter;
 import org.jboss.jms.util.XMLUtil;
 import org.jboss.test.messaging.MessagingTestCase;
 import org.jboss.test.messaging.tools.ServerManagement;
@@ -57,6 +61,8 @@
    // Static --------------------------------------------------------
    
    // Attributes ----------------------------------------------------
+   
+   protected InitialContext initialContext;
 
    // Constructors --------------------------------------------------
 
@@ -75,9 +81,9 @@
       }
 
       super.setUp();
-      ServerManagement.start("all");
+      ServerManagement.start("all");   
       
-      
+      initialContext = new InitialContext(ServerManagement.getJNDIEnvironment());
    }
 
    public void tearDown() throws Exception
@@ -292,7 +298,7 @@
    }
 
 
-   public void testDeployDestinationProgramatically() throws Exception
+   public void testDeployDestinationProgrammatically() throws Exception
    {
       ObjectName serverPeerObjectName = ServerManagement.getServerPeerObjectName();
 
@@ -360,7 +366,7 @@
 
    }
    
-   public void testDeployDestinationProgramaticallyWithParams() throws Exception
+   public void testDeployDestinationProgrammaticallyWithParams() throws Exception
    {
       ObjectName serverPeerObjectName = ServerManagement.getServerPeerObjectName();
 
@@ -542,6 +548,70 @@
 
       undeployDestination("PageableAttributes");
    }
+   
+   public void testGetSetMessageCounterHistoryDayLimit() throws Exception
+   {
+      int defaultLimit = 12;
+      
+      ServerManagement.setAttribute(ServerManagement.getServerPeerObjectName(), "DefaultMessageCounterHistoryDayLimit", String.valueOf(defaultLimit));
+      
+      ServerManagement.deployQueue("testQueue");
+      
+      ServerManagement.deployTopic("testTopic");
+      
+      Connection conn = null;
+      
+      try
+      {         
+         Queue testQueue = (Queue)initialContext.lookup("/queue/testQueue");
+         
+         Topic testTopic = (Topic)initialContext.lookup("/topic/testTopic");
+               
+         String queueON = "jboss.messaging.destination:service=Queue,name=testQueue";
+         
+         String topicON = "jboss.messaging.destination:service=Topic,name=testTopic";
+            
+         MessageCounter queueCounter = (MessageCounter)ServerManagement.getAttribute(new ObjectName(queueON), "MessageCounter");
+         
+         assertEquals(defaultLimit, queueCounter.getHistoryLimit());
+         
+         ConnectionFactory cf = (ConnectionFactory)initialContext.lookup("/ConnectionFactory");
+         
+         conn = cf.createConnection();
+         
+         Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+         
+         MessageConsumer sub = sess.createConsumer(testTopic);
+         
+         List counters = (List)ServerManagement.getAttribute(new ObjectName(topicON), "MessageCounters");
+         
+         assertNotNull(counters);
+         
+         assertEquals(1, counters.size());
+         
+         MessageCounter subCounter = (MessageCounter)counters.get(0);
+         
+         assertEquals(defaultLimit, subCounter.getHistoryLimit());
+         
+         int overrideLimit = 777;
+         
+         ServerManagement.setAttribute(new ObjectName(queueON), "MessageCounterHistoryDayLimit", String.valueOf(overrideLimit));
+         
+         ServerManagement.setAttribute(new ObjectName(topicON), "MessageCounterHistoryDayLimit", String.valueOf(overrideLimit));
+         
+         assertEquals(overrideLimit, queueCounter.getHistoryLimit());
+         
+         assertEquals(overrideLimit, subCounter.getHistoryLimit());
+      }
+      finally
+      {
+         if (conn != null) conn.close();
+         
+         ServerManagement.undeployQueue("testQueue");
+         
+         ServerManagement.undeployTopic("testTopic");
+      }                    
+   }
 
    // Package protected ---------------------------------------------
    

Modified: trunk/tests/src/org/jboss/test/messaging/tools/jmx/ClassLoaderJMXWrapper.java
===================================================================
--- trunk/tests/src/org/jboss/test/messaging/tools/jmx/ClassLoaderJMXWrapper.java	2007-01-09 17:37:07 UTC (rev 1929)
+++ trunk/tests/src/org/jboss/test/messaging/tools/jmx/ClassLoaderJMXWrapper.java	2007-01-09 18:16:04 UTC (rev 1930)
@@ -21,6 +21,7 @@
 */
 package org.jboss.test.messaging.tools.jmx;
 
+import java.lang.reflect.Array;
 import java.net.URLClassLoader;
 import java.net.URL;
 
@@ -56,7 +57,24 @@
 
    public Class loadClass(String name) throws ClassNotFoundException
    {
-      return delegate.loadClass(name);
+      if (name.endsWith("[]"))
+      {
+         name = name.substring(0, name.length() - 2);
+         
+         //The classloader of an array type is the classloader of it's element (if non primitive)
+         
+         Class cl = delegate.loadClass(name);
+         
+         Object arr = Array.newInstance(cl, 0);
+         
+         Class arrayClass = arr.getClass();
+         
+         return arrayClass;
+      }
+      else
+      {      
+         return delegate.loadClass(name);
+      }
    }
 
    // ClassLoader overrides -----------------------------------------




More information about the jboss-cvs-commits mailing list